- Added downlink reference mode option r <mode> [ 0 - (or missing) default/fixed bit, 1 - long leading, 2 - leading 0 and 3 - 1 of 4 ] to `lf t55xx detect`, `lf t55xx read`, `lf t55xx write`, and `lf t55xx bruteforce`
- Added special option `r 4` to bruteforce, to try all downlink modes (0,1,2 and 3) for each password
- `hf mfu info` now checks the NXP Originality Signature if availabe (piwi)
+- Added `hf mf personalize` to personalize the UID option of Mifare Classic EV1 cards (piwi)
## [v3.1.0][2018-10-10]
#include "iso15693.h"
#include "lfsampling.h"
#include "BigBuf.h"
+#include "mifarecmd.h"
#include "mifareutil.h"
#include "mifaresim.h"
#include "pcf7931.h"
case CMD_MIFARE_WRITEBL:
MifareWriteBlock(c->arg[0], c->arg[1], c->arg[2], c->d.asBytes);
break;
+ case CMD_MIFARE_PERSONALIZE_UID:
+ MifarePersonalizeUID(c->arg[0], c->arg[1], c->d.asBytes);
+ break;
//case CMD_MIFAREU_WRITEBL_COMPAT:
//MifareUWriteBlockCompat(c->arg[0], c->d.asBytes);
//break;
#include <stddef.h>
#include "common.h"
#include "usb_cmd.h"
-#include "hitag2.h"
#include "hitagS.h"
#include "mifare.h"
#include "../common/crc32.h"
void EPA_PACE_Collect_Nonce(UsbCommand * c);
void EPA_PACE_Replay(UsbCommand *c);
-// mifarecmd.h
-void MifareReadBlock(uint8_t arg0, uint8_t arg1, uint8_t arg2, uint8_t *data);
-void MifareUReadBlock(uint8_t arg0, uint8_t arg1, uint8_t *datain);
-void MifareUC_Auth(uint8_t arg0, uint8_t *datain);
-void MifareUReadCard(uint8_t arg0, uint16_t arg1, uint8_t arg2, uint8_t *datain);
-void MifareReadSector(uint8_t arg0, uint8_t arg1, uint8_t arg2, uint8_t *datain);
-void MifareWriteBlock(uint8_t arg0, uint8_t arg1, uint8_t arg2, uint8_t *datain);
-//void MifareUWriteBlockCompat(uint8_t arg0,uint8_t *datain);
-void MifareUWriteBlock(uint8_t arg0, uint8_t arg1, uint8_t *datain);
-void MifareNested(uint32_t arg0, uint32_t arg1, uint32_t arg2, uint8_t *datain);
-void MifareAcquireEncryptedNonces(uint32_t arg0, uint32_t arg1, uint32_t flags, uint8_t *datain);
-void MifareChkKeys(uint16_t arg0, uint16_t arg1, uint8_t arg2, uint8_t *datain);
-void MifareSetDbgLvl(uint32_t arg0, uint32_t arg1, uint32_t arg2, uint8_t *datain);
-void MifareEMemClr(uint32_t arg0, uint32_t arg1, uint32_t arg2, uint8_t *datain);
-void MifareEMemSet(uint32_t arg0, uint32_t arg1, uint32_t arg2, uint8_t *datain);
-void MifareEMemGet(uint32_t arg0, uint32_t arg1, uint32_t arg2, uint8_t *datain);
-void MifareECardLoad(uint32_t arg0, uint32_t arg1, uint32_t arg2, uint8_t *datain);
-void MifareCWipe(uint32_t arg0, uint32_t arg1, uint32_t arg2, uint8_t *datain); // Work with "magic Chinese" card
-void MifareCSetBlock(uint32_t arg0, uint32_t arg1, uint32_t arg2, uint8_t *datain);
-void MifareCGetBlock(uint32_t arg0, uint32_t arg1, uint32_t arg2, uint8_t *datain);
-void MifareCIdent(); // is "magic chinese" card?
-void MifareUSetPwd(uint8_t arg0, uint8_t *datain);
-
-//desfire
-void Mifare_DES_Auth1(uint8_t arg0,uint8_t *datain);
-void Mifare_DES_Auth2(uint32_t arg0, uint8_t *datain);
-
// mifaredesfire.h
-bool InitDesfireCard();
-void MifareSendCommand(uint8_t arg0,uint8_t arg1, uint8_t *datain);
-void MifareDesfireGetInformation();
-void MifareDES_Auth1(uint8_t arg0,uint8_t arg1,uint8_t arg2, uint8_t *datain);
-void ReaderMifareDES(uint32_t param, uint32_t param2, uint8_t * datain);
-int DesfireAPDU(uint8_t *cmd, size_t cmd_len, uint8_t *dataout);
-size_t CreateAPDU( uint8_t *datain, size_t len, uint8_t *dataout);
+bool InitDesfireCard();
+void MifareSendCommand(uint8_t arg0,uint8_t arg1, uint8_t *datain);
+void MifareDesfireGetInformation();
+void MifareDES_Auth1(uint8_t arg0,uint8_t arg1,uint8_t arg2, uint8_t *datain);
+void ReaderMifareDES(uint32_t param, uint32_t param2, uint8_t * datain);
+int DesfireAPDU(uint8_t *cmd, size_t cmd_len, uint8_t *dataout);
+size_t CreateAPDU( uint8_t *datain, size_t len, uint8_t *dataout);
// cmd.h
bool cmd_receive(UsbCommand* cmd);
#include "hitag2.h"
#include "proxmark3.h"
+#include "cmd.h"
#include "apps.h"
#include "util.h"
#include "hitag.h"
#include "string.h"
#include "BigBuf.h"
#include "fpgaloader.h"
+#include "protocols.h"
static bool bQuiet;
TAG_STATE_WRITING = 0x04, // In write command, awaiting sector contents to be written
} state;
unsigned int active_sector;
- byte_t crypto_active;
+ uint8_t crypto_active;
uint64_t cs;
- byte_t sectors[12][4];
+ uint8_t sectors[12][4];
};
static struct hitag2_tag tag = {
// 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.
#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_len = AUTH_TABLE_LENGTH;
-static byte_t password[4];
-static byte_t NrAr[8];
-static byte_t key[8];
-static byte_t writedata[4];
+static uint8_t password[4];
+static uint8_t NrAr[8];
+static uint8_t key[8];
+static uint8_t writedata[4];
static uint64_t cipher_state;
/* Following is a modified version of cryptolib.com/ciphers/hitag2/ */
// No warranties or guarantees of any kind.
// This code is released into the public domain by its author.
-// Basic macros:
-
-#define u8 uint8_t
-#define u32 uint32_t
-#define u64 uint64_t
-#define rev8(x) ((((x)>>7)&1)+((((x)>>6)&1)<<1)+((((x)>>5)&1)<<2)+((((x)>>4)&1)<<3)+((((x)>>3)&1)<<4)+((((x)>>2)&1)<<5)+((((x)>>1)&1)<<6)+(((x)&1)<<7))
-#define rev16(x) (rev8 (x)+(rev8 (x>> 8)<< 8))
-#define rev32(x) (rev16(x)+(rev16(x>>16)<<16))
-#define rev64(x) (rev32(x)+(rev32(x>>32)<<32))
-#define bit(x,n) (((x)>>(n))&1)
-#define bit32(x,n) ((((x)[(n)>>5])>>((n)))&1)
-#define inv32(x,i,n) ((x)[(i)>>5]^=((u32)(n))<<((i)&31))
-#define rotl64(x, n) ((((u64)(x))<<((n)&63))+(((u64)(x))>>((0-(n))&63)))
-
// Single bit Hitag2 functions:
-#define i4(x,a,b,c,d) ((u32)((((x)>>(a))&1)+(((x)>>(b))&1)*2+(((x)>>(c))&1)*4+(((x)>>(d))&1)*8))
+#define i4(x,a,b,c,d) ((uint32_t)((((x)>>(a))&1)+(((x)>>(b))&1)*2+(((x)>>(c))&1)*4+(((x)>>(d))&1)*8))
-static const u32 ht2_f4a = 0x2C79; // 0010 1100 0111 1001
-static const u32 ht2_f4b = 0x6671; // 0110 0110 0111 0001
-static const u32 ht2_f5c = 0x7907287B; // 0111 1001 0000 0111 0010 1000 0111 1011
+static const uint32_t ht2_f4a = 0x2C79; // 0010 1100 0111 1001
+static const uint32_t ht2_f4b = 0x6671; // 0110 0110 0111 0001
+static const uint32_t ht2_f5c = 0x7907287B; // 0111 1001 0000 0111 0010 1000 0111 1011
-static u32 _f20 (const u64 x)
-{
- u32 i5;
+static uint32_t _f20(const uint64_t x) {
+ uint32_t i5;
- i5 = ((ht2_f4a >> i4 (x, 1, 2, 4, 5)) & 1)* 1
- + ((ht2_f4b >> i4 (x, 7,11,13,14)) & 1)* 2
- + ((ht2_f4b >> i4 (x,16,20,22,25)) & 1)* 4
- + ((ht2_f4b >> i4 (x,27,28,30,32)) & 1)* 8
- + ((ht2_f4a >> i4 (x,33,42,43,45)) & 1)*16;
+ i5 = ((ht2_f4a >> i4(x, 1, 2, 4, 5)) & 1) * 1
+ + ((ht2_f4b >> i4(x, 7,11,13,14)) & 1) * 2
+ + ((ht2_f4b >> i4(x,16,20,22,25)) & 1) * 4
+ + ((ht2_f4b >> i4(x,27,28,30,32)) & 1) * 8
+ + ((ht2_f4a >> i4(x,33,42,43,45)) & 1) * 16;
return (ht2_f5c >> i5) & 1;
}
-static u64 _hitag2_init (const u64 key, const u32 serial, const u32 IV)
-{
- u32 i;
- u64 x = ((key & 0xFFFF) << 32) + serial;
+static uint64_t _hitag2_init(const uint64_t key, const uint32_t serial, const uint32_t IV) {
+ uint32_t i;
+ uint64_t x = ((key & 0xFFFF) << 32) + serial;
- for (i = 0; i < 32; i++)
- {
+ for (i = 0; i < 32; i++) {
x >>= 1;
- x += (u64) (_f20 (x) ^ (((IV >> i) ^ (key >> (i+16))) & 1)) << 47;
+ x += (uint64_t)(_f20(x) ^ (((IV >> i) ^ (key >> (i+16))) & 1)) << 47;
}
return x;
}
-static u64 _hitag2_round (u64 *state)
-{
- u64 x = *state;
+static uint64_t _hitag2_round(uint64_t *state) {
+ uint64_t x = *state;
x = (x >> 1) +
((((x >> 0) ^ (x >> 2) ^ (x >> 3) ^ (x >> 6)
^ (x >> 42) ^ (x >> 43) ^ (x >> 46) ^ (x >> 47)) & 1) << 47);
*state = x;
- return _f20 (x);
+ return _f20(x);
}
-static u32 _hitag2_byte (u64 * x)
-{
- u32 i, c;
-
- for (i = 0, c = 0; i < 8; i++) c += (u32) _hitag2_round (x) << (i^7);
+static uint32_t _hitag2_byte(uint64_t *x) {
+ uint32_t i, c;
+ for (i = 0, c = 0; i < 8; i++) {
+ c += (uint32_t) _hitag2_round(x) << (i^7);
+ }
return c;
}
-static int hitag2_reset(void)
-{
+static int hitag2_reset(void) {
tag.state = TAG_STATE_RESET;
tag.crypto_active = 0;
return 0;
}
-static int hitag2_init(void)
-{
-// memcpy(&tag, &resetdata, sizeof(tag));
+static int hitag2_init(void) {
hitag2_reset();
return 0;
}
-static void hitag2_cipher_reset(struct hitag2_tag *tag, const byte_t *iv)
-{
- uint64_t key = ((uint64_t)tag->sectors[2][2]) |
+static void hitag2_cipher_reset(struct hitag2_tag *tag, const uint8_t *iv) {
+ uint64_t key = ((uint64_t)tag->sectors[2][2]) |
((uint64_t)tag->sectors[2][3] << 8) |
((uint64_t)tag->sectors[1][0] << 16) |
((uint64_t)tag->sectors[1][1] << 24) |
((uint64_t)tag->sectors[1][2] << 32) |
((uint64_t)tag->sectors[1][3] << 40);
- uint32_t uid = ((uint32_t)tag->sectors[0][0]) |
+ uint32_t uid = ((uint32_t)tag->sectors[0][0]) |
((uint32_t)tag->sectors[0][1] << 8) |
((uint32_t)tag->sectors[0][2] << 16) |
((uint32_t)tag->sectors[0][3] << 24);
(((uint32_t)(iv[1])) << 8) |
(((uint32_t)(iv[2])) << 16) |
(((uint32_t)(iv[3])) << 24);
- 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)
-{
- byte_t authenticator_should[4];
+static int hitag2_cipher_authenticate(uint64_t *cs, const uint8_t *authenticator_is) {
+ uint8_t authenticator_should[4];
authenticator_should[0] = ~_hitag2_byte(cs);
authenticator_should[1] = ~_hitag2_byte(cs);
authenticator_should[2] = ~_hitag2_byte(cs);
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;
- for(i=0; i<bytes; i++) data[i] ^= _hitag2_byte(cs);
- for(i=0; i<bits; i++) data[bytes] ^= _hitag2_round(cs) << (7-i);
+ for (i = 0; i < bytes; i++) data[i] ^= _hitag2_byte(cs);
+ for (i = 0; i < bits; i++) data[bytes] ^= _hitag2_round(cs) << (7-i);
return 0;
}
// T0 = TIMER_CLOCK1 / 125000 = 192
#define T0 192
-#define SHORT_COIL() LOW(GPIO_SSC_DOUT)
-#define OPEN_COIL() HIGH(GPIO_SSC_DOUT)
-
-#define HITAG_FRAME_LEN 20
-#define HITAG_T_STOP 36 /* T_EOF should be > 36 */
-#define HITAG_T_LOW 8 /* T_LOW should be 4..10 */
-#define HITAG_T_0_MIN 15 /* T[0] should be 18..22 */
-#define HITAG_T_1_MIN 25 /* T[1] should be 26..30 */
-//#define HITAG_T_EOF 40 /* T_EOF should be > 36 */
-#define HITAG_T_EOF 80 /* T_EOF should be > 36 */
-#define HITAG_T_WAIT_1 200 /* T_wresp should be 199..206 */
-#define HITAG_T_WAIT_2 90 /* T_wresp should be 199..206 */
+#define HITAG_FRAME_LEN 20
+#define HITAG_T_STOP 36 /* T_EOF should be > 36 */
+#define HITAG_T_LOW 8 /* T_LOW should be 4..10 */
+#define HITAG_T_0_MIN 15 /* T[0] should be 18..22 */
+#define HITAG_T_1_MIN 25 /* T[1] should be 26..30 */
+//#define HITAG_T_EOF 40 /* T_EOF should be > 36 */
+#define HITAG_T_EOF 80 /* T_EOF should be > 36 */
+#define HITAG_T_WAIT_1 200 /* T_wresp should be 199..206 */
+#define HITAG_T_WAIT_2 90 /* T_wresp should be 199..206 */
#define HITAG_T_WAIT_MAX 300 /* bit more than HITAG_T_WAIT_1 + HITAG_T_WAIT_2 */
-#define HITAG_T_PROG 614
+#define HITAG_T_PROG 614
-#define HITAG_T_TAG_ONE_HALF_PERIOD 10
-#define HITAG_T_TAG_TWO_HALF_PERIOD 25
-#define HITAG_T_TAG_THREE_HALF_PERIOD 41
+#define HITAG_T_TAG_ONE_HALF_PERIOD 10
+#define HITAG_T_TAG_TWO_HALF_PERIOD 25
+#define HITAG_T_TAG_THREE_HALF_PERIOD 41
#define HITAG_T_TAG_FOUR_HALF_PERIOD 57
-#define HITAG_T_TAG_HALF_PERIOD 16
-#define HITAG_T_TAG_FULL_PERIOD 32
+#define HITAG_T_TAG_HALF_PERIOD 16
+#define HITAG_T_TAG_FULL_PERIOD 32
-#define HITAG_T_TAG_CAPTURE_ONE_HALF 13
-#define HITAG_T_TAG_CAPTURE_TWO_HALF 25
+#define HITAG_T_TAG_CAPTURE_ONE_HALF 13
+#define HITAG_T_TAG_CAPTURE_TWO_HALF 25
#define HITAG_T_TAG_CAPTURE_THREE_HALF 41
#define HITAG_T_TAG_CAPTURE_FOUR_HALF 57
-
static void hitag_send_bit(int bit) {
LED_A_ON();
// Reset clock for the next bit
AT91C_BASE_TC0->TC_CCR = AT91C_TC_SWTRG;
// Fixed modulation, earlier proxmark version used inverted signal
- if(bit == 0) {
+ if (bit == 0) {
// Manchester: Unloaded, then loaded |__--|
LOW(GPIO_SSC_DOUT);
- while(AT91C_BASE_TC0->TC_CV < T0*HITAG_T_TAG_HALF_PERIOD);
+ while (AT91C_BASE_TC0->TC_CV < T0*HITAG_T_TAG_HALF_PERIOD);
HIGH(GPIO_SSC_DOUT);
- while(AT91C_BASE_TC0->TC_CV < T0*HITAG_T_TAG_FULL_PERIOD);
+ while (AT91C_BASE_TC0->TC_CV < T0*HITAG_T_TAG_FULL_PERIOD);
} else {
// Manchester: Loaded, then unloaded |--__|
HIGH(GPIO_SSC_DOUT);
- while(AT91C_BASE_TC0->TC_CV < T0*HITAG_T_TAG_HALF_PERIOD);
+ while (AT91C_BASE_TC0->TC_CV < T0*HITAG_T_TAG_HALF_PERIOD);
LOW(GPIO_SSC_DOUT);
- while(AT91C_BASE_TC0->TC_CV < T0*HITAG_T_TAG_FULL_PERIOD);
+ while (AT91C_BASE_TC0->TC_CV < T0*HITAG_T_TAG_FULL_PERIOD);
}
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
- for(size_t i=0; i<5; i++) {
+ for(size_t i = 0; i < 5; i++) {
hitag_send_bit(1);
}
// Send the content of the frame
- for(size_t i=0; i<frame_len; i++) {
- hitag_send_bit((frame[i/8] >> (7-(i%8)))&1);
+ for (size_t i = 0; i < frame_len; i++) {
+ hitag_send_bit((frame[i/8] >> (7-(i%8))) & 0x01);
}
// Drop the modulation
LOW(GPIO_SSC_DOUT);
}
-
-static void hitag2_handle_reader_command(byte_t* rx, const size_t rxlen, byte_t* tx, size_t* txlen)
-{
- byte_t rx_air[HITAG_FRAME_LEN];
+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];
// Copy the (original) received frame how it is send over the air
- memcpy(rx_air,rx,nbytes(rxlen));
+ memcpy(rx_air, rx, nbytes(rxlen));
- if(tag.crypto_active) {
- hitag2_cipher_transcrypt(&(tag.cs),rx,rxlen/8,rxlen%8);
+ if (tag.crypto_active) {
+ hitag2_cipher_transcrypt(&(tag.cs), rx, rxlen/8, rxlen%8);
}
// Reset the transmission frame length
// Try to find out which command was send by selecting on length (in bits)
switch (rxlen) {
// Received 11000 from the reader, request for UID, send UID
- case 05: {
- // Always send over the air in the clear plaintext mode
- if(rx_air[0] != 0xC0) {
- // Unknown frame ?
- return;
+ case 05: {
+ // Always send over the air in the clear plaintext mode
+ if (rx_air[0] != HITAG2_START_AUTH) {
+ // Unknown frame ?
+ return;
+ }
+ *txlen = 32;
+ memcpy(tx, tag.sectors[0], 4);
+ tag.crypto_active = 0;
}
- *txlen = 32;
- memcpy(tx,tag.sectors[0],4);
- tag.crypto_active = 0;
- }
break;
// Read/Write command: ..xx x..y yy with yyy == ~xxx, xxx is sector number
- case 10: {
- unsigned int sector = (~( ((rx[0]<<2)&0x04) | ((rx[1]>>6)&0x03) ) & 0x07);
- // Verify complement of sector index
- if(sector != ((rx[0]>>3)&0x07)) {
- //DbpString("Transmission error (read/write)");
- return;
- }
+ case 10: {
+ unsigned int sector = (~( ((rx[0]<<2) & 0x04) | ((rx[1]>>6) & 0x03) ) & 0x07);
+ // Verify complement of sector index
+ if (sector != ((rx[0]>>3) & 0x07)) {
+ //DbpString("Transmission error (read/write)");
+ return;
+ }
- switch (rx[0] & 0xC6) {
- // Read command: 11xx x00y
- case 0xC0:
- memcpy(tx,tag.sectors[sector],4);
- *txlen = 32;
- break;
+ switch (rx[0] & 0xC6) {
+ // Read command: 11xx x00y
+ case HITAG2_READ_PAGE:
+ memcpy(tx, tag.sectors[sector], 4);
+ *txlen = 32;
+ break;
- // Inverted Read command: 01xx x10y
- case 0x44:
- for (size_t i=0; i<4; i++) {
- tx[i] = tag.sectors[sector][i] ^ 0xff;
- }
- *txlen = 32;
- break;
+ // Inverted Read command: 01xx x10y
+ case HITAG2_READ_PAGE_INVERTED:
+ for (size_t i = 0; i < 4; i++) {
+ tx[i] = tag.sectors[sector][i] ^ 0xff;
+ }
+ *txlen = 32;
+ break;
- // Write command: 10xx x01y
- case 0x82:
- // Prepare write, acknowledge by repeating command
- memcpy(tx,rx,nbytes(rxlen));
- *txlen = rxlen;
- tag.active_sector = sector;
- tag.state=TAG_STATE_WRITING;
- break;
+ // Write command: 10xx x01y
+ case HITAG2_WRITE_PAGE:
+ // Prepare write, acknowledge by repeating command
+ memcpy(tx, rx, nbytes(rxlen));
+ *txlen = rxlen;
+ tag.active_sector = sector;
+ tag.state = TAG_STATE_WRITING;
+ break;
- // Unknown command
- default:
- Dbprintf("Unknown command: %02x %02x",rx[0],rx[1]);
- return;
- break;
+ // Unknown command
+ default:
+ Dbprintf("Unknown command: %02x %02x", rx[0], rx[1]);
+ return;
+ break;
+ }
}
- }
break;
// Writing data or Reader password
- case 32: {
- if(tag.state == TAG_STATE_WRITING) {
- // These are the sector contents to be written. We don't have to do anything else.
- memcpy(tag.sectors[tag.active_sector],rx,nbytes(rxlen));
- tag.state=TAG_STATE_RESET;
- return;
- } else {
- // Received RWD password, respond with configuration and our password
- if(memcmp(rx,tag.sectors[1],4) != 0) {
- DbpString("Reader password is wrong");
+ case 32: {
+ if (tag.state == TAG_STATE_WRITING) {
+ // These are the sector contents to be written. We don't have to do anything else.
+ memcpy(tag.sectors[tag.active_sector], rx, nbytes(rxlen));
+ tag.state = TAG_STATE_RESET;
return;
+ } else {
+ // Received RWD password, respond with configuration and our password
+ if (memcmp(rx, tag.sectors[1], 4) != 0) {
+ DbpString("Reader password is wrong");
+ return;
+ }
+ *txlen = 32;
+ memcpy(tx, tag.sectors[3], 4);
}
- *txlen = 32;
- memcpy(tx,tag.sectors[3],4);
}
- }
break;
// Received RWD authentication challenge and respnse
- case 64: {
- // Store the authentication attempt
- if (auth_table_len < (AUTH_TABLE_LENGTH-8)) {
- memcpy(auth_table+auth_table_len,rx,8);
- auth_table_len += 8;
- }
+ case 64: {
+ // Store the authentication attempt
+ if (auth_table_len < (AUTH_TABLE_LENGTH-8)) {
+ memcpy(auth_table+auth_table_len, rx, 8);
+ auth_table_len += 8;
+ }
- // Reset the cipher state
- hitag2_cipher_reset(&tag,rx);
- // Check if the authentication was correct
- if(!hitag2_cipher_authenticate(&(tag.cs),rx+4)) {
- // The reader failed to authenticate, do nothing
- Dbprintf("auth: %02x%02x%02x%02x%02x%02x%02x%02x Failed!",rx[0],rx[1],rx[2],rx[3],rx[4],rx[5],rx[6],rx[7]);
- return;
- }
- // Succesful, but commented out reporting back to the Host, this may delay to much.
- // Dbprintf("auth: %02x%02x%02x%02x%02x%02x%02x%02x OK!",rx[0],rx[1],rx[2],rx[3],rx[4],rx[5],rx[6],rx[7]);
+ // Reset the cipher state
+ hitag2_cipher_reset(&tag, rx);
+ // Check if the authentication was correct
+ if (!hitag2_cipher_authenticate(&(tag.cs), rx+4)) {
+ // The reader failed to authenticate, do nothing
+ Dbprintf("auth: %02x%02x%02x%02x%02x%02x%02x%02x Failed!", rx[0], rx[1], rx[2], rx[3], rx[4], rx[5], rx[6], rx[7]);
+ return;
+ }
+ // Succesful, but commented out reporting back to the Host, this may delay to much.
+ // Dbprintf("auth: %02x%02x%02x%02x%02x%02x%02x%02x OK!",rx[0],rx[1],rx[2],rx[3],rx[4],rx[5],rx[6],rx[7]);
- // Activate encryption algorithm for all further communication
- tag.crypto_active = 1;
+ // Activate encryption algorithm for all further communication
+ tag.crypto_active = 1;
- // Use the tag password as response
- memcpy(tx,tag.sectors[3],4);
- *txlen = 32;
- }
+ // Use the tag password as response
+ memcpy(tx, tag.sectors[3], 4);
+ *txlen = 32;
+ }
break;
}
-// LogTraceHitag(rx,rxlen,0,0,false);
-// LogTraceHitag(tx,*txlen,0,0,true);
+ // LogTraceHitag(rx, rxlen, 0, 0, false);
+ // LogTraceHitag(tx, *txlen, 0, 0, true);
- if(tag.crypto_active) {
+ if (tag.crypto_active) {
hitag2_cipher_transcrypt(&(tag.cs), tx, *txlen/8, *txlen%8);
}
}
// Enable modulation, which means, drop the field
HIGH(GPIO_SSC_DOUT);
- // Wait for 4-10 times the carrier period
- while(AT91C_BASE_TC0->TC_CV < T0*6);
- // SpinDelayUs(8*8);
+ // t_low = 4...10 carrier periods
+ while (AT91C_BASE_TC0->TC_CV < T0*6);
// Disable modulation, just activates the field again
LOW(GPIO_SSC_DOUT);
- if(bit == 0) {
- // Zero bit: |_-|
- while(AT91C_BASE_TC0->TC_CV < T0*22);
- // SpinDelayUs(16*8);
+ if (bit == 0) {
+ // Zero bit: |_-|, T[0] = 18...22 carrier periods
+ while (AT91C_BASE_TC0->TC_CV < T0*22);
} else {
- // One bit: |_--|
- while(AT91C_BASE_TC0->TC_CV < T0*28);
- // SpinDelayUs(22*8);
+ // One bit: |_--|, T[1] = 26...32 carrier periods
+ while (AT91C_BASE_TC0->TC_CV < T0*28);
}
LED_A_OFF();
}
-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
- for(size_t i=0; i<frame_len; i++) {
- hitag_reader_send_bit((frame[i/8] >> (7-(i%8)))&1);
+ for(size_t i = 0; i < frame_len; i++) {
+ hitag_reader_send_bit((frame[i/8] >> (7-(i%8))) & 0x01);
}
// Send EOF
AT91C_BASE_TC0->TC_CCR = AT91C_TC_SWTRG;
// Enable modulation, which means, drop the field
HIGH(GPIO_SSC_DOUT);
- // Wait for 4-10 times the carrier period
- while(AT91C_BASE_TC0->TC_CV < T0*6);
+ // t_low = 4...10 carrier periods
+ while (AT91C_BASE_TC0->TC_CV < T0*6);
// Disable modulation, just activates the field again
LOW(GPIO_SSC_DOUT);
+ // t_stop > 36 carrier periods
+ while (AT91C_BASE_TC0->TC_CV < T0*36);
}
size_t blocknr;
-static bool hitag2_password(byte_t* rx, const size_t rxlen, byte_t* tx, size_t* txlen) {
+//-----------------------------------------------------------------------------
+// Hitag2 operations
+//-----------------------------------------------------------------------------
+
+static bool hitag2_write_page(uint8_t *rx, const size_t rxlen, uint8_t *tx, size_t *txlen) {
+ switch (writestate) {
+ case WRITE_STATE_START:
+ tx[0] = HITAG2_WRITE_PAGE | (blocknr << 3) | ((blocknr^7) >> 2);
+ tx[1] = ((blocknr^7) << 6);
+ *txlen = 10;
+ writestate = WRITE_STATE_PAGENUM_WRITTEN;
+ break;
+ case WRITE_STATE_PAGENUM_WRITTEN:
+ // Check if page number was received correctly
+ if ((rxlen == 10)
+ && (rx[0] == (HITAG2_WRITE_PAGE | (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
*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!");
+ if (bPwd && !bAuthenticating && write) {
+ if (!hitag2_write_page(rx, rxlen, tx, txlen)) {
return false;
}
- *txlen = 5;
- memcpy(tx,"\xc0",nbytes(*txlen));
- } break;
+ } 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;
+ }
+ tx[0] = HITAG2_START_AUTH;
+ *txlen = 5;
+ }
+ 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 {
+ // 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 == 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);
+ if (blocknr > 7) {
+ DbpString("Read successful!");
+ bSuccessful = true;
+ return false;
+ }
+ tx[0] = HITAG2_READ_PAGE | (blocknr << 3) | ((blocknr^7) >> 2);
+ tx[1] = ((blocknr^7) << 6);
+ *txlen = 10;
+ }
}
+ break;
- blocknr++;
- if (blocknr > 7) {
- DbpString("Read succesful!");
- bSuccessful = true;
+ // Unexpected response
+ default: {
+ Dbprintf("Unknown frame length: %d", rxlen);
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) {
- 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);
+ break;
}
- return false;
- default:
- DbpString("hitag2_write_page: Unknown state %d");
- bSuccessful = false;
- return false;
}
return true;
}
-static bool hitag2_crypto(byte_t* rx, const size_t rxlen, byte_t* tx, size_t* txlen, bool write) {
+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;
- if(bCrypto) {
- hitag2_cipher_transcrypt(&cipher_state,rx,rxlen/8,rxlen%8);
-
+ if (bCrypto) {
+ hitag2_cipher_transcrypt(&cipher_state, rx, rxlen/8, rxlen%8);
}
if (bCrypto && !bAuthenticating && write) {
if (!hitag2_write_page(rx, rxlen, tx, txlen)) {
return false;
}
- }
- else
- {
+ } 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 while we are in crypto mode (after sending NrAr)
- if (bCrypto) {
- // Failed during authentication
- if (bAuthenticating) {
- DbpString("Authentication failed!");
- return false;
- } else {
- // Failed reading a block, could be (read/write) locked, skip block and re-authenticate
- if (blocknr == 1) {
- // Write the low part of the key in memory
- memcpy(tag.sectors[1],key+2,4);
- } else if (blocknr == 2) {
- // Write the high part of the key in memory
- tag.sectors[2][0] = 0x00;
- tag.sectors[2][1] = 0x00;
- tag.sectors[2][2] = key[0];
- tag.sectors[2][3] = key[1];
+ // 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 while we are in crypto mode (after sending NrAr)
+ if (bCrypto) {
+ // Failed during authentication
+ if (bAuthenticating) {
+ DbpString("Authentication failed!");
+ return false;
+ } else {
+ // Failed reading a block, could be (read/write) locked, skip block and re-authenticate
+ if (blocknr == 1) {
+ // Write the low part of the key in memory
+ memcpy(tag.sectors[1], key+2, 4);
+ } else if (blocknr == 2) {
+ // Write the high part of the key in memory
+ tag.sectors[2][0] = 0x00;
+ tag.sectors[2][1] = 0x00;
+ tag.sectors[2][2] = key[0];
+ tag.sectors[2][3] = key[1];
+ } else {
+ // Just put zero's in the memory (of the unreadable block)
+ memset(tag.sectors[blocknr], 0x00, 4);
+ }
+ blocknr++;
+ bCrypto = false;
+ }
} else {
- // Just put zero's in the memory (of the unreadable block)
- memset(tag.sectors[blocknr],0x00,4);
+ tx[0] = HITAG2_START_AUTH;
+ *txlen = 5;
}
- blocknr++;
- bCrypto = false;
+ break;
}
- } else {
- *txlen = 5;
- memcpy(tx,"\xc0",nbytes(*txlen));
- }
- break;
- }
- // Received UID, crypto tag answer
- case 32: {
- if (!bCrypto) {
- uint64_t ui64key = key[0] | ((uint64_t)key[1]) << 8 | ((uint64_t)key[2]) << 16 | ((uint64_t)key[3]) << 24 | ((uint64_t)key[4]) << 32 | ((uint64_t)key[5]) << 40;
- uint32_t ui32uid = rx[0] | ((uint32_t)rx[1]) << 8 | ((uint32_t)rx[2]) << 16 | ((uint32_t)rx[3]) << 24;
- Dbprintf("hitag2_crypto: key=0x%x%x uid=0x%x", (uint32_t) ((rev64(ui64key)) >> 32), (uint32_t) ((rev64(ui64key)) & 0xffffffff), rev32(ui32uid));
- cipher_state = _hitag2_init(rev64(ui64key), rev32(ui32uid), 0);
- memset(tx,0x00,4);
- memset(tx+4,0xff,4);
- hitag2_cipher_transcrypt(&cipher_state, tx+4, 4, 0);
- *txlen = 64;
- bCrypto = true;
- bAuthenticating = true;
- } else {
- // Check if we received answer tag (at)
- if (bAuthenticating) {
- bAuthenticating = false;
- if (write) {
- if (!hitag2_write_page(rx, rxlen, tx, txlen)) {
+ // Received UID, crypto tag answer
+ case 32: {
+ if (!bCrypto) {
+ uint64_t ui64key = key[0] | ((uint64_t)key[1]) << 8 | ((uint64_t)key[2]) << 16 | ((uint64_t)key[3]) << 24 | ((uint64_t)key[4]) << 32 | ((uint64_t)key[5]) << 40;
+ uint32_t ui32uid = rx[0] | ((uint32_t)rx[1]) << 8 | ((uint32_t)rx[2]) << 16 | ((uint32_t)rx[3]) << 24;
+ Dbprintf("hitag2_crypto: key=0x%x%x uid=0x%x", (uint32_t) ((REV64(ui64key)) >> 32), (uint32_t) ((REV64(ui64key)) & 0xffffffff), REV32(ui32uid));
+ cipher_state = _hitag2_init(REV64(ui64key), REV32(ui32uid), 0);
+ memset(tx, 0x00, 4);
+ memset(tx+4, 0xff, 4);
+ hitag2_cipher_transcrypt(&cipher_state, tx+4, 4, 0);
+ *txlen = 64;
+ bCrypto = true;
+ bAuthenticating = true;
+ } else {
+ // Check if we received answer tag (at)
+ if (bAuthenticating) {
+ bAuthenticating = false;
+ if (write) {
+ if (!hitag2_write_page(rx, rxlen, tx, txlen)) {
+ return false;
+ }
+ break;
+ }
+ }
+ // stage 2+, got data block
+ else {
+ // Store the received block
+ memcpy(tag.sectors[blocknr], rx, 4);
+ blocknr++;
+ }
+ if (blocknr > 7) {
+ DbpString("Read successful!");
+ bSuccessful = true;
return false;
+ } else {
+ tx[0] = HITAG2_READ_PAGE | (blocknr << 3) | ((blocknr ^ 7) >> 2);
+ tx[1] = ((blocknr ^ 7) << 6);
+ *txlen = 10;
}
- break;
}
- } else {
- // Store the received block
- memcpy(tag.sectors[blocknr],rx,4);
- blocknr++;
}
+ break;
- if (blocknr > 7) {
- DbpString("Read succesful!");
- bSuccessful = true;
+ // Unexpected response
+ default: {
+ Dbprintf("Unknown frame length: %d",rxlen);
return false;
- } else {
- *txlen = 10;
- tx[0] = 0xc0 | (blocknr << 3) | ((blocknr^7) >> 2);
- tx[1] = ((blocknr^7) << 6);
}
+ break;
}
- } break;
-
- // Unexpected response
- default: {
- Dbprintf("Uknown frame length: %d",rxlen);
- return false;
- } break;
- }
}
- if(bCrypto) {
+ if (bCrypto) {
// We have to return now to avoid double encryption
if (!bAuthenticating) {
- hitag2_cipher_transcrypt(&cipher_state,tx,*txlen/8,*txlen%8);
+ hitag2_cipher_transcrypt(&cipher_state, tx, *txlen/8, *txlen%8);
}
}
return true;
}
-
-static bool hitag2_authenticate(byte_t* rx, const size_t rxlen, byte_t* tx, size_t* txlen) {
+static bool hitag2_authenticate(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 while we are in crypto mode (after sending NrAr)
- if (bCrypto) {
- DbpString("Authentication failed!");
- return false;
+ case 0: {
+ // Stop if there is no answer while we are in crypto mode (after sending NrAr)
+ if (bCrypto) {
+ DbpString("Authentication failed!");
+ return false;
+ }
+ tx[0] = HITAG2_START_AUTH;
+ *txlen = 5;
}
- *txlen = 5;
- memcpy(tx,"\xc0",nbytes(*txlen));
- } break;
+ break;
// Received UID, crypto tag answer
- case 32: {
- if (!bCrypto) {
- *txlen = 64;
- memcpy(tx,NrAr,8);
- bCrypto = true;
- } else {
- DbpString("Authentication succesful!");
- // We are done... for now
- return false;
+ case 32: {
+ if (!bCrypto) {
+ memcpy(tx, NrAr, 8);
+ *txlen = 64;
+ bCrypto = true;
+ } else {
+ DbpString("Authentication successful!");
+ // We are done... for now
+ return false;
+ }
}
- } break;
+ break;
// Unexpected response
- default: {
- Dbprintf("Uknown frame length: %d",rxlen);
- return false;
- } break;
+ default: {
+ Dbprintf("Unknown frame length: %d",rxlen);
+ return false;
+ }
+ break;
}
return true;
}
-
-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
*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 while we are in crypto mode (after sending NrAr)
- if (bCrypto) {
- Dbprintf("auth: %02x%02x%02x%02x%02x%02x%02x%02x Failed, removed entry!",NrAr[0],NrAr[1],NrAr[2],NrAr[3],NrAr[4],NrAr[5],NrAr[6],NrAr[7]);
+ case 0: {
+ // Stop if there is no answer while we are in crypto mode (after sending NrAr)
+ if (bCrypto) {
+ Dbprintf("auth: %02x%02x%02x%02x%02x%02x%02x%02x Failed, removed entry!", NrAr[0], NrAr[1], NrAr[2], NrAr[3], NrAr[4], NrAr[5], NrAr[6], NrAr[7]);
- // Removing failed entry from authentiations table
- memcpy(auth_table+auth_table_pos,auth_table+auth_table_pos+8,8);
- auth_table_len -= 8;
+ // Removing failed entry from authentiations table
+ memcpy(auth_table+auth_table_pos, auth_table+auth_table_pos+8, 8);
+ auth_table_len -= 8;
- // Return if we reached the end of the authentications table
- bCrypto = false;
- if (auth_table_pos == auth_table_len) {
- return false;
- }
+ // Return if we reached the end of the authentications table
+ bCrypto = false;
+ if (auth_table_pos == auth_table_len) {
+ return false;
+ }
- // Copy the next authentication attempt in row (at the same position, b/c we removed last failed entry)
- memcpy(NrAr,auth_table+auth_table_pos,8);
+ // Copy the next authentication attempt in row (at the same position, b/c we removed last failed entry)
+ memcpy(NrAr, auth_table+auth_table_pos, 8);
+ }
+ tx[0] = HITAG2_START_AUTH;
+ *txlen = 5;
}
- *txlen = 5;
- memcpy(tx,"\xc0",nbytes(*txlen));
- } break;
+ break;
// Received UID, crypto tag answer, or read block response
- case 32: {
- if (!bCrypto) {
- *txlen = 64;
- memcpy(tx,NrAr,8);
- bCrypto = true;
- } else {
- Dbprintf("auth: %02x%02x%02x%02x%02x%02x%02x%02x OK",NrAr[0],NrAr[1],NrAr[2],NrAr[3],NrAr[4],NrAr[5],NrAr[6],NrAr[7]);
- bCrypto = false;
- if ((auth_table_pos+8) == auth_table_len) {
- return false;
+ case 32: {
+ if (!bCrypto) {
+ *txlen = 64;
+ memcpy(tx, NrAr, 8);
+ bCrypto = true;
+ } else {
+ Dbprintf("auth: %02x%02x%02x%02x%02x%02x%02x%02x OK", NrAr[0], NrAr[1], NrAr[2], NrAr[3], NrAr[4], NrAr[5], NrAr[6], NrAr[7]);
+ bCrypto = false;
+ if ((auth_table_pos+8) == auth_table_len) {
+ return false;
+ }
+ auth_table_pos += 8;
+ memcpy(NrAr, auth_table+auth_table_pos, 8);
}
- auth_table_pos += 8;
- memcpy(NrAr,auth_table+auth_table_pos,8);
}
- } break;
+ break;
- default: {
- Dbprintf("Uknown frame length: %d",rxlen);
- return false;
- } break;
+ default: {
+ Dbprintf("Unknown frame length: %d",rxlen);
+ return false;
+ }
+ break;
}
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
*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: {
- // Just starting or if there is no answer
- *txlen = 5;
- memcpy(tx,"\xc0",nbytes(*txlen));
- } break;
+ case 0: {
+ // Just starting or if there is no answer
+ tx[0] = HITAG2_START_AUTH;
+ *txlen = 5;
+ }
+ break;
// Received UID
- case 32: {
- // Check if we received answer tag (at)
- if (bAuthenticating) {
- bAuthenticating = false;
- } else {
- // Store the received block
- memcpy(tag.sectors[blocknr],rx,4);
- blocknr++;
+ case 32: {
+ // Check if we received answer tag (at)
+ if (bAuthenticating) {
+ bAuthenticating = false;
+ } else {
+ // Store the received block
+ memcpy(tag.sectors[blocknr], rx, 4);
+ blocknr++;
+ }
+ if (blocknr > 0) {
+ //DbpString("Read successful!");
+ bSuccessful = true;
+ return false;
+ }
}
- if (blocknr > 0) {
- //DbpString("Read successful!");
- bSuccessful = true;
+ break;
+ // Unexpected response
+ default: {
+ Dbprintf("Unknown frame length: %d",rxlen);
return false;
}
- } break;
- // Unexpected response
- default: {
- Dbprintf("Uknown frame length: %d",rxlen);
- return false;
- } break;
+ break;
}
return true;
}
void SnoopHitag(uint32_t type) {
- int frame_count;
+ // int frame_count;
int response;
int overflow;
bool rising_edge;
int lastbit;
bool bSkip;
int tag_sof;
- byte_t rx[HITAG_FRAME_LEN] = {0};
- size_t rxlen=0;
+ uint8_t rx[HITAG_FRAME_LEN] = {0};
+ size_t rxlen = 0;
FpgaDownloadAndGo(FPGA_BITSTREAM_LF);
auth_table_pos = 0;
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);
DbpString("Starting Hitag2 snoop");
FpgaWriteConfWord(FPGA_MAJOR_MODE_LF_EDGE_DETECT | FPGA_LF_EDGE_DETECT_TOGGLE_MODE);
FpgaSendCommand(FPGA_CMD_SET_DIVISOR, 95); //125Khz
SetAdcMuxFor(GPIO_MUXSEL_LOPKD);
- RELAY_OFF();
// Configure output pin that is connected to the FPGA (for modulating)
AT91C_BASE_PIOA->PIO_OER = GPIO_SSC_DOUT;
// TC1: Capture mode, default timer source = MCK/2 (TIMER_CLOCK1), TIOA is external trigger,
// external trigger rising edge, load RA on rising edge of TIOA.
- uint32_t t1_channel_mode = AT91C_TC_CLKS_TIMER_DIV1_CLOCK | AT91C_TC_ETRGEDG_BOTH | AT91C_TC_ABETRG | AT91C_TC_LDRA_BOTH;
- AT91C_BASE_TC1->TC_CMR = t1_channel_mode;
+ AT91C_BASE_TC1->TC_CMR = AT91C_TC_CLKS_TIMER_DIV1_CLOCK | AT91C_TC_ETRGEDG_BOTH | AT91C_TC_ABETRG | AT91C_TC_LDRA_BOTH;
// Enable and reset counter
AT91C_BASE_TC1->TC_CCR = AT91C_TC_CLKEN | AT91C_TC_SWTRG;
// Reset the received frame, frame count and timing info
- frame_count = 0;
+ // frame_count = 0;
response = 0;
overflow = 0;
reader_frame = false;
bSkip = true;
tag_sof = 4;
- while(!BUTTON_PRESS()) {
+ while (!BUTTON_PRESS()) {
// Watchdog hit
WDT_HIT();
// Receive frame, watch for at most T0*EOF periods
while (AT91C_BASE_TC1->TC_CV < T0*HITAG_T_EOF) {
// Check if rising edge in modulation is detected
- if(AT91C_BASE_TC1->TC_SR & AT91C_TC_LDRAS) {
+ if (AT91C_BASE_TC1->TC_SR & AT91C_TC_LDRAS) {
// Retrieve the new timing values
int ra = (AT91C_BASE_TC1->TC_RA/T0);
// Switch from tag to reader capture
LED_C_OFF();
reader_frame = true;
- memset(rx,0x00,sizeof(rx));
+ memset(rx, 0x00, sizeof(rx));
rxlen = 0;
}
if (reader_frame) {
LED_B_ON();
// Capture reader frame
- if(ra >= HITAG_T_STOP) {
+ if (ra >= HITAG_T_STOP) {
if (rxlen != 0) {
//DbpString("wierd0?");
}
// Capture the T0 periods that have passed since last communication or field drop (reset)
response = (ra - HITAG_T_LOW);
- } else if(ra >= HITAG_T_1_MIN ) {
+ } else if (ra >= HITAG_T_1_MIN) {
// '1' bit
rx[rxlen / 8] |= 1 << (7-(rxlen%8));
rxlen++;
- } else if(ra >= HITAG_T_0_MIN) {
+ } else if (ra >= HITAG_T_0_MIN) {
// '0' bit
rx[rxlen / 8] |= 0 << (7-(rxlen%8));
rxlen++;
} else {
LED_C_ON();
// Capture tag frame (manchester decoding using only falling edges)
- if(ra >= HITAG_T_EOF) {
+ if (ra >= HITAG_T_EOF) {
if (rxlen != 0) {
//DbpString("wierd1?");
}
// Capture the T0 periods that have passed since last communication or field drop (reset)
// We always recieve a 'one' first, which has the falling edge after a half period |-_|
- response = ra-HITAG_T_TAG_HALF_PERIOD;
- } else if(ra >= HITAG_T_TAG_CAPTURE_FOUR_HALF) {
+ response = ra - HITAG_T_TAG_HALF_PERIOD;
+ } else if (ra >= HITAG_T_TAG_CAPTURE_FOUR_HALF) {
// Manchester coding example |-_|_-|-_| (101)
rx[rxlen / 8] |= 0 << (7-(rxlen%8));
rxlen++;
rx[rxlen / 8] |= 1 << (7-(rxlen%8));
rxlen++;
- } else if(ra >= HITAG_T_TAG_CAPTURE_THREE_HALF) {
+ } else if (ra >= HITAG_T_TAG_CAPTURE_THREE_HALF) {
// Manchester coding example |_-|...|_-|-_| (0...01)
rx[rxlen / 8] |= 0 << (7-(rxlen%8));
rxlen++;
}
lastbit = !lastbit;
bSkip = !bSkip;
- } else if(ra >= HITAG_T_TAG_CAPTURE_TWO_HALF) {
+ } else if (ra >= HITAG_T_TAG_CAPTURE_TWO_HALF) {
// Manchester coding example |_-|_-| (00) or |-_|-_| (11)
if (tag_sof) {
// Ignore bits that are transmitted during SOF
}
// Check if frame was captured
- if(rxlen > 0) {
- frame_count++;
- if (!LogTraceHitag(rx,rxlen,response,0,reader_frame)) {
+ if (rxlen > 0) {
+ // frame_count++;
+ if (!LogTraceHitag(rx, rxlen, response, 0, reader_frame)) {
DbpString("Trace full");
break;
}
}
// Reset the received frame and response timing info
- memset(rx,0x00,sizeof(rx));
+ memset(rx, 0x00, sizeof(rx));
response = 0;
reader_frame = false;
lastbit = 1;
// DbpString("All done");
}
-void SimulateHitagTag(bool tag_mem_supplied, byte_t* data) {
- int frame_count;
+void SimulateHitagTag(bool tag_mem_supplied, uint8_t *data) {
+ // int frame_count;
int response;
int overflow;
- byte_t rx[HITAG_FRAME_LEN];
- size_t rxlen=0;
- byte_t tx[HITAG_FRAME_LEN];
- size_t txlen=0;
+ uint8_t rx[HITAG_FRAME_LEN];
+ size_t rxlen = 0;
+ uint8_t tx[HITAG_FRAME_LEN];
+ size_t txlen = 0;
bool bQuitTraceFull = false;
bQuiet = false;
auth_table_len = 0;
auth_table_pos = 0;
- byte_t* auth_table;
+ uint8_t *auth_table;
BigBuf_free();
- auth_table = (byte_t *)BigBuf_malloc(AUTH_TABLE_LENGTH);
+ auth_table = BigBuf_malloc(AUTH_TABLE_LENGTH);
memset(auth_table, 0x00, AUTH_TABLE_LENGTH);
DbpString("Starting Hitag2 simulation");
if (tag_mem_supplied) {
DbpString("Loading hitag2 memory...");
- memcpy((byte_t*)tag.sectors,data,48);
+ memcpy((uint8_t*)tag.sectors, data, 48);
}
uint32_t block = 0;
- for (size_t i=0; i<12; i++) {
- for (size_t j=0; j<4; j++) {
+ for (size_t i = 0; i < 12; i++) {
+ for (size_t j = 0; j < 4; j++) {
block <<= 8;
block |= tag.sectors[i][j];
}
- Dbprintf("| %d | %08x |",i,block);
+ Dbprintf("| %d | %08x |", i, block);
}
// Set up simulator mode, frequency divisor which will drive the FPGA
FpgaWriteConfWord(FPGA_MAJOR_MODE_LF_EDGE_DETECT);
FpgaSendCommand(FPGA_CMD_SET_DIVISOR, 95); //125Khz
SetAdcMuxFor(GPIO_MUXSEL_LOPKD);
- RELAY_OFF();
// Configure output pin that is connected to the FPGA (for modulating)
AT91C_BASE_PIOA->PIO_OER = GPIO_SSC_DOUT;
AT91C_BASE_TC1->TC_CMR = AT91C_TC_CLKS_TIMER_DIV1_CLOCK | AT91C_TC_ETRGEDG_RISING | AT91C_TC_ABETRG | AT91C_TC_LDRA_RISING;
// Reset the received frame, frame count and timing info
- memset(rx,0x00,sizeof(rx));
- frame_count = 0;
+ memset(rx, 0x00, sizeof(rx));
+ // frame_count = 0;
response = 0;
overflow = 0;
// Enable and reset counter
AT91C_BASE_TC1->TC_CCR = AT91C_TC_CLKEN | AT91C_TC_SWTRG;
- while(!BUTTON_PRESS()) {
+ while (!BUTTON_PRESS()) {
// Watchdog hit
WDT_HIT();
// Receive frame, watch for at most T0*EOF periods
while (AT91C_BASE_TC1->TC_CV < T0*HITAG_T_EOF) {
// Check if rising edge in modulation is detected
- if(AT91C_BASE_TC1->TC_SR & AT91C_TC_LDRAS) {
+ if (AT91C_BASE_TC1->TC_SR & AT91C_TC_LDRAS) {
// Retrieve the new timing values
int ra = (AT91C_BASE_TC1->TC_RA/T0) + overflow;
overflow = 0;
LED_B_ON();
// Capture reader frame
- if(ra >= HITAG_T_STOP) {
+ if (ra >= HITAG_T_STOP) {
if (rxlen != 0) {
//DbpString("wierd0?");
}
// Capture the T0 periods that have passed since last communication or field drop (reset)
response = (ra - HITAG_T_LOW);
- } else if(ra >= HITAG_T_1_MIN ) {
+ } else if (ra >= HITAG_T_1_MIN) {
// '1' bit
rx[rxlen / 8] |= 1 << (7-(rxlen%8));
rxlen++;
- } else if(ra >= HITAG_T_0_MIN) {
+ } else if (ra >= HITAG_T_0_MIN) {
// '0' bit
rx[rxlen / 8] |= 0 << (7-(rxlen%8));
rxlen++;
}
// Check if frame was captured
- if(rxlen > 4) {
- frame_count++;
+ if (rxlen > 4) {
+ // frame_count++;
if (!bQuiet) {
- if (!LogTraceHitag(rx,rxlen,response,0,true)) {
+ if (!LogTraceHitag(rx, rxlen, response, 0, true)) {
DbpString("Trace full");
if (bQuitTraceFull) {
break;
AT91C_BASE_TC1->TC_CCR = AT91C_TC_CLKDIS;
// Process the incoming frame (rx) and prepare the outgoing frame (tx)
- hitag2_handle_reader_command(rx,rxlen,tx,&txlen);
+ hitag2_handle_reader_command(rx, rxlen, tx, &txlen);
// Wait for HITAG_T_WAIT_1 carrier periods after the last reader bit,
// not that since the clock counts since the rising edge, but T_Wait1 is
// with respect to the falling edge, we need to wait actually (T_Wait1 - T_Low)
// periods. The gap time T_Low varies (4..10). All timer values are in
// terms of T0 units
- while(AT91C_BASE_TC0->TC_CV < T0*(HITAG_T_WAIT_1-HITAG_T_LOW));
+ while (AT91C_BASE_TC0->TC_CV < T0*(HITAG_T_WAIT_1-HITAG_T_LOW));
// Send and store the tag answer (if there is any)
if (txlen) {
// Transmit the tag frame
- hitag_send_frame(tx,txlen);
+ hitag_send_frame(tx, txlen);
// Store the frame in the trace
if (!bQuiet) {
- if (!LogTraceHitag(tx,txlen,0,0,false)) {
+ if (!LogTraceHitag(tx, txlen, 0, 0, false)) {
DbpString("Trace full");
if (bQuitTraceFull) {
break;
}
// Reset the received frame and response timing info
- memset(rx,0x00,sizeof(rx));
+ memset(rx, 0x00, sizeof(rx));
response = 0;
// Enable and reset external trigger in timer for capturing future frames
}
-void ReaderHitag(hitag_function htf, hitag_data* htd) {
- int frame_count;
+void ReaderHitag(hitag_function htf, hitag_data *htd) {
+ // int frame_count;
int response;
- byte_t rx[HITAG_FRAME_LEN];
- size_t rxlen=0;
- byte_t txbuf[HITAG_FRAME_LEN];
- byte_t* tx = txbuf;
- size_t txlen=0;
+ uint8_t rx[HITAG_FRAME_LEN];
+ size_t rxlen = 0;
+ uint8_t txbuf[HITAG_FRAME_LEN];
+ uint8_t *tx = txbuf;
+ size_t txlen = 0;
int lastbit;
bool bSkip;
int reset_sof;
//DbpString("Starting Hitag reader family");
// Check configuration
- switch(htf) {
- case RHT2F_PASSWORD: {
- Dbprintf("List identifier in password mode");
- memcpy(password,htd->pwd.password,4);
- blocknr = 0;
- bQuitTraceFull = false;
- bQuiet = false;
- bPwd = false;
- } break;
- case RHT2F_AUTHENTICATE: {
- DbpString("Authenticating using nr,ar pair:");
- memcpy(NrAr,htd->auth.NrAr,8);
- Dbhexdump(8,NrAr,false);
- bQuiet = false;
- bCrypto = false;
- bAuthenticating = false;
- bQuitTraceFull = true;
- } break;
- case RHT2F_CRYPTO:
- {
- DbpString("Authenticating using key:");
- memcpy(key,htd->crypto.key,6); //HACK; 4 or 6?? I read both in the code.
- Dbhexdump(6,key,false);
- blocknr = 0;
- bQuiet = false;
- bCrypto = false;
- bAuthenticating = false;
- bQuitTraceFull = true;
- } break;
- case RHT2F_TEST_AUTH_ATTEMPTS: {
- Dbprintf("Testing %d authentication attempts",(auth_table_len/8));
- auth_table_pos = 0;
- memcpy(NrAr, auth_table, 8);
- bQuitTraceFull = false;
- bQuiet = false;
- bCrypto = false;
- } break;
- case RHT2F_UID_ONLY: {
- blocknr = 0;
- bQuiet = false;
- bCrypto = false;
- bAuthenticating = false;
- bQuitTraceFull = true;
- } break;
- default: {
- Dbprintf("Error, unknown function: %d",htf);
- return;
- } break;
+ switch (htf) {
+ case RHT2F_PASSWORD: {
+ Dbprintf("List identifier in password mode");
+ memcpy(password, htd->pwd.password, 4);
+ blocknr = 0;
+ bQuitTraceFull = false;
+ bQuiet = false;
+ bPwd = false;
+ bAuthenticating = false;
+ }
+ break;
+ case RHT2F_AUTHENTICATE: {
+ DbpString("Authenticating using nr,ar pair:");
+ memcpy(NrAr, htd->auth.NrAr, 8);
+ Dbhexdump(8, NrAr, false);
+ bQuiet = false;
+ bCrypto = false;
+ bAuthenticating = false;
+ bQuitTraceFull = true;
+ }
+ break;
+ case RHT2F_CRYPTO:
+ {
+ DbpString("Authenticating using key:");
+ memcpy(key, htd->crypto.key, 6); //HACK; 4 or 6?? I read both in the code.
+ Dbhexdump(6, key, false);
+ blocknr = 0;
+ bQuiet = false;
+ bCrypto = false;
+ bAuthenticating = false;
+ bQuitTraceFull = true;
+ }
+ break;
+ case RHT2F_TEST_AUTH_ATTEMPTS: {
+ Dbprintf("Testing %d authentication attempts", (auth_table_len/8));
+ auth_table_pos = 0;
+ memcpy(NrAr, auth_table, 8);
+ bQuitTraceFull = false;
+ bQuiet = false;
+ bCrypto = false;
+ }
+ break;
+ case RHT2F_UID_ONLY: {
+ blocknr = 0;
+ bQuiet = false;
+ bCrypto = false;
+ bAuthenticating = false;
+ bQuitTraceFull = true;
+ }
+ break;
+ default: {
+ Dbprintf("Error, unknown function: %d", htf);
+ return;
+ }
+ break;
}
LED_D_ON();
// Set Frequency divisor which will drive the FPGA and analog mux selection
FpgaSendCommand(FPGA_CMD_SET_DIVISOR, 95); //125Khz
SetAdcMuxFor(GPIO_MUXSEL_LOPKD);
- RELAY_OFF();
// Disable modulation at default, which means enable the field
LOW(GPIO_SSC_DOUT);
- // Give it a bit of time for the resonant antenna to settle.
- SpinDelay(30);
-
// Enable Peripheral Clock for TIMER_CLOCK0, used to measure exact timing before answering
AT91C_BASE_PMC->PMC_PCER = (1 << AT91C_ID_TC0);
AT91C_BASE_TC1->TC_CCR = AT91C_TC_CLKEN | AT91C_TC_SWTRG;
// Reset the received frame, frame count and timing info
- frame_count = 0;
+ // frame_count = 0;
response = 0;
lastbit = 1;
// Tag specific configuration settings (sof, timings, etc.)
- if (htf < 10){
+ if (htf < 10) {
// hitagS settings
reset_sof = 1;
t_wait = 200;
t_wait = HITAG_T_WAIT_2;
//DbpString("Configured for hitag2 reader");
} else {
- Dbprintf("Error, unknown hitag reader type: %d",htf);
- return;
+ Dbprintf("Error, unknown hitag reader type: %d", htf);
+ goto out;
}
- uint8_t attempt_count=0;
- while(!bStop && !BUTTON_PRESS()) {
- // Watchdog hit
+
+ // wait for tag to power up
+ // t_PowerUp = 312,5 carrier periods
+ while (AT91C_BASE_TC0->TC_CV < T0*(312-t_wait));
+
+ uint8_t attempt_count = 0;
+ while (!bStop && !BUTTON_PRESS()) {
WDT_HIT();
// Check if frame was captured and store it
- if(rxlen > 0) {
- frame_count++;
+ if (rxlen > 0) {
+ // frame_count++;
if (!bQuiet) {
- if (!LogTraceHitag(rx,rxlen,response,0,false)) {
+ if (!LogTraceHitag(rx, rxlen, response, 0, false)) {
DbpString("Trace full");
if (bQuitTraceFull) {
break;
// By default reset the transmission buffer
tx = txbuf;
- switch(htf) {
+ switch (htf) {
case RHT2F_PASSWORD: {
- bStop = !hitag2_password(rx,rxlen,tx,&txlen);
- } break;
+ bStop = !hitag2_password(rx, rxlen, tx, &txlen, false);
+ }
+ break;
case RHT2F_AUTHENTICATE: {
- bStop = !hitag2_authenticate(rx,rxlen,tx,&txlen);
- } break;
+ bStop = !hitag2_authenticate(rx, rxlen, tx, &txlen);
+ }
+ break;
case RHT2F_CRYPTO: {
- bStop = !hitag2_crypto(rx,rxlen,tx,&txlen, false);
- } break;
+ bStop = !hitag2_crypto(rx, rxlen, tx, &txlen, false);
+ }
+ break;
case RHT2F_TEST_AUTH_ATTEMPTS: {
- bStop = !hitag2_test_auth_attempts(rx,rxlen,tx,&txlen);
- } break;
+ bStop = !hitag2_test_auth_attempts(rx, rxlen, tx, &txlen);
+ }
+ break;
case RHT2F_UID_ONLY: {
bStop = !hitag2_read_uid(rx, rxlen, tx, &txlen);
attempt_count++; //attempt 3 times to get uid then quit
- if (!bStop && attempt_count == 3) bStop = true;
- } break;
+ if (!bStop && attempt_count == 3)
+ bStop = true;
+ }
+ break;
default: {
- Dbprintf("Error, unknown function: %d",htf);
- return;
- } break;
+ Dbprintf("Error, unknown function: %d", htf);
+ goto out;
+ }
}
// Send and store the reader command
// falling edge occured halfway the period. with respect to this falling edge,
// we need to wait (T_Wait2 + half_tag_period) when the last was a 'one'.
// All timer values are in terms of T0 units
- while(AT91C_BASE_TC0->TC_CV < T0*(t_wait+(HITAG_T_TAG_HALF_PERIOD*lastbit)));
+ while (AT91C_BASE_TC0->TC_CV < T0*(t_wait+(HITAG_T_TAG_HALF_PERIOD*lastbit)));
//Dbprintf("DEBUG: Sending reader frame");
// Transmit the reader frame
- hitag_reader_send_frame(tx,txlen);
+ hitag_reader_send_frame(tx, txlen);
// Enable and reset external trigger in timer for capturing future frames
AT91C_BASE_TC1->TC_CCR = AT91C_TC_CLKEN | AT91C_TC_SWTRG;
// Add transmitted frame to total count
- if(txlen > 0) {
- frame_count++;
+ if (txlen > 0) {
+ // frame_count++;
if (!bQuiet) {
// 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)) {
if (bQuitTraceFull) {
break;
} else {
}
// Reset values for receiving frames
- memset(rx,0x00,sizeof(rx));
+ memset(rx, 0x00, sizeof(rx));
rxlen = 0;
lastbit = 1;
bSkip = true;
// Receive frame, watch for at most T0*EOF periods
while (AT91C_BASE_TC1->TC_CV < T0*HITAG_T_WAIT_MAX) {
// Check if falling edge in tag modulation is detected
- if(AT91C_BASE_TC1->TC_SR & AT91C_TC_LDRAS) {
+ if (AT91C_BASE_TC1->TC_SR & AT91C_TC_LDRAS) {
// Retrieve the new timing values
int ra = (AT91C_BASE_TC1->TC_RA/T0);
LED_B_ON();
// Capture tag frame (manchester decoding using only falling edges)
- if(ra >= HITAG_T_EOF) {
+ if (ra >= HITAG_T_EOF) {
if (rxlen != 0) {
//Dbprintf("DEBUG: Wierd1");
}
// Capture the T0 periods that have passed since last communication or field drop (reset)
// We always recieve a 'one' first, which has the falling edge after a half period |-_|
- response = ra-HITAG_T_TAG_HALF_PERIOD;
- } else if(ra >= HITAG_T_TAG_CAPTURE_FOUR_HALF) {
+ response = ra - HITAG_T_TAG_HALF_PERIOD;
+ } else if (ra >= HITAG_T_TAG_CAPTURE_FOUR_HALF) {
// Manchester coding example |-_|_-|-_| (101)
//need to test to verify we don't exceed memory...
rxlen++;
rx[rxlen / 8] |= 1 << (7-(rxlen%8));
rxlen++;
- } else if(ra >= HITAG_T_TAG_CAPTURE_THREE_HALF) {
+ } else if (ra >= HITAG_T_TAG_CAPTURE_THREE_HALF) {
// Manchester coding example |_-|...|_-|-_| (0...01)
//need to test to verify we don't exceed memory...
}
lastbit = !lastbit;
bSkip = !bSkip;
- } else if(ra >= HITAG_T_TAG_CAPTURE_TWO_HALF) {
+ } else if (ra >= HITAG_T_TAG_CAPTURE_TWO_HALF) {
// Manchester coding example |_-|_-| (00) or |-_|-_| (11)
//need to test to verify we don't exceed memory...
}
}
//if we saw over 100 wierd values break it probably isn't hitag...
- if (errorCount >100) break;
+ if (errorCount > 100) break;
// We can break this loop if we received the last bit from a frame
if (AT91C_BASE_TC1->TC_CV > T0*HITAG_T_EOF) {
- if (rxlen>0) break;
+ if (rxlen > 0) break;
}
}
}
+
+out:
//Dbprintf("DEBUG: Done waiting for frame");
LED_B_OFF();
//Dbprintf("frame received: %d",frame_count);
//DbpString("All done");
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
- 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) {
- int frame_count;
+void WriterHitag(hitag_function htf, hitag_data *htd, int page) {
+ // int frame_count;
int response;
- byte_t rx[HITAG_FRAME_LEN];
- size_t rxlen=0;
- byte_t txbuf[HITAG_FRAME_LEN];
- byte_t* tx = txbuf;
- size_t txlen=0;
+ uint8_t rx[HITAG_FRAME_LEN];
+ size_t rxlen = 0;
+ uint8_t txbuf[HITAG_FRAME_LEN];
+ uint8_t *tx = txbuf;
+ size_t txlen = 0;
int lastbit;
bool bSkip;
int reset_sof;
//DbpString("Starting Hitag reader family");
// Check configuration
- switch(htf) {
- case WHT2F_CRYPTO:
- {
- DbpString("Authenticating using key:");
- memcpy(key,htd->crypto.key,6); //HACK; 4 or 6?? I read both in the code.
- memcpy(writedata, htd->crypto.data, 4);
- Dbhexdump(6,key,false);
- blocknr = page;
- bQuiet = false;
- bCrypto = false;
- bAuthenticating = false;
- bQuitTraceFull = true;
- writestate = WRITE_STATE_START;
- } break;
- default: {
- Dbprintf("Error, unknown function: %d",htf);
- return;
- } break;
+ switch (htf) {
+ case WHT2F_CRYPTO: {
+ DbpString("Authenticating using key:");
+ memcpy(key, htd->crypto.key, 6); //HACK; 4 or 6?? I read both in the code.
+ memcpy(writedata, htd->crypto.data, 4);
+ Dbhexdump(6, key, false);
+ blocknr = page;
+ bQuiet = false;
+ bCrypto = false;
+ bAuthenticating = false;
+ bQuitTraceFull = true;
+ 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;
+ bAuthenticating = false;
+ writestate = WRITE_STATE_START;
+ }
+ break;
+ default: {
+ Dbprintf("Error, unknown function: %d", htf);
+ return;
+ }
+ break;
}
LED_D_ON();
// Set Frequency divisor which will drive the FPGA and analog mux selection
FpgaSendCommand(FPGA_CMD_SET_DIVISOR, 95); //125Khz
SetAdcMuxFor(GPIO_MUXSEL_LOPKD);
- RELAY_OFF();
// Disable modulation at default, which means enable the field
LOW(GPIO_SSC_DOUT);
AT91C_BASE_TC1->TC_CCR = AT91C_TC_CLKEN | AT91C_TC_SWTRG;
// Reset the received frame, frame count and timing info
- frame_count = 0;
+ // frame_count = 0;
response = 0;
lastbit = 1;
bStop = false;
// Tag specific configuration settings (sof, timings, etc.)
- if (htf < 10){
+ if (htf < 10) {
// hitagS settings
reset_sof = 1;
t_wait = 200;
t_wait = HITAG_T_WAIT_2;
//DbpString("Configured for hitag2 reader");
} else {
- Dbprintf("Error, unknown hitag reader type: %d",htf);
+ Dbprintf("Error, unknown hitag reader type: %d", htf);
return;
}
- while(!bStop && !BUTTON_PRESS()) {
- // Watchdog hit
+ while (!bStop && !BUTTON_PRESS()) {
+
WDT_HIT();
// Check if frame was captured and store it
- if(rxlen > 0) {
- frame_count++;
+ if (rxlen > 0) {
+ // frame_count++;
if (!bQuiet) {
- if (!LogTraceHitag(rx,rxlen,response,0,false)) {
+ if (!LogTraceHitag(rx, rxlen, response, 0, false)) {
DbpString("Trace full");
if (bQuitTraceFull) {
break;
// By default reset the transmission buffer
tx = txbuf;
- switch(htf) {
- case WHT2F_CRYPTO: {
- bStop = !hitag2_crypto(rx,rxlen,tx,&txlen, true);
- } break;
- default: {
- Dbprintf("Error, unknown function: %d",htf);
- return;
- } break;
+ switch (htf) {
+ case WHT2F_CRYPTO: {
+ 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;
+ }
+ break;
}
// Send and store the reader command
// falling edge occured halfway the period. with respect to this falling edge,
// we need to wait (T_Wait2 + half_tag_period) when the last was a 'one'.
// All timer values are in terms of T0 units
- while(AT91C_BASE_TC0->TC_CV < T0*(t_wait+(HITAG_T_TAG_HALF_PERIOD*lastbit)));
+ while (AT91C_BASE_TC0->TC_CV < T0*(t_wait+(HITAG_T_TAG_HALF_PERIOD*lastbit)));
//Dbprintf("DEBUG: Sending reader frame");
// Transmit the reader frame
- hitag_reader_send_frame(tx,txlen);
+ hitag_reader_send_frame(tx, txlen);
- // Enable and reset external trigger in timer for capturing future frames
+ // Enable and reset external trigger in timer for capturing future frames
AT91C_BASE_TC1->TC_CCR = AT91C_TC_CLKEN | AT91C_TC_SWTRG;
// Add transmitted frame to total count
- if(txlen > 0) {
- frame_count++;
+ if (txlen > 0) {
+ // frame_count++;
if (!bQuiet) {
// 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)) {
if (bQuitTraceFull) {
break;
} else {
}
// Reset values for receiving frames
- memset(rx,0x00,sizeof(rx));
+ memset(rx, 0x00, sizeof(rx));
rxlen = 0;
lastbit = 1;
bSkip = true;
// Receive frame, watch for at most T0*EOF periods
while (AT91C_BASE_TC1->TC_CV < T0*HITAG_T_WAIT_MAX) {
// Check if falling edge in tag modulation is detected
- if(AT91C_BASE_TC1->TC_SR & AT91C_TC_LDRAS) {
+ if (AT91C_BASE_TC1->TC_SR & AT91C_TC_LDRAS) {
// Retrieve the new timing values
int ra = (AT91C_BASE_TC1->TC_RA/T0);
LED_B_ON();
// Capture tag frame (manchester decoding using only falling edges)
- if(ra >= HITAG_T_EOF) {
+ if (ra >= HITAG_T_EOF) {
if (rxlen != 0) {
//Dbprintf("DEBUG: Wierd1");
}
// Capture the T0 periods that have passed since last communication or field drop (reset)
// We always recieve a 'one' first, which has the falling edge after a half period |-_|
- response = ra-HITAG_T_TAG_HALF_PERIOD;
- } else if(ra >= HITAG_T_TAG_CAPTURE_FOUR_HALF) {
+ response = ra - HITAG_T_TAG_HALF_PERIOD;
+ } else if (ra >= HITAG_T_TAG_CAPTURE_FOUR_HALF) {
// Manchester coding example |-_|_-|-_| (101)
- //need to test to verify we don't exceed memory...
- //if ( ((rxlen+2) / 8) > HITAG_FRAME_LEN) {
- // break;
- //}
+ // need to test to verify we don't exceed memory...
+ // if ( ((rxlen+2) / 8) > HITAG_FRAME_LEN) {
+ // break;
+ // }
rx[rxlen / 8] |= 0 << (7-(rxlen%8));
rxlen++;
rx[rxlen / 8] |= 1 << (7-(rxlen%8));
rxlen++;
- } else if(ra >= HITAG_T_TAG_CAPTURE_THREE_HALF) {
+ } else if (ra >= HITAG_T_TAG_CAPTURE_THREE_HALF) {
// Manchester coding example |_-|...|_-|-_| (0...01)
- //need to test to verify we don't exceed memory...
- //if ( ((rxlen+2) / 8) > HITAG_FRAME_LEN) {
- // break;
- //}
+ // need to test to verify we don't exceed memory...
+ // if ( ((rxlen+2) / 8) > HITAG_FRAME_LEN) {
+ // break;
+ // }
rx[rxlen / 8] |= 0 << (7-(rxlen%8));
rxlen++;
// We have to skip this half period at start and add the 'one' the second time
}
lastbit = !lastbit;
bSkip = !bSkip;
- } else if(ra >= HITAG_T_TAG_CAPTURE_TWO_HALF) {
+ } else if (ra >= HITAG_T_TAG_CAPTURE_TWO_HALF) {
// Manchester coding example |_-|_-| (00) or |-_|-_| (11)
- //need to test to verify we don't exceed memory...
- //if ( ((rxlen+2) / 8) > HITAG_FRAME_LEN) {
- // break;
- //}
+ // need to test to verify we don't exceed memory...
+ // if ( ((rxlen+2) / 8) > HITAG_FRAME_LEN) {
+ // break;
+ // }
if (tag_sof) {
// Ignore bits that are transmitted during SOF
tag_sof--;
rxlen++;
}
} else {
- //Dbprintf("DEBUG: Wierd2");
+ // Dbprintf("DEBUG: Wierd2");
errorCount++;
- // Ignore wierd value, is to small to mean anything
+ // Ignore wierd value, it is too small to mean anything
}
}
- //if we saw over 100 wierd values break it probably isn't hitag...
- if (errorCount >100) break;
+ // if we saw over 100 wierd values break it probably isn't hitag...
+ if (errorCount > 100) break;
// We can break this loop if we received the last bit from a frame
if (AT91C_BASE_TC1->TC_CV > T0*HITAG_T_EOF) {
- if (rxlen>0) break;
+ if (rxlen > 0) break;
}
}
// 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;
- 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));
}
}
//Dbprintf("DEBUG: Done waiting for frame");
FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
//Dbprintf("frame received: %d",frame_count);
//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);
}
#include <stdbool.h>
#include "hitag.h"
-void SnoopHitag(uint32_t type);
-void SimulateHitagTag(bool tag_mem_supplied, uint8_t* data);
-void ReaderHitag(hitag_function htf, hitag_data* htd);
-void WriterHitag(hitag_function htf, hitag_data* htd, int page);
+extern void SnoopHitag(uint32_t type);
+extern void SimulateHitagTag(bool tag_mem_supplied, uint8_t* data);
+extern void ReaderHitag(hitag_function htf, hitag_data* htd);
+extern void WriterHitag(hitag_function htf, hitag_data* htd, int page);
#endif
#define CRC_PRESET 0xFF
#define CRC_POLYNOM 0x1D
-#define u8 uint8_t
-#define u32 uint32_t
-#define u64 uint64_t
-#define rev8(x) ((((x)>>7)&1)+((((x)>>6)&1)<<1)+((((x)>>5)&1)<<2)+((((x)>>4)&1)<<3)+((((x)>>3)&1)<<4)+((((x)>>2)&1)<<5)+((((x)>>1)&1)<<6)+(((x)&1)<<7))
-#define rev16(x) (rev8 (x)+(rev8 (x>> 8)<< 8))
-#define rev32(x) (rev16(x)+(rev16(x>>16)<<16))
-#define rev64(x) (rev32(x)+(rev32(x>>32)<<32))
-#define bit(x,n) (((x)>>(n))&1)
-#define bit32(x,n) ((((x)[(n)>>5])>>((n)))&1)
-#define inv32(x,i,n) ((x)[(i)>>5]^=((u32)(n))<<((i)&31))
-#define rotl64(x, n) ((((u64)(x))<<((n)&63))+(((u64)(x))>>((0-(n))&63)))
-
static bool bQuiet;
static bool bSuccessful;
static struct hitagS_tag tag;
bool end=false;
// Single bit Hitag2 functions:
-#define i4(x,a,b,c,d) ((u32)((((x)>>(a))&1)+(((x)>>(b))&1)*2+(((x)>>(c))&1)*4+(((x)>>(d))&1)*8))
-static const u32 ht2_f4a = 0x2C79; // 0010 1100 0111 1001
-static const u32 ht2_f4b = 0x6671; // 0110 0110 0111 0001
-static const u32 ht2_f5c = 0x7907287B; // 0111 1001 0000 0111 0010 1000 0111 1011
+#define i4(x,a,b,c,d) ((uint32_t)((((x)>>(a))&1)+(((x)>>(b))&1)*2+(((x)>>(c))&1)*4+(((x)>>(d))&1)*8))
+static const uint32_t ht2_f4a = 0x2C79; // 0010 1100 0111 1001
+static const uint32_t ht2_f4b = 0x6671; // 0110 0110 0111 0001
+static const uint32_t ht2_f5c = 0x7907287B; // 0111 1001 0000 0111 0010 1000 0111 1011
#define ht2bs_4a(a,b,c,d) (~(((a|b)&c)^(a|d)^b))
#define ht2bs_4b(a,b,c,d) (~(((d|c)&(a^b))^(d|a|b)))
#define ht2bs_5c(a,b,c,d,e) (~((((((c^e)|d)&a)^b)&(c^b))^(((d^e)|a)&((d^b)|c))))
-#define uf20bs u32
+#define uf20bs uint32_t
-static u32 f20(const u64 x) {
- u32 i5;
+static uint32_t f20(const uint64_t x) {
+ uint32_t i5;
i5 = ((ht2_f4a >> i4(x, 1, 2, 4, 5)) & 1) * 1
+ ((ht2_f4b >> i4(x, 7, 11, 13, 14)) & 1) * 2
return (ht2_f5c >> i5) & 1;
}
-static u64 hitag2_round(u64 *state) {
- u64 x = *state;
+
+static uint64_t hitag2_init(const uint64_t key, const uint32_t serial, const uint32_t IV) {
+ uint32_t i;
+ uint64_t x = ((key & 0xFFFF) << 32) + serial;
+ for (i = 0; i < 32; i++) {
+ x >>= 1;
+ x += (uint64_t) (f20(x) ^ (((IV >> i) ^ (key >> (i + 16))) & 1)) << 47;
+ }
+ return x;
+}
+
+static uint64_t hitag2_round(uint64_t *state) {
+ uint64_t x = *state;
x = (x >> 1)
+ ((((x >> 0) ^ (x >> 2) ^ (x >> 3) ^ (x >> 6) ^ (x >> 7) ^ (x >> 8)
*state = x;
return f20(x);
}
-static u64 hitag2_init(const u64 key, const u32 serial, const u32 IV) {
- u32 i;
- u64 x = ((key & 0xFFFF) << 32) + serial;
- for (i = 0; i < 32; i++) {
- x >>= 1;
- x += (u64) (f20(x) ^ (((IV >> i) ^ (key >> (i + 16))) & 1)) << 47;
- }
- return x;
-}
-static u32 hitag2_byte(u64 *x) {
- u32 i, c;
+
+static uint32_t hitag2_byte(uint64_t *x) {
+ uint32_t i, c;
for (i = 0, c = 0; i < 8; i++)
- c += (u32) hitag2_round(x) << (i ^ 7);
+ c += (uint32_t) hitag2_round(x) << (i ^ 7);
return c;
}
byte_t rx_air[HITAG_FRAME_LEN];
byte_t page;
int i;
- u64 state;
+ uint64_t state;
unsigned char crc;
// Copy the (original) received frame how it is send over the air
//challenge message received
Dbprintf("Challenge for UID: %X", temp_uid);
temp2++;
- state = hitag2_init(rev64(tag.key), rev32(tag.pages[0][0]),
- rev32(((rx[3] << 24) + (rx[2] << 16) + (rx[1] << 8) + rx[0])));
+ state = hitag2_init(REV64(tag.key), REV32(tag.pages[0][0]),
+ REV32(((rx[3] << 24) + (rx[2] << 16) + (rx[1] << 8) + rx[0])));
Dbprintf(
",{0x%02X, 0x%02X, 0x%02X, 0x%02X, 0x%02X, 0x%02X, 0x%02X, 0x%02X}",
rx[0], rx[1], rx[2], rx[3], rx[4], rx[5], rx[6], rx[7]);
unsigned char uid[32];
byte_t uid1 = 0x00, uid2 = 0x00, uid3 = 0x00, uid4 = 0x00;
unsigned char crc;
- u64 state;
+ uint64_t state;
byte_t auth_ks[4];
byte_t conf_pages[3];
memcpy(rx_air, rx, nbytes(rxlen));
*txlen = 64;
if(end!=true){
if(htf==02||htf==04){ //RHTS_KEY //WHTS_KEY
- state = hitag2_init(rev64(key), rev32(tag.uid), rev32(rnd));
+ state = hitag2_init(REV64(key), REV32(tag.uid), REV32(rnd));
/*
- Dbprintf("key: %02X %02X\n\n", key, rev64(key));
- Dbprintf("tag.uid: %02X %02X\n\n", tag.uid, rev32(tag.uid));
- Dbprintf("rnd: %02X %02X\n\n", rnd, rev32(rnd));
+ Dbprintf("key: %02X %02X\n\n", key, REV64(key));
+ Dbprintf("tag.uid: %02X %02X\n\n", tag.uid, REV32(tag.uid));
+ Dbprintf("rnd: %02X %02X\n\n", rnd, REV32(rnd));
*/
for (i = 0; i < 4; i++) {
auth_ks[i] = hitag2_byte(&state) ^ 0xff;
pwdl0=0;
pwdl1=0;
if(htf==02 || htf==04) { //RHTS_KEY //WHTS_KEY
- state = hitag2_init(rev64(key), rev32(tag.uid), rev32(rnd));
+ state = hitag2_init(REV64(key), REV32(tag.uid), REV32(rnd));
for (i = 0; i < 5; i++) {
hitag2_byte(&state);
}
\r
#include "mifarecmd.h"\r
\r
+#include <stdint.h>\r
+\r
+#include "proxmark3.h"\r
+#include "cmd.h"\r
+#include "crapto1/crapto1.h"\r
+#include "iso14443a.h"\r
+#include "BigBuf.h"\r
+#include "mifareutil.h"\r
+#include "apps.h"\r
+#include "protocols.h"\r
#include "util.h"\r
#include "parity.h"\r
#include "crc.h"\r
#include "fpgaloader.h"\r
\r
-#define HARDNESTED_AUTHENTICATION_TIMEOUT 848 // card times out 1ms after wrong authentication (according to NXP documentation)\r
-#define HARDNESTED_PRE_AUTHENTICATION_LEADTIME 400 // some (non standard) cards need a pause after select before they are ready for first authentication \r
+#define HARDNESTED_AUTHENTICATION_TIMEOUT 848 // card times out 1ms after wrong authentication (according to NXP documentation)\r
+#define HARDNESTED_PRE_AUTHENTICATION_LEADTIME 400 // some (non standard) cards need a pause after select before they are ready for first authentication\r
\r
/*\r
// the block number for the ISO14443-4 PCB\r
\r
while (true) {\r
if(!iso14443a_select_card(uid, NULL, &cuid, true, 0, true)) {\r
- if (MF_DBGLEVEL >= 1) Dbprintf("Can't select card");\r
+ if (MF_DBGLEVEL >= 1) Dbprintf("Can't select card");\r
break;\r
};\r
\r
if(mifare_classic_auth(pcs, cuid, blockNo, keyType, ui64Key, AUTH_FIRST)) {\r
- if (MF_DBGLEVEL >= 1) Dbprintf("Auth error");\r
+ if (MF_DBGLEVEL >= 1) Dbprintf("Auth error");\r
break;\r
};\r
\r
if(mifare_classic_readblock(pcs, cuid, blockNo, dataoutbuf)) {\r
- if (MF_DBGLEVEL >= 1) Dbprintf("Read block error");\r
+ if (MF_DBGLEVEL >= 1) Dbprintf("Read block error");\r
break;\r
};\r
\r
if(mifare_classic_halt(pcs, cuid)) {\r
- if (MF_DBGLEVEL >= 1) Dbprintf("Halt error");\r
+ if (MF_DBGLEVEL >= 1) Dbprintf("Halt error");\r
break;\r
};\r
\r
// ----------------------------- crypto1 destroy\r
crypto1_destroy(pcs);\r
\r
- if (MF_DBGLEVEL >= 2) DbpString("READ BLOCK FINISHED");\r
+ if (MF_DBGLEVEL >= 2) DbpString("READ BLOCK FINISHED");\r
\r
LED_B_ON();\r
cmd_send(CMD_ACK,isOK,0,0,dataoutbuf,16);\r
isOK = 1;\r
if(!iso14443a_select_card(uid, NULL, &cuid, true, 0, true)) {\r
isOK = 0;\r
- if (MF_DBGLEVEL >= 1) Dbprintf("Can't select card");\r
+ if (MF_DBGLEVEL >= 1) Dbprintf("Can't select card");\r
}\r
\r
\r
if(isOK && mifare_classic_auth(pcs, cuid, FirstBlockOfSector(sectorNo), keyType, ui64Key, AUTH_FIRST)) {\r
isOK = 0;\r
- if (MF_DBGLEVEL >= 1) Dbprintf("Auth error");\r
+ if (MF_DBGLEVEL >= 1) Dbprintf("Auth error");\r
}\r
\r
for (uint8_t blockNo = 0; isOK && blockNo < NumBlocksPerSector(sectorNo); blockNo++) {\r
if(mifare_classic_readblock(pcs, cuid, FirstBlockOfSector(sectorNo) + blockNo, dataoutbuf + 16 * blockNo)) {\r
isOK = 0;\r
- if (MF_DBGLEVEL >= 1) Dbprintf("Read sector %2d block %2d error", sectorNo, blockNo);\r
+ if (MF_DBGLEVEL >= 1) Dbprintf("Read sector %2d block %2d error", sectorNo, blockNo);\r
break;\r
}\r
}\r
\r
if(mifare_classic_halt(pcs, cuid)) {\r
- if (MF_DBGLEVEL >= 1) Dbprintf("Halt error");\r
+ if (MF_DBGLEVEL >= 1) Dbprintf("Halt error");\r
}\r
\r
// ----------------------------- crypto1 destroy\r
\r
while (true) {\r
if(!iso14443a_select_card(uid, NULL, &cuid, true, 0, true)) {\r
- if (MF_DBGLEVEL >= 1) Dbprintf("Can't select card");\r
+ if (MF_DBGLEVEL >= 1) Dbprintf("Can't select card");\r
break;\r
};\r
\r
if(mifare_classic_auth(pcs, cuid, blockNo, keyType, ui64Key, AUTH_FIRST)) {\r
- if (MF_DBGLEVEL >= 1) Dbprintf("Auth error");\r
+ if (MF_DBGLEVEL >= 1) Dbprintf("Auth error");\r
break;\r
};\r
\r
if(mifare_classic_writeblock(pcs, cuid, blockNo, blockdata)) {\r
- if (MF_DBGLEVEL >= 1) Dbprintf("Write block error");\r
+ if (MF_DBGLEVEL >= 1) Dbprintf("Write block error");\r
break;\r
};\r
\r
if(mifare_classic_halt(pcs, cuid)) {\r
- if (MF_DBGLEVEL >= 1) Dbprintf("Halt error");\r
+ if (MF_DBGLEVEL >= 1) Dbprintf("Halt error");\r
break;\r
};\r
\r
// ----------------------------- crypto1 destroy\r
crypto1_destroy(pcs);\r
\r
- if (MF_DBGLEVEL >= 2) DbpString("WRITE BLOCK FINISHED");\r
+ if (MF_DBGLEVEL >= 2) DbpString("WRITE BLOCK FINISHED");\r
\r
LED_B_ON();\r
cmd_send(CMD_ACK,isOK,0,0,0,0);\r
if(mifare_ultra_writeblock_compat(blockNo, blockdata)) {\r
if (MF_DBGLEVEL >= 1) Dbprintf("Write block error");\r
OnError(0);\r
- return; };\r
+ return; };\r
\r
if(mifare_ultra_halt()) {\r
if (MF_DBGLEVEL >= 1) Dbprintf("Halt error");\r
if (!have_uid) { // need a full select cycle to get the uid first\r
iso14a_card_select_t card_info;\r
if(!iso14443a_select_card(uid, &card_info, &cuid, true, 0, true)) {\r
- if (MF_DBGLEVEL >= 1) Dbprintf("AcquireNonces: Can't select card (ALL)");\r
+ if (MF_DBGLEVEL >= 1) Dbprintf("AcquireNonces: Can't select card (ALL)");\r
continue;\r
}\r
switch (card_info.uidlen) {\r
have_uid = true;\r
} else { // no need for anticollision. We can directly select the card\r
if(!iso14443a_select_card(uid, NULL, NULL, false, cascade_levels, true)) {\r
- if (MF_DBGLEVEL >= 1) Dbprintf("AcquireNonces: Can't select card (UID)");\r
+ if (MF_DBGLEVEL >= 1) Dbprintf("AcquireNonces: Can't select card (UID)");\r
continue;\r
}\r
}\r
\r
uint32_t nt1;\r
if (mifare_classic_authex(pcs, cuid, blockNo, keyType, ui64Key, AUTH_FIRST, &nt1, NULL)) {\r
- if (MF_DBGLEVEL >= 1) Dbprintf("AcquireNonces: Auth1 error");\r
+ if (MF_DBGLEVEL >= 1) Dbprintf("AcquireNonces: Auth1 error");\r
continue;\r
}\r
\r
// nested authentication\r
uint16_t len = mifare_sendcmd_short(pcs, AUTH_NESTED, 0x60 + (targetKeyType & 0x01), targetBlockNo, receivedAnswer, par_enc, NULL);\r
if (len != 4) {\r
- if (MF_DBGLEVEL >= 1) Dbprintf("AcquireNonces: Auth2 error len=%d", len);\r
+ if (MF_DBGLEVEL >= 1) Dbprintf("AcquireNonces: Auth2 error len=%d", len);\r
continue;\r
}\r
\r
ReaderTransmit(dummy_answer, 1, NULL);\r
\r
timeout = GetCountSspClk() + HARDNESTED_AUTHENTICATION_TIMEOUT;\r
- \r
+\r
num_nonces++;\r
if (num_nonces % 2) {\r
memcpy(buf+i, receivedAnswer, 4);\r
cmd_send(CMD_ACK, isOK, cuid, num_nonces, buf, sizeof(buf));\r
LED_B_OFF();\r
\r
- if (MF_DBGLEVEL >= 3) DbpString("AcquireEncryptedNonces finished");\r
+ if (MF_DBGLEVEL >= 3) DbpString("AcquireEncryptedNonces finished");\r
\r
if (field_off) {\r
FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);\r
int16_t isOK = 0;\r
#define NESTED_MAX_TRIES 12\r
uint16_t unsuccessfull_tries = 0;\r
- if (calibrate) { // for first call only. Otherwise reuse previous calibration\r
+ if (calibrate) { // for first call only. Otherwise reuse previous calibration\r
LED_B_ON();\r
WDT_HIT();\r
\r
\r
// prepare next select. No need to power down the card.\r
if(mifare_classic_halt(pcs, cuid)) {\r
- if (MF_DBGLEVEL >= 1) Dbprintf("Nested: Halt error");\r
+ if (MF_DBGLEVEL >= 1) Dbprintf("Nested: Halt error");\r
rtr--;\r
continue;\r
}\r
\r
if(!iso14443a_select_card(uid, NULL, &cuid, true, 0, true)) {\r
- if (MF_DBGLEVEL >= 1) Dbprintf("Nested: Can't select card");\r
+ if (MF_DBGLEVEL >= 1) Dbprintf("Nested: Can't select card");\r
rtr--;\r
continue;\r
};\r
\r
auth1_time = 0;\r
if(mifare_classic_authex(pcs, cuid, blockNo, keyType, ui64Key, AUTH_FIRST, &nt1, &auth1_time)) {\r
- if (MF_DBGLEVEL >= 1) Dbprintf("Nested: Auth1 error");\r
+ if (MF_DBGLEVEL >= 1) Dbprintf("Nested: Auth1 error");\r
rtr--;\r
continue;\r
};\r
auth2_time = 0;\r
}\r
if(mifare_classic_authex(pcs, cuid, blockNo, keyType, ui64Key, AUTH_NESTED, &nt2, &auth2_time)) {\r
- if (MF_DBGLEVEL >= 1) Dbprintf("Nested: Auth2 error");\r
+ if (MF_DBGLEVEL >= 1) Dbprintf("Nested: Auth2 error");\r
rtr--;\r
continue;\r
};\r
\r
- nttmp = prng_successor(nt1, 100); //NXP Mifare is typical around 840,but for some unlicensed/compatible mifare card this can be 160\r
+ nttmp = prng_successor(nt1, 100); //NXP Mifare is typical around 840,but for some unlicensed/compatible mifare card this can be 160\r
for (i = 101; i < 1200; i++) {\r
nttmp = prng_successor(nttmp, 1);\r
if (nttmp == nt2) break;\r
if (MF_DBGLEVEL >= 3) Dbprintf("Nested: calibrating... ntdist=%d", i);\r
} else {\r
unsuccessfull_tries++;\r
- if (unsuccessfull_tries > NESTED_MAX_TRIES) { // card isn't vulnerable to nested attack (random numbers are not predictable)\r
+ if (unsuccessfull_tries > NESTED_MAX_TRIES) { // card isn't vulnerable to nested attack (random numbers are not predictable)\r
isOK = -3;\r
}\r
}\r
\r
// prepare next select. No need to power down the card.\r
if(mifare_classic_halt(pcs, cuid)) {\r
- if (MF_DBGLEVEL >= 1) Dbprintf("Nested: Halt error");\r
+ if (MF_DBGLEVEL >= 1) Dbprintf("Nested: Halt error");\r
continue;\r
}\r
\r
if(!iso14443a_select_card(uid, NULL, &cuid, true, 0, true)) {\r
- if (MF_DBGLEVEL >= 1) Dbprintf("Nested: Can't select card");\r
+ if (MF_DBGLEVEL >= 1) Dbprintf("Nested: Can't select card");\r
continue;\r
};\r
\r
auth1_time = 0;\r
if(mifare_classic_authex(pcs, cuid, blockNo, keyType, ui64Key, AUTH_FIRST, &nt1, &auth1_time)) {\r
- if (MF_DBGLEVEL >= 1) Dbprintf("Nested: Auth1 error");\r
+ if (MF_DBGLEVEL >= 1) Dbprintf("Nested: Auth1 error");\r
continue;\r
};\r
\r
auth2_time = auth1_time + delta_time;\r
len = mifare_sendcmd_short(pcs, AUTH_NESTED, 0x60 + (targetKeyType & 0x01), targetBlockNo, receivedAnswer, par, &auth2_time);\r
if (len != 4) {\r
- if (MF_DBGLEVEL >= 1) Dbprintf("Nested: Auth2 error len=%d", len);\r
+ if (MF_DBGLEVEL >= 1) Dbprintf("Nested: Auth2 error len=%d", len);\r
continue;\r
};\r
\r
ks1 = nt2 ^ nttest;\r
\r
if (valid_nonce(nttest, nt2, ks1, par_array)){\r
- if (ncount > 0) { // we are only interested in disambiguous nonces, try again\r
+ if (ncount > 0) { // we are only interested in disambiguous nonces, try again\r
if (MF_DBGLEVEL >= 3) Dbprintf("Nonce#%d: dismissed (ambigous), ntdist=%d", i+1, j);\r
target_nt[i] = 0;\r
break;\r
cmd_send(CMD_ACK, isOK, 0, targetBlockNo + (targetKeyType * 0x100), buf, sizeof(buf));\r
LED_B_OFF();\r
\r
- if (MF_DBGLEVEL >= 3) DbpString("NESTED FINISHED");\r
+ if (MF_DBGLEVEL >= 3) DbpString("NESTED FINISHED");\r
\r
FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);\r
LEDsoff();\r
if (set14aTimeout){\r
iso14a_set_timeout(set14aTimeout * 10); // timeout: ms = x/106 35-minimum, 50-OK 106-recommended 500-safe\r
}\r
- \r
+\r
if (multisectorCheck) {\r
TKeyIndex keyIndex = {{0}};\r
uint8_t sectorCnt = blockNo;\r
LED_A_OFF();\r
}\r
\r
+\r
+//-----------------------------------------------------------------------------\r
+// MIFARE Personalize UID. Only for Mifare Classic EV1 7Byte UID\r
+//-----------------------------------------------------------------------------\r
+void MifarePersonalizeUID(uint8_t keyType, uint8_t perso_option, uint8_t *data) {\r
+\r
+ uint8_t uid[10];\r
+ uint32_t cuid;\r
+ struct Crypto1State mpcs = {0, 0};\r
+ struct Crypto1State *pcs;\r
+ pcs = &mpcs;\r
+\r
+ LED_A_ON();\r
+ clear_trace();\r
+\r
+ iso14443a_setup(FPGA_HF_ISO14443A_READER_LISTEN);\r
+\r
+ bool isOK = false;\r
+ while (true) {\r
+ if (!iso14443a_select_card(uid, NULL, &cuid, true, 0, true)) {\r
+ if (MF_DBGLEVEL >= 1) Dbprintf("Can't select card");\r
+ break;\r
+ }\r
+\r
+ uint8_t block_number = 0;\r
+ uint64_t key = bytes_to_num(data, 6);\r
+ if (mifare_classic_auth(pcs, cuid, block_number, keyType, key, AUTH_FIRST)) {\r
+ if (MF_DBGLEVEL >= 1) Dbprintf("Auth error");\r
+ break;\r
+ }\r
+\r
+ uint8_t receivedAnswer[MAX_MIFARE_FRAME_SIZE];\r
+ uint8_t receivedAnswerPar[MAX_MIFARE_PARITY_SIZE];\r
+ int len = mifare_sendcmd_short(pcs, true, MIFARE_EV1_PERSONAL_UID, perso_option, receivedAnswer, receivedAnswerPar, NULL);\r
+ if (len != 1 || receivedAnswer[0] != CARD_ACK) {\r
+ if (MF_DBGLEVEL >= 1) Dbprintf("Cmd Error: %02x", receivedAnswer[0]);\r
+ break;;\r
+ }\r
+ isOK = true;\r
+ break;\r
+ }\r
+\r
+ FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);\r
+ LED_D_OFF();\r
+\r
+ crypto1_destroy(pcs);\r
+\r
+ if (MF_DBGLEVEL >= 2) DbpString("PERSONALIZE UID FINISHED");\r
+\r
+ cmd_send(CMD_ACK, isOK, 0, 0, NULL, 0);\r
+\r
+ LED_A_OFF();\r
+}\r
+\r
//-----------------------------------------------------------------------------\r
// MIFARE commands set debug level\r
//\r
\r
if(!iso14443a_select_card(uid, NULL, &cuid, true, 0, true)) {\r
isOK = false;\r
- if (MF_DBGLEVEL >= 1) Dbprintf("Can't select card");\r
+ if (MF_DBGLEVEL >= 1) Dbprintf("Can't select card");\r
}\r
\r
for (uint8_t sectorNo = 0; isOK && sectorNo < numSectors; sectorNo++) {\r
if (sectorNo == 0){\r
if(isOK && mifare_classic_auth(pcs, cuid, FirstBlockOfSector(sectorNo), keyType, ui64Key, AUTH_FIRST)) {\r
isOK = false;\r
- if (MF_DBGLEVEL >= 1) Dbprintf("Sector[%2d]. Auth error", sectorNo);\r
+ if (MF_DBGLEVEL >= 1) Dbprintf("Sector[%2d]. Auth error", sectorNo);\r
break;\r
}\r
} else {\r
if(isOK && mifare_classic_auth(pcs, cuid, FirstBlockOfSector(sectorNo), keyType, ui64Key, AUTH_NESTED)) {\r
isOK = false;\r
- if (MF_DBGLEVEL >= 1) Dbprintf("Sector[%2d]. Auth nested error", sectorNo);\r
+ if (MF_DBGLEVEL >= 1) Dbprintf("Sector[%2d]. Auth nested error", sectorNo);\r
break;\r
}\r
}\r
for (uint8_t blockNo = 0; isOK && blockNo < NumBlocksPerSector(sectorNo); blockNo++) {\r
if(isOK && mifare_classic_readblock(pcs, cuid, FirstBlockOfSector(sectorNo) + blockNo, dataoutbuf)) {\r
isOK = false;\r
- if (MF_DBGLEVEL >= 1) Dbprintf("Error reading sector %2d block %2d", sectorNo, blockNo);\r
+ if (MF_DBGLEVEL >= 1) Dbprintf("Error reading sector %2d block %2d", sectorNo, blockNo);\r
break;\r
};\r
if (isOK) {\r
if (blockNo < NumBlocksPerSector(sectorNo) - 1) {\r
emlSetMem(dataoutbuf, FirstBlockOfSector(sectorNo) + blockNo, 1);\r
- } else { // sector trailer, keep the keys, set only the AC\r
+ } else { // sector trailer, keep the keys, set only the AC\r
emlGetMem(dataoutbuf2, FirstBlockOfSector(sectorNo) + blockNo, 1);\r
memcpy(&dataoutbuf2[6], &dataoutbuf[6], 4);\r
emlSetMem(dataoutbuf2, FirstBlockOfSector(sectorNo) + blockNo, 1);\r
}\r
\r
if(mifare_classic_halt(pcs, cuid)) {\r
- if (MF_DBGLEVEL >= 1) Dbprintf("Halt error");\r
+ if (MF_DBGLEVEL >= 1) Dbprintf("Halt error");\r
};\r
\r
// ----------------------------- crypto1 destroy\r
bool needWipe = cmdParams & 0x01;\r
bool needFill = cmdParams & 0x02;\r
bool gen1b = cmdParams & 0x04;\r
- \r
+\r
uint8_t receivedAnswer[MAX_MIFARE_FRAME_SIZE];\r
uint8_t receivedAnswerPar[MAX_MIFARE_PARITY_SIZE];\r
- \r
+\r
uint8_t block0[16] = {0x01, 0x02, 0x03, 0x04, 0x04, 0x08, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xBE, 0xAF};\r
uint8_t block1[16] = {0x00};\r
uint8_t blockK[16] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x08, 0x77, 0x8F, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF};\r
uint8_t d_block[18] = {0x00};\r
- \r
+\r
// card commands\r
uint8_t wupC1[] = { 0x40 };\r
uint8_t wupC2[] = { 0x43 };\r
uint8_t wipeC[] = { 0x41 };\r
- \r
+\r
// iso14443 setup\r
LED_A_ON();\r
LED_B_OFF();\r
// tracing\r
clear_trace();\r
set_tracing(true);\r
- \r
+\r
while (true){\r
// wipe\r
if (needWipe){\r
ReaderTransmitBitsPar(wupC1,7,0, NULL);\r
- if(!ReaderReceive(receivedAnswer, receivedAnswerPar) || (receivedAnswer[0] != 0x0a)) {\r
- if (MF_DBGLEVEL >= 1) Dbprintf("wupC1 error");\r
+ if(!ReaderReceive(receivedAnswer, receivedAnswerPar) || (receivedAnswer[0] != CARD_ACK)) {\r
+ if (MF_DBGLEVEL >= 1) Dbprintf("wupC1 error");\r
break;\r
};\r
\r
ReaderTransmit(wipeC, sizeof(wipeC), NULL);\r
- if(!ReaderReceive(receivedAnswer, receivedAnswerPar) || (receivedAnswer[0] != 0x0a)) {\r
- if (MF_DBGLEVEL >= 1) Dbprintf("wipeC error");\r
+ if(!ReaderReceive(receivedAnswer, receivedAnswerPar) || (receivedAnswer[0] != CARD_ACK)) {\r
+ if (MF_DBGLEVEL >= 1) Dbprintf("wipeC error");\r
break;\r
};\r
\r
if(mifare_classic_halt(NULL, 0)) {\r
- if (MF_DBGLEVEL > 2) Dbprintf("Halt error");\r
+ if (MF_DBGLEVEL > 2) Dbprintf("Halt error");\r
};\r
};\r
- \r
+\r
// put default data\r
if (needFill){\r
// select commands\r
ReaderTransmitBitsPar(wupC1, 7, 0, NULL);\r
\r
- // gen1b magic tag : do no issue wupC2 and don't expect 0x0a response after SELECT_UID (after getting UID from chip in 'hf mf csetuid' command)\r
- if (!gen1b) { \r
+ // gen1b magic tag : do no issue wupC2 and don't expect CARD_ACK response after SELECT_UID (after getting UID from chip in 'hf mf csetuid' command)\r
+ if (!gen1b) {\r
\r
- if(!ReaderReceive(receivedAnswer, receivedAnswerPar) || (receivedAnswer[0] != 0x0a)) {\r
- if (MF_DBGLEVEL >= 1) Dbprintf("wupC1 error");\r
+ if(!ReaderReceive(receivedAnswer, receivedAnswerPar) || (receivedAnswer[0] != CARD_ACK)) {\r
+ if (MF_DBGLEVEL >= 1) Dbprintf("wupC1 error");\r
break;\r
};\r
\r
ReaderTransmit(wupC2, sizeof(wupC2), NULL);\r
- if(!ReaderReceive(receivedAnswer, receivedAnswerPar) || (receivedAnswer[0] != 0x0a)) {\r
- if (MF_DBGLEVEL >= 1) Dbprintf("wupC2 error");\r
+ if(!ReaderReceive(receivedAnswer, receivedAnswerPar) || (receivedAnswer[0] != CARD_ACK)) {\r
+ if (MF_DBGLEVEL >= 1) Dbprintf("wupC2 error");\r
break;\r
};\r
}\r
\r
// send blocks command\r
for (int blockNo = 0; blockNo < numBlocks; blockNo++) {\r
- if ((mifare_sendcmd_short(NULL, 0, 0xA0, blockNo, receivedAnswer, receivedAnswerPar, NULL) != 1) || (receivedAnswer[0] != 0x0a)) {\r
- if (MF_DBGLEVEL >= 1) Dbprintf("write block send command error");\r
+ if ((mifare_sendcmd_short(NULL, 0, 0xA0, blockNo, receivedAnswer, receivedAnswerPar, NULL) != 1) || (receivedAnswer[0] != CARD_ACK)) {\r
+ if (MF_DBGLEVEL >= 1) Dbprintf("write block send command error");\r
break;\r
};\r
- \r
+\r
// check type of block and add crc\r
if (!isBlockTrailer(blockNo)){\r
memcpy(d_block, block1, 16);\r
\r
// send write command\r
ReaderTransmit(d_block, sizeof(d_block), NULL);\r
- if ((ReaderReceive(receivedAnswer, receivedAnswerPar) != 1) || (receivedAnswer[0] != 0x0a)) {\r
- if (MF_DBGLEVEL >= 1) Dbprintf("write block send data error");\r
+ if ((ReaderReceive(receivedAnswer, receivedAnswerPar) != 1) || (receivedAnswer[0] != CARD_ACK)) {\r
+ if (MF_DBGLEVEL >= 1) Dbprintf("write block send data error");\r
break;\r
};\r
}\r
- \r
+\r
// halt\r
- // do no issue halt command for gen1b \r
+ // do no issue halt command for gen1b\r
if (!gen1b) {\r
if (mifare_classic_halt(NULL, 0)) {\r
- if (MF_DBGLEVEL > 2) Dbprintf("Halt error");\r
+ if (MF_DBGLEVEL > 2) Dbprintf("Halt error");\r
break;\r
}\r
}\r
}\r
break;\r
- } \r
+ }\r
\r
// send USB response\r
LED_B_ON();\r
cmd_send(CMD_ACK,isOK,0,0,NULL,0);\r
LED_B_OFF();\r
- \r
+\r
// reset fpga\r
FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);\r
LEDsoff();\r
- \r
+\r
return;\r
}\r
\r
// get UID from chip\r
if (workFlags & 0x01) {\r
if(!iso14443a_select_card(uid, NULL, &cuid, true, 0, true)) {\r
- if (MF_DBGLEVEL >= 1) Dbprintf("Can't select card");\r
+ if (MF_DBGLEVEL >= 1) Dbprintf("Can't select card");\r
// Continue, if we set wrong UID or wrong UID checksum or some ATQA or SAK we will can't select card. But we need to write block 0 to make card work.\r
//break;\r
};\r
\r
if(mifare_classic_halt(NULL, cuid)) {\r
- if (MF_DBGLEVEL > 2) Dbprintf("Halt error");\r
+ if (MF_DBGLEVEL > 2) Dbprintf("Halt error");\r
// Continue, some magic tags misbehavies and send an answer to it.\r
// break;\r
};\r
// Wipe command don't work with gen1b\r
if (needWipe && !(workFlags & 0x40)){\r
ReaderTransmitBitsPar(wupC1,7,0, NULL);\r
- if(!ReaderReceive(receivedAnswer, receivedAnswerPar) || (receivedAnswer[0] != 0x0a)) {\r
- if (MF_DBGLEVEL >= 1) Dbprintf("wupC1 error");\r
+ if(!ReaderReceive(receivedAnswer, receivedAnswerPar) || (receivedAnswer[0] != CARD_ACK)) {\r
+ if (MF_DBGLEVEL >= 1) Dbprintf("wupC1 error");\r
break;\r
};\r
\r
ReaderTransmit(wipeC, sizeof(wipeC), NULL);\r
- if(!ReaderReceive(receivedAnswer, receivedAnswerPar) || (receivedAnswer[0] != 0x0a)) {\r
- if (MF_DBGLEVEL >= 1) Dbprintf("wipeC error");\r
+ if(!ReaderReceive(receivedAnswer, receivedAnswerPar) || (receivedAnswer[0] != CARD_ACK)) {\r
+ if (MF_DBGLEVEL >= 1) Dbprintf("wipeC error");\r
break;\r
};\r
\r
if(mifare_classic_halt(NULL, 0)) {\r
- if (MF_DBGLEVEL > 2) Dbprintf("Halt error");\r
+ if (MF_DBGLEVEL > 2) Dbprintf("Halt error");\r
// Continue, some magic tags misbehavies and send an answer to it.\r
- // break;\r
+ // break;\r
};\r
};\r
\r
if (workFlags & 0x02) {\r
ReaderTransmitBitsPar(wupC1,7,0, NULL);\r
\r
- // gen1b magic tag : do no issue wupC2 and don't expect 0x0a response after SELECT_UID (after getting UID from chip in 'hf mf csetuid' command)\r
+ // gen1b magic tag : do no issue wupC2 and don't expect CARD_ACK response after SELECT_UID (after getting UID from chip in 'hf mf csetuid' command)\r
if (!(workFlags & 0x40)) {\r
\r
- if(!ReaderReceive(receivedAnswer, receivedAnswerPar) || (receivedAnswer[0] != 0x0a)) {\r
- if (MF_DBGLEVEL >= 1) Dbprintf("wupC1 error");\r
+ if(!ReaderReceive(receivedAnswer, receivedAnswerPar) || (receivedAnswer[0] != CARD_ACK)) {\r
+ if (MF_DBGLEVEL >= 1) Dbprintf("wupC1 error");\r
break;\r
};\r
\r
ReaderTransmit(wupC2, sizeof(wupC2), NULL);\r
- if(!ReaderReceive(receivedAnswer, receivedAnswerPar) || (receivedAnswer[0] != 0x0a)) {\r
- if (MF_DBGLEVEL >= 1) Dbprintf("wupC2 error");\r
+ if(!ReaderReceive(receivedAnswer, receivedAnswerPar) || (receivedAnswer[0] != CARD_ACK)) {\r
+ if (MF_DBGLEVEL >= 1) Dbprintf("wupC2 error");\r
break;\r
};\r
}\r
}\r
\r
- if ((mifare_sendcmd_short(NULL, 0, 0xA0, blockNo, receivedAnswer, receivedAnswerPar, NULL) != 1) || (receivedAnswer[0] != 0x0a)) {\r
- if (MF_DBGLEVEL >= 1) Dbprintf("write block send command error");\r
+ if ((mifare_sendcmd_short(NULL, 0, 0xA0, blockNo, receivedAnswer, receivedAnswerPar, NULL) != 1) || (receivedAnswer[0] != CARD_ACK)) {\r
+ if (MF_DBGLEVEL >= 1) Dbprintf("write block send command error");\r
break;\r
};\r
\r
AppendCrc14443a(d_block, 16);\r
\r
ReaderTransmit(d_block, sizeof(d_block), NULL);\r
- if ((ReaderReceive(receivedAnswer, receivedAnswerPar) != 1) || (receivedAnswer[0] != 0x0a)) {\r
- if (MF_DBGLEVEL >= 1) Dbprintf("write block send data error");\r
+ if ((ReaderReceive(receivedAnswer, receivedAnswerPar) != 1) || (receivedAnswer[0] != CARD_ACK)) {\r
+ if (MF_DBGLEVEL >= 1) Dbprintf("write block send data error");\r
break;\r
};\r
\r
// do no issue halt command for gen1b magic tag (#db# halt error. response len: 1)\r
if (!(workFlags & 0x40)) {\r
if (mifare_classic_halt(NULL, 0)) {\r
- if (MF_DBGLEVEL > 2) Dbprintf("Halt error");\r
+ if (MF_DBGLEVEL > 2) Dbprintf("Halt error");\r
// Continue, some magic tags misbehavies and send an answer to it.\r
// break;\r
}\r
while (true) {\r
if (workFlags & 0x02) {\r
ReaderTransmitBitsPar(wupC1,7,0, NULL);\r
- if(!ReaderReceive(receivedAnswer, receivedAnswerPar) || (receivedAnswer[0] != 0x0a)) {\r
- if (MF_DBGLEVEL >= 1) Dbprintf("wupC1 error");\r
+ if(!ReaderReceive(receivedAnswer, receivedAnswerPar) || (receivedAnswer[0] != CARD_ACK)) {\r
+ if (MF_DBGLEVEL >= 1) Dbprintf("wupC1 error");\r
break;\r
};\r
// do no issue for gen1b magic tag\r
if (!(workFlags & 0x40)) {\r
ReaderTransmit(wupC2, sizeof(wupC2), NULL);\r
- if(!ReaderReceive(receivedAnswer, receivedAnswerPar) || (receivedAnswer[0] != 0x0a)) {\r
- if (MF_DBGLEVEL >= 1) Dbprintf("wupC2 error");\r
+ if(!ReaderReceive(receivedAnswer, receivedAnswerPar) || (receivedAnswer[0] != CARD_ACK)) {\r
+ if (MF_DBGLEVEL >= 1) Dbprintf("wupC2 error");\r
break;\r
};\r
}\r
\r
// read block\r
if ((mifare_sendcmd_short(NULL, 0, 0x30, blockNo, receivedAnswer, receivedAnswerPar, NULL) != 18)) {\r
- if (MF_DBGLEVEL >= 1) Dbprintf("read block send command error");\r
+ if (MF_DBGLEVEL >= 1) Dbprintf("read block send command error");\r
break;\r
};\r
memcpy(data, receivedAnswer, 18);\r
// do no issue halt command for gen1b magic tag (#db# halt error. response len: 1)\r
if (!(workFlags & 0x40)) {\r
if (mifare_classic_halt(NULL, cuid)) {\r
- if (MF_DBGLEVEL > 1) Dbprintf("Halt error");\r
+ if (MF_DBGLEVEL > 1) Dbprintf("Halt error");\r
// Continue, some magic tags misbehavies and send an answer to it.\r
- // break;\r
+ // break;\r
}\r
}\r
}\r
\r
uint8_t receivedAnswer[MAX_MIFARE_FRAME_SIZE];\r
uint8_t receivedAnswerPar[MAX_MIFARE_PARITY_SIZE];\r
- \r
+\r
LED_A_ON();\r
LED_B_OFF();\r
LED_C_OFF();\r
iso14443a_setup(FPGA_HF_ISO14443A_READER_LISTEN);\r
\r
clear_trace();\r
- set_tracing(true); \r
+ set_tracing(true);\r
\r
ReaderTransmitBitsPar(wupC1,7,0, NULL);\r
- if(ReaderReceive(receivedAnswer, receivedAnswerPar) && (receivedAnswer[0] == 0x0a)) {\r
+ if(ReaderReceive(receivedAnswer, receivedAnswerPar) && (receivedAnswer[0] == CARD_ACK)) {\r
isOK = 2;\r
\r
ReaderTransmit(wupC2, sizeof(wupC2), NULL);\r
- if(ReaderReceive(receivedAnswer, receivedAnswerPar) && (receivedAnswer[0] == 0x0a)) {\r
+ if(ReaderReceive(receivedAnswer, receivedAnswerPar) && (receivedAnswer[0] == CARD_ACK)) {\r
isOK = 1;\r
};\r
};\r
\r
// From iceman1001: removed the if, since some magic tags misbehavies and send an answer to it.\r
mifare_classic_halt(NULL, 0);\r
- \r
+\r
LED_B_ON();\r
cmd_send(CMD_ACK,isOK,0,0,0,0);\r
LED_B_OFF();\r
\r
FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);\r
- LEDsoff(); \r
+ LEDsoff();\r
}\r
\r
//\r
}\r
\r
if (MF_DBGLEVEL >= MF_DBG_EXTENDED) DbpString("AUTH 1 FINISHED");\r
- cmd_send(CMD_ACK,1,cuid,0,dataout, sizeof(dataout));\r
+ cmd_send(CMD_ACK,1,cuid,0,dataout, sizeof(dataout));\r
}\r
\r
void Mifare_DES_Auth2(uint32_t arg0, uint8_t *datain){\r
// Routines to support ISO 14443 type A.\r
//-----------------------------------------------------------------------------\r
\r
-#ifndef __MIFARECMD_H\r
-#define __MIFARECMD_H\r
+#ifndef MIFARECMD_H__\r
+#define MIFARECMD_H__\r
\r
-#include "proxmark3.h"\r
-#include "apps.h"\r
-#include "util.h"\r
+#include <stdint.h>\r
\r
-#include "iso14443crc.h"\r
-#include "iso14443a.h"\r
-#include "crapto1/crapto1.h"\r
-#include "mifareutil.h"\r
-#include "common.h"\r
+extern void MifareReadBlock(uint8_t arg0, uint8_t arg1, uint8_t arg2, uint8_t *data);\r
+extern void MifareUReadBlock(uint8_t arg0, uint8_t arg1, uint8_t *datain);\r
+extern void MifareUC_Auth(uint8_t arg0, uint8_t *datain);\r
+extern void MifareUReadCard(uint8_t arg0, uint16_t arg1, uint8_t arg2, uint8_t *datain);\r
+extern void MifareReadSector(uint8_t arg0, uint8_t arg1, uint8_t arg2, uint8_t *datain);\r
+extern void MifareWriteBlock(uint8_t arg0, uint8_t arg1, uint8_t arg2, uint8_t *datain);\r
+//extern void MifareUWriteBlockCompat(uint8_t arg0,uint8_t *datain);\r
+extern void MifareUWriteBlock(uint8_t arg0, uint8_t arg1, uint8_t *datain);\r
+extern void MifareNested(uint32_t arg0, uint32_t arg1, uint32_t arg2, uint8_t *datain);\r
+extern void MifareAcquireEncryptedNonces(uint32_t arg0, uint32_t arg1, uint32_t flags, uint8_t *datain);\r
+extern void MifareChkKeys(uint16_t arg0, uint16_t arg1, uint8_t arg2, uint8_t *datain);\r
+extern void MifareSetDbgLvl(uint32_t arg0, uint32_t arg1, uint32_t arg2, uint8_t *datain);\r
+extern void MifareEMemClr(uint32_t arg0, uint32_t arg1, uint32_t arg2, uint8_t *datain);\r
+extern void MifareEMemSet(uint32_t arg0, uint32_t arg1, uint32_t arg2, uint8_t *datain);\r
+extern void MifareEMemGet(uint32_t arg0, uint32_t arg1, uint32_t arg2, uint8_t *datain);\r
+extern void MifareECardLoad(uint32_t arg0, uint32_t arg1, uint32_t arg2, uint8_t *datain);\r
+extern void MifareCWipe(uint32_t arg0, uint32_t arg1, uint32_t arg2, uint8_t *datain); // Work with "magic Chinese" card\r
+extern void MifareCSetBlock(uint32_t arg0, uint32_t arg1, uint32_t arg2, uint8_t *datain);\r
+extern void MifareCGetBlock(uint32_t arg0, uint32_t arg1, uint32_t arg2, uint8_t *datain);\r
+extern void MifareCIdent(); // is "magic chinese" card?\r
+extern void MifareUSetPwd(uint8_t arg0, uint8_t *datain);\r
+extern void MifarePersonalizeUID(uint8_t keyType, uint8_t perso_option, uint8_t *datain);\r
\r
+//desfire\r
+extern void Mifare_DES_Auth1(uint8_t arg0,uint8_t *datain);\r
+extern void Mifare_DES_Auth2(uint32_t arg0, uint8_t *datain);\r
\r
-#endif
\ No newline at end of file
+#endif\r
#include "iso14443a.h"\r
#include "crapto1/crapto1.h"\r
#include "mbedtls/des.h"\r
+#include "protocols.h"\r
\r
int MF_DBGLEVEL = MF_DBG_INFO;\r
\r
uint8_t receivedAnswerPar[MAX_MIFARE_PARITY_SIZE];\r
\r
// Transmit MIFARE_CLASSIC_AUTH\r
- len = mifare_sendcmd_short(pcs, isNested, 0x60 + (keyType & 0x01), blockNo, receivedAnswer, receivedAnswerPar, timing);\r
+ len = mifare_sendcmd_short(pcs, isNested, keyType & 0x01 ? MIFARE_AUTH_KEYB : MIFARE_AUTH_KEYA, blockNo, receivedAnswer, receivedAnswerPar, timing);\r
if (MF_DBGLEVEL >= 4) Dbprintf("rand tag nonce len: %x", len);\r
if (len != 4) return 1;\r
\r
uint8_t receivedAnswerPar[MAX_MIFARE_PARITY_SIZE];\r
\r
// command MIFARE_CLASSIC_READBLOCK\r
- len = mifare_sendcmd_short(pcs, 1, 0x30, blockNo, receivedAnswer, receivedAnswerPar, NULL);\r
+ len = mifare_sendcmd_short(pcs, 1, MIFARE_CMD_READBLOCK, blockNo, receivedAnswer, receivedAnswerPar, NULL);\r
if (len == 1) {\r
if (MF_DBGLEVEL >= 1) Dbprintf("Cmd Error: %02x", receivedAnswer[0]);\r
return 1;\r
\r
if (MF_DBGLEVEL >= MF_DBG_EXTENDED)\r
Dbprintf("EV1 Auth : %02x%02x%02x%02x", key[0], key[1], key[2], key[3]);\r
- len = mifare_sendcmd(0x1B, key, sizeof(key), resp, respPar, NULL);\r
+ len = mifare_sendcmd(MIFARE_ULEV1_AUTH, key, sizeof(key), resp, respPar, NULL);\r
//len = mifare_sendcmd_short_mfuev1auth(NULL, 0, 0x1B, key, resp, respPar, NULL);\r
if (len != 4) {\r
if (MF_DBGLEVEL >= MF_DBG_ERROR) Dbprintf("Cmd Error: %02x %u", resp[0], len);\r
uint8_t respPar[3] = {0,0,0};\r
\r
// REQUEST AUTHENTICATION\r
- len = mifare_sendcmd_short(NULL, 1, 0x1A, 0x00, resp, respPar ,NULL);\r
+ len = mifare_sendcmd_short(NULL, 1, MIFARE_ULC_AUTH_1, 0x00, resp, respPar ,NULL);\r
if (len != 11) {\r
if (MF_DBGLEVEL >= MF_DBG_ERROR) Dbprintf("Cmd Error: %02x", resp[0]);\r
return 0;\r
);\r
\r
//len = mifare_sendcmd_short_mfucauth(NULL, 1, 0xAF, rnd_ab, resp, respPar, NULL);\r
- len = mifare_sendcmd(0xAF, rnd_ab, sizeof(rnd_ab), resp, respPar, NULL);\r
+ len = mifare_sendcmd(MIFARE_ULC_AUTH_2, rnd_ab, sizeof(rnd_ab), resp, respPar, NULL);\r
if (len != 11) {\r
if (MF_DBGLEVEL >= MF_DBG_ERROR) Dbprintf("Cmd Error: %02x", resp[0]);\r
return 0;\r
int result = 0;\r
\r
for (retries = 0; retries < MFU_MAX_RETRIES; retries++) {\r
- len = mifare_sendcmd_short(NULL, 1, 0x30, blockNo, receivedAnswer, receivedAnswerPar, NULL);\r
+ len = mifare_sendcmd_short(NULL, 1, MIFARE_CMD_READBLOCK, blockNo, receivedAnswer, receivedAnswerPar, NULL);\r
if (len == 1) {\r
if (MF_DBGLEVEL >= MF_DBG_ERROR) Dbprintf("Cmd Error: %02x", receivedAnswer[0]);\r
result = 1;\r
uint8_t receivedAnswerPar[MAX_MIFARE_PARITY_SIZE];\r
\r
// command MIFARE_CLASSIC_WRITEBLOCK\r
- len = mifare_sendcmd_short(pcs, 1, 0xA0, blockNo, receivedAnswer, receivedAnswerPar, NULL);\r
+ len = mifare_sendcmd_short(pcs, 1, MIFARE_CMD_WRITEBLOCK, blockNo, receivedAnswer, receivedAnswerPar, NULL);\r
\r
if ((len != 1) || (receivedAnswer[0] != 0x0A)) { // 0x0a - ACK\r
if (MF_DBGLEVEL >= 1) Dbprintf("Cmd Error: %02x", receivedAnswer[0]);\r
uint8_t receivedAnswer[MAX_FRAME_SIZE];\r
uint8_t receivedAnswerPar[MAX_PARITY_SIZE];\r
\r
- len = mifare_sendcmd_short(NULL, true, 0xA0, blockNo, receivedAnswer, receivedAnswerPar, NULL);\r
+ len = mifare_sendcmd_short(NULL, true, MIFARE_CMD_WRITEBLOCK, blockNo, receivedAnswer, receivedAnswerPar, NULL);\r
\r
if ((len != 1) || (receivedAnswer[0] != 0x0A)) { // 0x0a - ACK\r
if (MF_DBGLEVEL >= MF_DBG_ERROR)\r
uint8_t receivedAnswer[MAX_MIFARE_FRAME_SIZE];\r
uint8_t receivedAnswerPar[MAX_MIFARE_PARITY_SIZE];\r
\r
- len = mifare_sendcmd_short(pcs, pcs == NULL ? false:true, 0x50, 0x00, receivedAnswer, receivedAnswerPar, NULL);\r
+ len = mifare_sendcmd_short(pcs, pcs == NULL ? false:true, ISO14443A_CMD_HALT, 0x00, receivedAnswer, receivedAnswerPar, NULL);\r
if (len != 0) {\r
if (MF_DBGLEVEL >= MF_DBG_ERROR)\r
Dbprintf("halt error. response len: %x", len);\r
uint8_t receivedAnswer[MAX_MIFARE_FRAME_SIZE];\r
uint8_t receivedAnswerPar[MAX_MIFARE_PARITY_SIZE];\r
\r
- len = mifare_sendcmd_short(NULL, true, 0x50, 0x00, receivedAnswer, receivedAnswerPar, NULL);\r
+ len = mifare_sendcmd_short(NULL, true, ISO14443A_CMD_HALT, 0x00, receivedAnswer, receivedAnswerPar, NULL);\r
if (len != 0) {\r
if (MF_DBGLEVEL >= MF_DBG_ERROR)\r
Dbprintf("halt error. response len: %x", len);\r
bool IsBlock1PCF7931(uint8_t *block) {
// assuming all RFU bits are set to 0
+
+ uint8_t rb1 = block[14] & 0x80;
+ uint8_t rfb = block[14] & 0x7f;
+ uint8_t rlb = block[15];
+
if (block[10] == 0 && block[11] == 0 && block[12] == 0 && block[13] == 0)
- if((block[14] & 0x7f) <= 9 && block[15] <= 9)
+ // block 1 is sent only if (RLB >= 1 && RFB <= 1) or RB1 enabled
+ if(rfb <= rlb && rfb <= 9 && rlb <= 9 && ((rfb <= 1 && rlb >= 1) || rb1))
return true;
return false;
Dbprintf("Error, no tag or bad tag");
return;
}
+
// exit if too many errors during reading
if (tries > 50 && (2*errors > tries)) {
Dbprintf("Error reading the tag");
// our logic breaks if we don't get at least two blocks
if (n < 2) {
+ // skip if all 0s block or no blocks
if (n == 0 || !memcmp(tmp_blocks[0], "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00", 16))
continue;
+ // add block to single blocks list
if (single_blocks_cnt < max_blocks) {
for (i = 0; i < single_blocks_cnt; ++i) {
if (!memcmp(single_blocks[i], tmp_blocks[0], 16)) {
}
if (j != 1) {
memcpy(single_blocks[single_blocks_cnt], tmp_blocks[0], 16);
+ print_result("got single block", single_blocks[single_blocks_cnt], 16);
single_blocks_cnt++;
}
j = 0;
}
Dbprintf("(dbg) got %d blocks (%d/%d found) (%d tries, %d errors)", n, found_blocks, (max_blocks == 0 ? found_blocks : max_blocks), tries, errors);
+ for (i = 0; i < n; ++i)
+ {
+ print_result("got consecutive blocks", tmp_blocks[i], 16);
+ }
i = 0;
if(!found_0_1) {
goto end;
}
}
- while (found_blocks != max_blocks);
+ while (found_blocks < max_blocks);
end:
Dbprintf("-----------------------------------------");
#define BYTEx(x, n) (((x) >> (n * 8)) & 0xff )
-#define LED_RED 1
+#define LED_RED 1
#define LED_ORANGE 2
-#define LED_GREEN 4
-#define LED_RED2 8
-#define BUTTON_HOLD 1
-#define BUTTON_NO_CLICK 0
-#define BUTTON_SINGLE_CLICK -1
-#define BUTTON_DOUBLE_CLICK -2
-#define BUTTON_ERROR -99
+#define LED_GREEN 4
+#define LED_RED2 8
+
+#define BUTTON_HOLD 1
+#define BUTTON_NO_CLICK 0
+#define BUTTON_SINGLE_CLICK -1
+#define BUTTON_DOUBLE_CLICK -2
+#define BUTTON_ERROR -99
+
+#define REV8(x) ((((x)>>7)&1)|((((x)>>6)&1)<<1)|((((x)>>5)&1)<<2)|((((x)>>4)&1)<<3)|((((x)>>3)&1)<<4)|((((x)>>2)&1)<<5)|((((x)>>1)&1)<<6)|(((x)&1)<<7))
+#define REV16(x) (REV8(x) | (REV8 (x >> 8) << 8))
+#define REV32(x) (REV16(x) | (REV16(x >> 16) << 16))
+#define REV64(x) (REV32(x) | (REV32(x >> 32) << 32))
void print_result(char *name, uint8_t *buf, size_t len);
size_t nbytes(size_t nbits);
#include "mifare/mad.h"\r
#include "mifare/ndef.h"\r
#include "emv/dump.h"\r
+#include "protocols.h"\r
\r
#define NESTED_SECTOR_RETRY 10 // how often we try mfested() until we give up\r
\r
PrintAndLog("--block no:%d, key type:%c, key:%s", blockNo, keyType?'B':'A', sprint_hex(key, 6));\r
PrintAndLog("--data: %s", sprint_hex(bldata, 16));\r
\r
- UsbCommand c = {CMD_MIFARE_WRITEBL, {blockNo, keyType, 0}};\r
+ UsbCommand c = {CMD_MIFARE_WRITEBL, {blockNo, keyType, 0}};\r
memcpy(c.d.asBytes, key, 6);\r
memcpy(c.d.asBytes + 10, bldata, 16);\r
- SendCommand(&c);\r
+ SendCommand(&c);\r
\r
UsbCommand resp;\r
if (WaitForResponseTimeout(CMD_ACK,&resp,1500)) {\r
}\r
PrintAndLog("--block no:%d, key type:%c, key:%s ", blockNo, keyType?'B':'A', sprint_hex(key, 6));\r
\r
- UsbCommand c = {CMD_MIFARE_READBL, {blockNo, keyType, 0}};\r
+ UsbCommand c = {CMD_MIFARE_READBL, {blockNo, keyType, 0}};\r
memcpy(c.d.asBytes, key, 6);\r
- SendCommand(&c);\r
+ SendCommand(&c);\r
\r
UsbCommand resp;\r
if (WaitForResponseTimeout(CMD_ACK,&resp,1500)) {\r
return 2;\r
}\r
\r
- return 0;\r
+ return 0;\r
}\r
\r
int CmdHF14AMfRdSc(const char *Cmd)\r
PrintAndLog("Command execute timeout");\r
}\r
\r
- return 0;\r
+ return 0;\r
}\r
\r
uint8_t FirstBlockOfSector(uint8_t sectorNo)\r
bool createDumpFile = 0;\r
bool singleBlock = false; // Flag to ID if a single or multi key check\r
uint8_t keyFoundCount = 0; // Counter to display the number of keys found/transfered to emulator\r
- \r
+\r
sector_t *e_sector = NULL;\r
\r
keyBlock = calloc(stKeyBlock, 6);\r
return 1;\r
};\r
}\r
- \r
+\r
parseParamTDS(Cmd, 2, &transferToEml, &createDumpFile, &btimeout14a);\r
\r
if (singleBlock & createDumpFile) {\r
uint32_t max_keys = keycnt > USB_CMD_DATA_SIZE / 6 ? USB_CMD_DATA_SIZE / 6 : keycnt;\r
\r
// !SingleKey, so all key check (if SectorsCnt > 0)\r
- if (!singleBlock) { \r
+ if (!singleBlock) {\r
PrintAndLog("To cancel this operation press the button on the proxmark...");\r
printf("--");\r
for (uint32_t c = 0; c < keycnt; c += max_keys) {\r
PrintAndLog("Command execute timeout");\r
}\r
}\r
- } else { \r
+ } else {\r
int keyAB = keyType;\r
do {\r
for (uint32_t c = 0; c < keycnt; c += max_keys) {\r
clearTraceLog = false;\r
\r
if (res != 1) {\r
- if (!res) { \r
+ if (!res) {\r
// Use the common format below\r
// PrintAndLog("Found valid key:[%d:%c]%012" PRIx64, blockNo, (keyAB & 0x01)?'B':'A', key64);\r
foundAKey = true;\r
- \r
+\r
// Store the Single Key for display list\r
// For a single block check, SectorsCnt = Sector that contains the block\r
- e_sector[SectorsCnt-1].foundKey[(keyAB & 0x01)] = true; // flag key found \r
- e_sector[SectorsCnt-1].Key[(keyAB & 0x01)] = key64; // Save key data \r
- \r
+ e_sector[SectorsCnt-1].foundKey[(keyAB & 0x01)] = true; // flag key found\r
+ e_sector[SectorsCnt-1].Key[(keyAB & 0x01)] = key64; // Save key data\r
+\r
}\r
} else {\r
PrintAndLog("Command execute timeout");\r
for (uint16_t t = 0; t < 2; t++) {\r
if (e_sector[sectorNo].foundKey[t]) {\r
num_to_bytes(e_sector[sectorNo].Key[t], 6, block + t * 10);\r
- keyFoundCount++; // Key found count for information\r
+ keyFoundCount++; // Key found count for information\r
}\r
}\r
mfEmlSetMem(block, FirstBlockOfSector(sectorNo) + NumBlocksPerSector(sectorNo) - 1, 1);\r
fclose(fkeys);\r
PrintAndLog("Found keys have been dumped to file dumpkeys.bin. 0xffffffffffff has been inserted for unknown keys.");\r
}\r
- \r
+\r
free(e_sector);\r
free(keyBlock);\r
PrintAndLog("");\r
return 0;\r
}\r
\r
- UsbCommand c = {CMD_MIFARE_SET_DBGMODE, {dbgMode, 0, 0}};\r
- SendCommand(&c);\r
+ UsbCommand c = {CMD_MIFARE_SET_DBGMODE, {dbgMode, 0, 0}};\r
+ SendCommand(&c);\r
\r
- return 0;\r
+ return 0;\r
}\r
\r
int CmdHF14AMfEGet(const char *Cmd)\r
PrintAndLog("Command execute timeout");\r
}\r
\r
- return 0;\r
+ return 0;\r
}\r
\r
int CmdHF14AMfEClear(const char *Cmd)\r
return 0;\r
}\r
\r
- UsbCommand c = {CMD_MIFARE_EML_MEMCLR, {0, 0, 0}};\r
- SendCommand(&c);\r
- return 0;\r
+ UsbCommand c = {CMD_MIFARE_EML_MEMCLR, {0, 0, 0}};\r
+ SendCommand(&c);\r
+ return 0;\r
}\r
\r
\r
\r
PrintAndLog("Saved %d blocks to file: %s", numBlocks, filename);\r
\r
- return 0;\r
+ return 0;\r
}\r
\r
\r
case '\0': numSectors = 16; break;\r
case '2' : numSectors = 32; break;\r
case '4' : numSectors = 40; break;\r
- case 'd' : \r
+ case 'd' :\r
case 'D' : createDumpFile = true; break;\r
}\r
cmdp++;\r
return 0;\r
}\r
\r
-static command_t CommandTable[] =\r
-{\r
- {"help", CmdHelp, 1, "This help"},\r
- {"dbg", CmdHF14AMfDbg, 0, "Set default debug mode"},\r
- {"rdbl", CmdHF14AMfRdBl, 0, "Read MIFARE classic block"},\r
- {"rdsc", CmdHF14AMfRdSc, 0, "Read MIFARE classic sector"},\r
- {"dump", CmdHF14AMfDump, 0, "Dump MIFARE classic tag to binary file"},\r
- {"restore", CmdHF14AMfRestore, 0, "Restore MIFARE classic binary file to BLANK tag"},\r
- {"wrbl", CmdHF14AMfWrBl, 0, "Write MIFARE classic block"},\r
- {"auth4", CmdHF14AMfAuth4, 0, "ISO14443-4 AES authentication"},\r
- {"chk", CmdHF14AMfChk, 0, "Test block keys"},\r
- {"mifare", CmdHF14AMifare, 0, "Read parity error messages."},\r
- {"hardnested", CmdHF14AMfNestedHard, 0, "Nested attack for hardened Mifare cards"},\r
- {"nested", CmdHF14AMfNested, 0, "Test nested authentication"},\r
- {"sniff", CmdHF14AMfSniff, 0, "Sniff card-reader communication"},\r
- {"sim", CmdHF14AMfSim, 0, "Simulate MIFARE card"},\r
- {"eclr", CmdHF14AMfEClear, 0, "Clear simulator memory"},\r
- {"eget", CmdHF14AMfEGet, 0, "Get simulator memory block"},\r
- {"eset", CmdHF14AMfESet, 0, "Set simulator memory block"},\r
- {"eload", CmdHF14AMfELoad, 0, "Load from file emul dump"},\r
- {"esave", CmdHF14AMfESave, 0, "Save to file emul dump"},\r
- {"ecfill", CmdHF14AMfECFill, 0, "Fill simulator memory with help of keys from simulator"},\r
- {"ekeyprn", CmdHF14AMfEKeyPrn, 0, "Print keys from simulator memory"},\r
- {"cwipe", CmdHF14AMfCWipe, 0, "Wipe magic Chinese card"},\r
- {"csetuid", CmdHF14AMfCSetUID, 0, "Set UID for magic Chinese card"},\r
- {"csetblk", CmdHF14AMfCSetBlk, 0, "Write block - Magic Chinese card"},\r
- {"cgetblk", CmdHF14AMfCGetBlk, 0, "Read block - Magic Chinese card"},\r
- {"cgetsc", CmdHF14AMfCGetSc, 0, "Read sector - Magic Chinese card"},\r
- {"cload", CmdHF14AMfCLoad, 0, "Load dump into magic Chinese card"},\r
- {"csave", CmdHF14AMfCSave, 0, "Save dump from magic Chinese card into file or emulator"},\r
- {"decrypt", CmdDecryptTraceCmds, 1, "[nt] [ar_enc] [at_enc] [data] - to decrypt snoop or trace"},\r
- {"mad", CmdHF14AMfMAD, 0, "Checks and prints MAD"},\r
- {"ndef", CmdHFMFNDEF, 0, "Prints NDEF records from card"},\r
- {NULL, NULL, 0, NULL}\r
+int CmdHFMFPersonalize(const char *cmd) {\r
+\r
+ CLIParserInit("hf mf personalize",\r
+ "Personalize the UID of a Mifare Classic EV1 card. This is only possible if it is a 7Byte UID card and if it is not already personalized.",\r
+ "Usage:\n\thf mf personalize UIDF0 -> double size UID according to ISO/IEC14443-3\n"\r
+ "\thf mf personalize UIDF1 -> double size UID according to ISO/IEC14443-3, optional usage of selection process shortcut\n"\r
+ "\thf mf personalize UIDF2 -> single size random ID according to ISO/IEC14443-3\n"\r
+ "\thf mf personalize UIDF3 -> single size NUID according to ISO/IEC14443-3\n"\r
+ "\thf mf personalize -t B -k B0B1B2B3B4B5 UIDF3 -> use key B = 0xB0B1B2B3B4B5 instead of default key A\n");\r
+\r
+ void *argtable[] = {\r
+ arg_param_begin,\r
+ arg_str0("tT", "keytype", "<A|B>", "key type (A or B) to authenticate sector 0 (default: A)"),\r
+ arg_str0("kK", "key", "<key (hex 6 Bytes)>", "key to authenticate sector 0 (default: FFFFFFFFFFFF)"),\r
+ arg_str1(NULL, NULL, "<UIDF0|UIDF1|UIDF2|UIDF3>", "Personalization Option"),\r
+ arg_param_end\r
+ };\r
+ CLIExecWithReturn(cmd, argtable, true);\r
+\r
+ char keytypestr[2] = "A";\r
+ uint8_t keytype = 0x00;\r
+ int keytypestr_len;\r
+ int res = CLIParamStrToBuf(arg_get_str(1), (uint8_t*)keytypestr, 1, &keytypestr_len);\r
+ if (res || (keytypestr[0] != 'a' && keytypestr[0] != 'A' && keytypestr[0] != 'b' && keytypestr[0] != 'B')) {\r
+ PrintAndLog("ERROR: not a valid key type. Key type must be A or B");\r
+ CLIParserFree();\r
+ return 1;\r
+ }\r
+ if (keytypestr[0] == 'B' || keytypestr[0] == 'b') {\r
+ keytype = 0x01;\r
+ }\r
+\r
+ uint8_t key[6] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};\r
+ int key_len;\r
+ res = CLIParamHexToBuf(arg_get_str(2), key, 6, &key_len);\r
+ if (res || (!res && key_len > 0 && key_len != 6)) {\r
+ PrintAndLog("ERROR: not a valid key. Key must be 12 hex digits");\r
+ CLIParserFree();\r
+ return 1;\r
+ }\r
+\r
+ char pers_optionstr[6];\r
+ int opt_len;\r
+ uint8_t pers_option;\r
+ res = CLIParamStrToBuf(arg_get_str(3), (uint8_t*)pers_optionstr, 5, &opt_len);\r
+ if (res || (!res && opt_len > 0 && opt_len != 5)\r
+ || (strncmp(pers_optionstr, "UIDF0", 5) && strncmp(pers_optionstr, "UIDF1", 5) && strncmp(pers_optionstr, "UIDF2", 5) && strncmp(pers_optionstr, "UIDF3", 5))) {\r
+ PrintAndLog("ERROR: invalid personalization option. Must be one of UIDF0, UIDF1, UIDF2, or UIDF3");\r
+ CLIParserFree();\r
+ return 1;\r
+ }\r
+ if (!strncmp(pers_optionstr, "UIDF0", 5)) {\r
+ pers_option = MIFARE_EV1_UIDF0;\r
+ } else if (!strncmp(pers_optionstr, "UIDF1", 5)) {\r
+ pers_option = MIFARE_EV1_UIDF1;\r
+ } else if (!strncmp(pers_optionstr, "UIDF2", 5)) {\r
+ pers_option = MIFARE_EV1_UIDF2;\r
+ } else {\r
+ pers_option = MIFARE_EV1_UIDF3;\r
+ }\r
+\r
+ CLIParserFree();\r
+\r
+ UsbCommand c = {CMD_MIFARE_PERSONALIZE_UID, {keytype, pers_option, 0}};\r
+ memcpy(c.d.asBytes, key, 6);\r
+ SendCommand(&c);\r
+\r
+ UsbCommand resp;\r
+ if (WaitForResponseTimeout(CMD_ACK, &resp, 1500)) {\r
+ uint8_t isOK = resp.arg[0] & 0xff;\r
+ PrintAndLog("Personalization %s", isOK ? "FAILED" : "SUCCEEDED");\r
+ } else {\r
+ PrintAndLog("Command execute timeout");\r
+ }\r
+\r
+ return 0;\r
+}\r
+\r
+\r
+static command_t CommandTable[] = {\r
+ {"help", CmdHelp, 1, "This help"},\r
+ {"dbg", CmdHF14AMfDbg, 0, "Set default debug mode"},\r
+ {"rdbl", CmdHF14AMfRdBl, 0, "Read MIFARE classic block"},\r
+ {"rdsc", CmdHF14AMfRdSc, 0, "Read MIFARE classic sector"},\r
+ {"dump", CmdHF14AMfDump, 0, "Dump MIFARE classic tag to binary file"},\r
+ {"restore", CmdHF14AMfRestore, 0, "Restore MIFARE classic binary file to BLANK tag"},\r
+ {"wrbl", CmdHF14AMfWrBl, 0, "Write MIFARE classic block"},\r
+ {"auth4", CmdHF14AMfAuth4, 0, "ISO14443-4 AES authentication"},\r
+ {"chk", CmdHF14AMfChk, 0, "Test block keys"},\r
+ {"mifare", CmdHF14AMifare, 0, "Read parity error messages."},\r
+ {"hardnested", CmdHF14AMfNestedHard, 0, "Nested attack for hardened Mifare cards"},\r
+ {"nested", CmdHF14AMfNested, 0, "Test nested authentication"},\r
+ {"sniff", CmdHF14AMfSniff, 0, "Sniff card-reader communication"},\r
+ {"sim", CmdHF14AMfSim, 0, "Simulate MIFARE card"},\r
+ {"eclr", CmdHF14AMfEClear, 0, "Clear simulator memory"},\r
+ {"eget", CmdHF14AMfEGet, 0, "Get simulator memory block"},\r
+ {"eset", CmdHF14AMfESet, 0, "Set simulator memory block"},\r
+ {"eload", CmdHF14AMfELoad, 0, "Load from file emul dump"},\r
+ {"esave", CmdHF14AMfESave, 0, "Save to file emul dump"},\r
+ {"ecfill", CmdHF14AMfECFill, 0, "Fill simulator memory with help of keys from simulator"},\r
+ {"ekeyprn", CmdHF14AMfEKeyPrn, 0, "Print keys from simulator memory"},\r
+ {"cwipe", CmdHF14AMfCWipe, 0, "Wipe magic Chinese card"},\r
+ {"csetuid", CmdHF14AMfCSetUID, 0, "Set UID for magic Chinese card"},\r
+ {"csetblk", CmdHF14AMfCSetBlk, 0, "Write block - Magic Chinese card"},\r
+ {"cgetblk", CmdHF14AMfCGetBlk, 0, "Read block - Magic Chinese card"},\r
+ {"cgetsc", CmdHF14AMfCGetSc, 0, "Read sector - Magic Chinese card"},\r
+ {"cload", CmdHF14AMfCLoad, 0, "Load dump into magic Chinese card"},\r
+ {"csave", CmdHF14AMfCSave, 0, "Save dump from magic Chinese card into file or emulator"},\r
+ {"decrypt", CmdDecryptTraceCmds, 1, "[nt] [ar_enc] [at_enc] [data] - to decrypt snoop or trace"},\r
+ {"mad", CmdHF14AMfMAD, 0, "Checks and prints MAD"},\r
+ {"ndef", CmdHFMFNDEF, 0, "Prints NDEF records from card"},\r
+ {"personalize", CmdHFMFPersonalize, 0, "Personalize UID (Mifare Classic EV1 only)"},\r
+ {NULL, NULL, 0, NULL}\r
};\r
\r
-int CmdHFMF(const char *Cmd)\r
-{\r
+\r
+int CmdHFMF(const char *Cmd) {\r
(void)WaitForResponseTimeout(CMD_ACK,NULL,100);\r
CmdsParse(CommandTable, Cmd);\r
return 0;\r
}\r
\r
-int CmdHelp(const char *Cmd)\r
-{\r
- CmdsHelp(CommandTable);\r
- return 0;\r
+\r
+int CmdHelp(const char *Cmd) {\r
+ CmdsHelp(CommandTable);\r
+ return 0;\r
}\r
#include "hitag.h"
#include "cmdmain.h"
-static int CmdHelp(const char *Cmd);
-
-size_t nbytes(size_t nbits) {
- return (nbits/8)+((nbits%8)>0);
+static size_t nbytes(size_t nbits) {
+ return (nbits/8) + ((nbits%8)>0);
}
-int CmdLFHitagList(const char *Cmd)
-{
- uint8_t *got = malloc(USB_CMD_DATA_SIZE);
+
+static int CmdLFHitagList(const char *Cmd) {
+ uint8_t *got = malloc(USB_CMD_DATA_SIZE);
// Query for the actual size of the trace
UsbCommand response;
GetFromBigBuf(got, USB_CMD_DATA_SIZE, 0, &response, -1, false);
got = p;
GetFromBigBuf(got, traceLen, 0, NULL, -1, false);
}
-
+
PrintAndLog("recorded activity (TraceLen = %d bytes):");
PrintAndLog(" ETU :nbits: who bytes");
PrintAndLog("---------+-----+----+-----------");
char filename[FILE_PATH_SIZE] = { 0x00 };
FILE* pf = NULL;
-
- if (len > FILE_PATH_SIZE)
+
+ if (len > FILE_PATH_SIZE)
len = FILE_PATH_SIZE;
memcpy(filename, Cmd, len);
-
+
if (strlen(filename) > 0) {
if ((pf = fopen(filename,"wb")) == NULL) {
PrintAndLog("Error: Could not open file [%s]",filename);
}
for (;;) {
-
+
if(i > traceLen) { break; }
bool isResponse;
int len = nbytes(bits);
if (len > 100) {
- break;
+ break;
}
if (i + len > traceLen) { break;}
int fillupBits = 8 - (bits % 8);
byte_t framefilled[bits+fillupBits];
byte_t* ff = framefilled;
-
+
int response_bit[200] = {0};
int z = 0;
for (int y = 0; y < len; y++) {
char line[1000] = "";
for (j = 0; j < len; j++) {
- //if((parityBits >> (len - j - 1)) & 0x01) {
- if (isResponse && (oddparity8(frame[j]) != ((parityBits >> (len - j - 1)) & 0x01))) {
- sprintf(line+(j*4), "%02x! ", frame[j]);
- } else {
- sprintf(line+(j*4), "%02x ", frame[j]);
- }
+ //if((parityBits >> (len - j - 1)) & 0x01) {
+ if (isResponse && (oddparity8(frame[j]) != ((parityBits >> (len - j - 1)) & 0x01))) {
+ sprintf(line+(j*4), "%02x! ", frame[j]);
+ } else {
+ sprintf(line+(j*4), "%02x ", frame[j]);
+ }
}
PrintAndLog(" +%7d: %3d: %s %s",
(isResponse ? "TAG" : " "),
line);
}
-
+
prev = timestamp;
i += (len + 9);
}
-
+
if (pf) {
fclose(pf);
PrintAndLog("Recorded activity succesfully written to file: %s", filename);
return 0;
}
-int CmdLFHitagSnoop(const char *Cmd) {
- UsbCommand c = {CMD_SNOOP_HITAG};
- SendCommand(&c);
- return 0;
+
+static int CmdLFHitagSnoop(const char *Cmd) {
+ UsbCommand c = {CMD_SNOOP_HITAG};
+ SendCommand(&c);
+ return 0;
}
-int CmdLFHitagSim(const char *Cmd) {
-
- UsbCommand c = {CMD_SIMULATE_HITAG};
+
+static int CmdLFHitagSim(const char *Cmd) {
+
+ UsbCommand c = {CMD_SIMULATE_HITAG};
char filename[FILE_PATH_SIZE] = { 0x00 };
FILE* pf;
bool tag_mem_supplied;
int len = strlen(Cmd);
if (len > FILE_PATH_SIZE) len = FILE_PATH_SIZE;
memcpy(filename, Cmd, len);
-
+
if (strlen(filename) > 0) {
if ((pf = fopen(filename,"rb+")) == NULL) {
PrintAndLog("Error: Could not open file [%s]",filename);
} else {
tag_mem_supplied = false;
}
-
+
// Does the tag comes with memory
c.arg[0] = (uint32_t)tag_mem_supplied;
- SendCommand(&c);
- return 0;
+ SendCommand(&c);
+ return 0;
+}
+
+
+static bool getHitagUid(uint32_t *uid) {
+ // ToDo: this is for Hitag2 only (??)
+
+ UsbCommand c = {CMD_READER_HITAG, {RHT2F_UID_ONLY}};
+
+ SendCommand(&c);
+
+ UsbCommand resp;
+ if (!WaitForResponseTimeout(CMD_ACK, &resp, 2500)) {
+ PrintAndLogEx(WARNING, "timeout while waiting for reply.");
+ return false;
+ }
+
+ if (resp.arg[0] == false) {
+ PrintAndLogEx(DEBUG, "DEBUG: Error - failed getting UID");
+ return false;
+ }
+
+ if (uid)
+ *uid = bytes_to_num(resp.d.asBytes, 4);
+
+ return true;
}
+
+static int CmdLFHitagInfo(const char *Cmd) {
+ char ctmp = param_getchar(Cmd, 0);
+ if (ctmp != '\0') {
+ PrintAndLog("Usage: lf hitag info [h]");
+ PrintAndLog("Options:");
+ PrintAndLog(" h This help");
+ PrintAndLog("Examples:");
+ PrintAndLog(" lf hitag info");
+ return 0;
+ }
+
+ // read UID
+ uint32_t uid = 0;
+ if (getHitagUid(&uid) == false)
+ return 1;
+
+ PrintAndLogEx(SUCCESS, "UID: %08X", uid);
+
+ // how to detemine Hitag types?
+ // read block3, get configuration byte.
+ // PrintAndLogEx(FAILED, _RED_("TODO: This is a hardcoded example!"));
+
+ // common configurations.
+ // printHitagConfiguration(0x06);
+ //printHitagConfiguration( 0x0E );
+ //printHitagConfiguration( 0x02 );
+ //printHitagConfiguration( 0x00 );
+ //printHitagConfiguration( 0x04 );
+ return 0;
+}
+
+
int CmdLFHitagReader(const char *Cmd) {
- UsbCommand c = {CMD_READER_HITAG};//, {param_get32ex(Cmd,0,0,10),param_get32ex(Cmd,1,0,16),param_get32ex(Cmd,2,0,16),param_get32ex(Cmd,3,0,16)}};
+ UsbCommand c = {CMD_READER_HITAG};
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) {
case 01: { //RHTSF_CHALLENGE
c = (UsbCommand){ CMD_READ_HITAG_S };
- num_to_bytes(param_get32ex(Cmd,1,0,16),4,htd->auth.NrAr);
- num_to_bytes(param_get32ex(Cmd,2,0,16),4,htd->auth.NrAr+4);
- c.arg[1] = param_get64ex(Cmd,3,0,0); //firstpage
- c.arg[2] = param_get64ex(Cmd,4,0,0); //tag mode
+ num_to_bytes(param_get32ex(Cmd, 1, 0, 16), 4, htd->auth.NrAr);
+ num_to_bytes(param_get32ex(Cmd, 2, 0, 16), 4, htd->auth.NrAr+4);
+ c.arg[1] = param_get64ex(Cmd, 3, 0, 0); //firstpage
+ c.arg[2] = param_get64ex(Cmd, 4, 0, 0); //tag mode
} break;
case 02: { //RHTSF_KEY
c = (UsbCommand){ CMD_READ_HITAG_S };
- num_to_bytes(param_get64ex(Cmd,1,0,16),6,htd->crypto.key);
- c.arg[1] = param_get64ex(Cmd,2,0,0); //firstpage
- c.arg[2] = param_get64ex(Cmd,3,0,0); //tag mode
+ num_to_bytes(param_get64ex(Cmd, 1, 0, 16), 6, htd->crypto.key);
+ c.arg[1] = param_get64ex(Cmd, 2, 0, 0); //firstpage
+ c.arg[2] = param_get64ex(Cmd, 3, 0, 0); //tag mode
} break;
case 03: { //RHTSF_CHALLENGE BLOCK
c = (UsbCommand){ CMD_READ_HITAG_S_BLK };
- num_to_bytes(param_get32ex(Cmd,1,0,16),4,htd->auth.NrAr);
- num_to_bytes(param_get32ex(Cmd,2,0,16),4,htd->auth.NrAr+4);
- c.arg[1] = param_get64ex(Cmd,3,0,0); //firstpage
- c.arg[2] = param_get64ex(Cmd,4,0,0); //tag mode
+ num_to_bytes(param_get32ex(Cmd, 1, 0, 16), 4, htd->auth.NrAr);
+ num_to_bytes(param_get32ex(Cmd, 2, 0, 16), 4, htd->auth.NrAr+4);
+ c.arg[1] = param_get64ex(Cmd, 3, 0, 0); //firstpage
+ c.arg[2] = param_get64ex(Cmd, 4, 0, 0); //tag mode
} break;
case 04: { //RHTSF_KEY BLOCK
c = (UsbCommand){ CMD_READ_HITAG_S_BLK };
- num_to_bytes(param_get64ex(Cmd,1,0,16),6,htd->crypto.key);
- c.arg[1] = param_get64ex(Cmd,2,0,0); //firstpage
- c.arg[2] = param_get64ex(Cmd,3,0,0); //tag mode
+ num_to_bytes(param_get64ex(Cmd, 1, 0, 16), 6, htd->crypto.key);
+ c.arg[1] = param_get64ex(Cmd, 2, 0, 0); //firstpage
+ c.arg[2] = param_get64ex(Cmd, 3, 0, 0); //tag mode
} break;
case RHT2F_PASSWORD: {
- num_to_bytes(param_get32ex(Cmd,1,0,16),4,htd->pwd.password);
+ num_to_bytes(param_get32ex(Cmd, 1, 0, 16), 4, htd->pwd.password);
} break;
case RHT2F_AUTHENTICATE: {
- num_to_bytes(param_get32ex(Cmd,1,0,16),4,htd->auth.NrAr);
- num_to_bytes(param_get32ex(Cmd,2,0,16),4,htd->auth.NrAr+4);
+ num_to_bytes(param_get32ex(Cmd, 1, 0, 16), 4, htd->auth.NrAr);
+ num_to_bytes(param_get32ex(Cmd, 2, 0, 16), 4, htd->auth.NrAr+4);
} break;
case RHT2F_CRYPTO: {
- num_to_bytes(param_get64ex(Cmd,1,0,16),6,htd->crypto.key);
- // num_to_bytes(param_get32ex(Cmd,2,0,16),4,htd->auth.NrAr+4);
+ num_to_bytes(param_get64ex(Cmd, 1, 0, 16), 6, htd->crypto.key);
+ // num_to_bytes(param_get32ex(Cmd,2,0,16),4,htd->auth.NrAr+4);
} break;
case RHT2F_TEST_AUTH_ATTEMPTS: {
// No additional parameters needed
PrintAndLog("");
PrintAndLog("Usage: hitag reader <Reader Function #>");
PrintAndLog("Reader Functions:");
- PrintAndLog(" HitagS (0*)");
- 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(" 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(" Valid tagmodes are 0=STANDARD, 1=ADVANCED, 2=FAST_ADVANCED (default is ADVANCED)");
- PrintAndLog(" Hitag1 (1*)");
- PrintAndLog(" Hitag2 (2*)");
- PrintAndLog(" 21 <password> (password mode)");
- PrintAndLog(" 22 <nr> <ar> (authentication)");
- PrintAndLog(" 23 <key> (authentication) key is in format: ISK high + ISK low");
- PrintAndLog(" 25 (test recorded authentications)");
- PrintAndLog(" 26 just read UID");
+ PrintAndLog(" HitagS (0*):");
+ 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(" 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(" Valid tagmodes are 0=STANDARD, 1=ADVANCED, 2=FAST_ADVANCED (default is ADVANCED)");
+ PrintAndLog(" Hitag1 (1*):");
+ PrintAndLog(" (not yet implemented)");
+ PrintAndLog(" Hitag2 (2*):");
+ PrintAndLog(" 21 <password> (password mode)");
+ PrintAndLog(" 22 <nr> <ar> (authentication)");
+ PrintAndLog(" 23 <key> (authentication) key is in format: ISK high + ISK low");
+ PrintAndLog(" 25 (test recorded authentications)");
+ PrintAndLog(" 26 just read UID");
return 1;
} break;
}
SendCommand(&c);
UsbCommand resp;
- WaitForResponse(CMD_ACK,&resp);
+ if (!WaitForResponseTimeout(CMD_ACK, &resp, 4000)) {
+ PrintAndLogEx(WARNING, "timeout while waiting for reply.");
+ return 1;
+ }
// Check the return status, stored in the first argument
- if (resp.arg[0] == false) return 1;
-
+ if (resp.arg[0] == false) {
+ PrintAndLogEx(DEBUG, "DEBUG: Error - hitag failed");
+ return 1;
+ }
+
uint32_t id = bytes_to_num(resp.d.asBytes,4);
-
+
if (htf == RHT2F_UID_ONLY){
PrintAndLog("Valid Hitag2 tag found - UID: %08x",id);
} else {
PrintAndLog("Succesfully saved tag memory to [%s]",filename);
}
-
return 0;
}
-int CmdLFHitagSimS(const char *Cmd) {
+static int CmdLFHitagSimS(const char *Cmd) {
UsbCommand c = { CMD_SIMULATE_HITAG_S };
char filename[FILE_PATH_SIZE] = { 0x00 };
FILE* pf;
return 0;
}
-int CmdLFHitagCheckChallenges(const char *Cmd) {
+
+static int CmdLFHitagCheckChallenges(const char *Cmd) {
UsbCommand c = { CMD_TEST_HITAGS_TRACES };
char filename[FILE_PATH_SIZE] = { 0x00 };
FILE* pf;
int len = strlen(Cmd);
if (len > FILE_PATH_SIZE) len = FILE_PATH_SIZE;
memcpy(filename, Cmd, len);
-
+
if (strlen(filename) > 0) {
if ((pf = fopen(filename,"rb+")) == NULL) {
PrintAndLog("Error: Could not open file [%s]",filename);
PrintAndLog("Error: File reading error");
fclose(pf);
return 1;
- }
+ }
fclose(pf);
} else {
file_given = false;
}
-
+
//file with all the challenges to try
c.arg[0] = (uint32_t)file_given;
c.arg[1] = param_get64ex(Cmd,2,0,0); //get mode
- SendCommand(&c);
- return 0;
+ SendCommand(&c);
+ return 0;
}
-int CmdLFHitagWP(const char *Cmd) {
+static int CmdLFHitagWriter(const char *Cmd) {
UsbCommand c = { CMD_WR_HITAG_S };
hitag_data* htd = (hitag_data*)c.d.asBytes;
hitag_function htf = param_get32ex(Cmd,0,0,10);
switch (htf) {
- case 03: { //WHTSF_CHALLENGE
+ case WHTSF_CHALLENGE: {
num_to_bytes(param_get64ex(Cmd,1,0,16),8,htd->auth.NrAr);
c.arg[2]= param_get32ex(Cmd, 2, 0, 10);
num_to_bytes(param_get32ex(Cmd,3,0,16),4,htd->auth.data);
} break;
- case 04:
- case 24:
- { //WHTSF_KEY
+ case WHTSF_KEY:
+ case WHT2F_CRYPTO: {
num_to_bytes(param_get64ex(Cmd,1,0,16),6,htd->crypto.key);
c.arg[2]= param_get32ex(Cmd, 2, 0, 10);
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;
default: {
PrintAndLog("Error: unkown writer function %d",htf);
PrintAndLog("Hitag writer functions");
- PrintAndLog(" HitagS (0*)");
- 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(" Hitag1 (1*)");
- 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(" HitagS (0*):");
+ 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(" Hitag1 (1*)");
+ 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(" 27 <password> <page> <byte0...byte3> write page on a Hitag2 tag");
return 1;
} break;
}
// Copy the hitag function into the first argument
c.arg[0] = htf;
- // Send the command to the proxmark
- SendCommand(&c);
-
- UsbCommand resp;
- WaitForResponse(CMD_ACK,&resp);
-
- // Check the return status, stored in the first argument
- if (resp.arg[0] == false) return 1;
- return 0;
+ // Send the command to the proxmark
+ SendCommand(&c);
+
+ UsbCommand resp;
+ if (!WaitForResponseTimeout(CMD_ACK, &resp, 4000)) {
+ PrintAndLogEx(WARNING, "timeout while waiting for reply.");
+ return 1;
+ }
+
+ // Check the return status, stored in the first argument
+ if (resp.arg[0] == false) {
+ PrintAndLogEx(DEBUG, "DEBUG: Error - hitag write failed");
+ return 1;
+ }
+ return 0;
}
-static command_t CommandTable[] =
+static int CmdHelp(const char *Cmd);
+
+static command_t CommandTable[] =
{
- {"help", CmdHelp, 1, "This help"},
- {"list", CmdLFHitagList, 1, "<outfile> List Hitag trace history"},
- {"reader", CmdLFHitagReader, 1, "Act like a Hitag Reader"},
- {"sim", CmdLFHitagSim, 1, "<infile> Simulate Hitag transponder"},
- {"snoop", CmdLFHitagSnoop, 1, "Eavesdrop Hitag communication"},
- {"writer", CmdLFHitagWP, 1, "Act like a Hitag Writer" },
- {"simS", CmdLFHitagSimS, 1, "<hitagS.hts> Simulate HitagS transponder" },
- {"checkChallenges", CmdLFHitagCheckChallenges, 1, "<challenges.cc> <tagmode> test all challenges" }, {
- NULL,NULL, 0, NULL }
+ {"help", CmdHelp, 1, "This help"},
+ {"list", CmdLFHitagList, 0, "<outfile> List Hitag trace history"},
+ {"info", CmdLFHitagInfo, 0, "Tag information" },
+ {"reader", CmdLFHitagReader, 0, "Act like a Hitag Reader"},
+ {"sim", CmdLFHitagSim, 0, "Simulate Hitag transponder"},
+ {"snoop", CmdLFHitagSnoop, 0, "Eavesdrop Hitag communication"},
+ {"writer", CmdLFHitagWriter, 0, "Act like a Hitag Writer" },
+ {"simS", CmdLFHitagSimS, 0, "Simulate HitagS transponder" },
+ {"checkChallenges", CmdLFHitagCheckChallenges, 0, "Test challenges from a file" },
+ { NULL, NULL, 0, NULL }
};
-int CmdLFHitag(const char *Cmd)
-{
- CmdsParse(CommandTable, Cmd);
- return 0;
+
+static int CmdHelp(const char *Cmd) {
+ CmdsHelp(CommandTable);
+ return 0;
}
-int CmdHelp(const char *Cmd)
-{
- CmdsHelp(CommandTable);
- return 0;
+
+int CmdLFHitag(const char *Cmd) {
+ CmdsParse(CommandTable, Cmd);
+ return 0;
}
#ifndef CMDLFHITAG_H__
#define CMDLFHITAG_H__
-int CmdLFHitag(const char *Cmd);
-
-int CmdLFHitagList(const char *Cmd);
-int CmdLFHitagSnoop(const char *Cmd);
-int CmdLFHitagSim(const char *Cmd);
-int CmdLFHitagReader(const char *Cmd);
+extern int CmdLFHitag(const char *Cmd);
+extern int CmdLFHitagReader(const char *Cmd);
#endif
#ifndef _WIN32
#include <termios.h>
-#include <sys/ioctl.h>
+#include <sys/ioctl.h>
#include <unistd.h>
int ukbhit(void)
Ntty.c_oflag = 0x0000; // output mode
Ntty.c_lflag &= ~ICANON; // control mode = raw
Ntty.c_cc[VMIN] = 1; // return if at least 1 character is in the queue
- Ntty.c_cc[VTIME] = 0; // no timeout. Wait forever
-
+ Ntty.c_cc[VTIME] = 0; // no timeout. Wait forever
+
if (0 == (error = tcsetattr(STDIN_FILENO, TCSANOW, &Ntty))) { // set new attributes
- error += ioctl(STDIN_FILENO, FIONREAD, &cnt); // get number of characters availabe
- error += tcsetattr(STDIN_FILENO, TCSANOW, &Otty); // reset attributes
+ error += ioctl(STDIN_FILENO, FIONREAD, &cnt); // get number of characters availabe
+ error += tcsetattr(STDIN_FILENO, TCSANOW, &Otty); // reset attributes
}
return ( error == 0 ? cnt : -1 );
// log files functions
void AddLogLine(char *file, char *extData, char *c) {
FILE *fLog = NULL;
- char filename[FILE_PATH_SIZE] = {0x00};
- int len = 0;
+ char filename[FILE_PATH_SIZE] = {0x00};
+ int len = 0;
+
+ len = strlen(file);
+ if (len > FILE_PATH_SIZE) len = FILE_PATH_SIZE;
+ memcpy(filename, file, len);
- len = strlen(file);
- if (len > FILE_PATH_SIZE) len = FILE_PATH_SIZE;
- memcpy(filename, file, len);
-
fLog = fopen(filename, "a");
if (!fLog) {
printf("Could not append log file %s", filename);
void FillFileNameByUID(char *fileName, uint8_t *uid, char *ext, int byteCount) {
char * fnameptr = fileName;
-
+
for (int j = 0; j < byteCount; j++, fnameptr += 2)
- sprintf(fnameptr, "%02x", (unsigned int) uid[j]);
- sprintf(fnameptr, "%s", ext);
+ sprintf(fnameptr, "%02x", (unsigned int) uid[j]);
+ sprintf(fnameptr, "%s", ext);
}
// fill buffer from structure [{uint8_t data, size_t length},...]
*dataLength = 0;
va_list valist;
va_start(valist, dataLength);
-
+
uint8_t *vdata = NULL;
size_t vlength = 0;
do{
vdata = va_arg(valist, uint8_t *);
if (!vdata)
break;
-
+
vlength = va_arg(valist, size_t);
if (*dataLength + vlength > maxDataLength) {
va_end(valist);
return 1;
}
-
+
memcpy(&data[*dataLength], vdata, vlength);
*dataLength += vlength;
-
+
} while (vdata);
-
+
va_end(valist);
return 0;
if (strlen(value) % 2)
return false;
-
+
return true;
}
-void hex_to_buffer(const uint8_t *buf, const uint8_t *hex_data, const size_t hex_len, const size_t hex_max_len,
+void hex_to_buffer(const uint8_t *buf, const uint8_t *hex_data, const size_t hex_len, const size_t hex_max_len,
const size_t min_str_len, const size_t spaces_between, bool uppercase) {
-
+
char *tmp = (char *)buf;
size_t i;
memset(tmp, 0x00, hex_max_len);
int maxLen = ( hex_len > hex_max_len) ? hex_max_len : hex_len;
for (i = 0; i < maxLen; ++i, tmp += 2 + spaces_between) {
- sprintf(tmp, (uppercase) ? "%02X" : "%02x", (unsigned int) hex_data[i]);
-
+ sprintf(tmp, (uppercase) ? "%02X" : "%02x", (unsigned int) hex_data[i]);
+
for (int j = 0; j < spaces_between; j++)
sprintf(tmp + 2 + j, " ");
}
-
+
i *= (2 + spaces_between);
int minStrLen = min_str_len > i ? min_str_len : 0;
if (minStrLen > hex_max_len)
minStrLen = hex_max_len;
- for(; i < minStrLen; i++, tmp += 1)
+ for(; i < minStrLen; i++, tmp += 1)
sprintf(tmp, " ");
return;
char *sprint_hex(const uint8_t *data, const size_t len) {
static char buf[4097] = {0};
-
+
hex_to_buffer((uint8_t *)buf, data, len, sizeof(buf) - 1, 0, 1, false);
return buf;
tmp[i] = ((c < 32) || (c == 127)) ? '.' : c;
++i;
}
-
+
int minStrLen = min_str_len > i ? min_str_len : 0;
- for(; i < minStrLen; ++i)
+ for(; i < minStrLen; ++i)
tmp[i] = ' ';
-
+
return buf;
}
char *sprint_ascii(const uint8_t *data, const size_t len) {
- return sprint_ascii_ex(data, len, 0);
+ return sprint_ascii_ex(data, len, 0);
}
void num_to_bytes(uint64_t n, size_t len, uint8_t* dest)
return num;
}
-void num_to_bytebits(uint64_t n, size_t len, uint8_t *dest) {
+void num_to_bytebits(uint64_t n, size_t len, uint8_t *dest) {
while (len--) {
dest[len] = n & 1;
n >>= 1;
//assumes little endian
char *printBits(size_t const size, void const * const ptr)
{
- unsigned char *b = (unsigned char*) ptr;
- unsigned char byte;
+ unsigned char *b = (unsigned char*) ptr;
+ unsigned char byte;
static char buf[1024];
char *tmp = buf;
- int i, j;
-
- for (i=size-1;i>=0;i--)
- {
- for (j=7;j>=0;j--)
- {
- byte = b[i] & (1<<j);
- byte >>= j;
- sprintf(tmp, "%u", (unsigned int)byte);
+ int i, j;
+
+ for (i=size-1;i>=0;i--)
+ {
+ for (j=7;j>=0;j--)
+ {
+ byte = b[i] & (1<<j);
+ byte >>= j;
+ sprintf(tmp, "%u", (unsigned int)byte);
tmp++;
- }
- }
+ }
+ }
return buf;
}
{
int i;
int len = strlen(line);
-
+
*bg = 0;
*en = 0;
-
+
// skip spaces
while (line[*bg] ==' ' || line[*bg]=='\t') (*bg)++;
if (*bg >= len) {
for (i = 0; i < paramnum; i++) {
while (line[*bg]!=' ' && line[*bg]!='\t' && line[*bg] != '\0') (*bg)++;
while (line[*bg]==' ' || line[*bg]=='\t') (*bg)++;
-
+
if (line[*bg] == '\0') return 1;
}
-
+
*en = *bg;
while (line[*en] != ' ' && line[*en] != '\t' && line[*en] != '\0') (*en)++;
-
+
(*en)--;
return 0;
int param_getlength(const char *line, int paramnum)
{
int bg, en;
-
+
if (param_getptr(line, &bg, &en, paramnum)) return 0;
return en - bg + 1;
char param_getchar_indx(const char *line, int indx, int paramnum) {
int bg, en;
-
+
if (param_getptr(line, &bg, &en, paramnum)) return 0x00;
if (bg + indx > en)
return '\0';
-
+
return line[bg + indx];
}
int bg, en;
//TODO, check more thorougly
if (!param_getptr(line, &bg, &en, paramnum)) return 1;
- // return strtoul(&line[bg], NULL, 10) & 0xff;
+ // return strtoul(&line[bg], NULL, 10) & 0xff;
return 0;
}
{
int bg, en;
- if (!param_getptr(line, &bg, &en, paramnum))
+ if (!param_getptr(line, &bg, &en, paramnum))
return strtoul(&line[bg], NULL, base) & 0xff;
else
return deflt;
{
int bg, en;
- if (!param_getptr(line, &bg, &en, paramnum))
+ if (!param_getptr(line, &bg, &en, paramnum))
return strtoul(&line[bg], NULL, base);
else
return deflt;
{
int bg, en;
- if (!param_getptr(line, &bg, &en, paramnum))
+ if (!param_getptr(line, &bg, &en, paramnum))
return strtoull(&line[bg], NULL, base);
else
return deflt;
}
-int param_gethex(const char *line, int paramnum, uint8_t * data, int hexcnt)
+int param_gethex(const char *line, int paramnum, uint8_t *data, int hexcnt)
{
int bg, en, temp, i;
if (hexcnt % 2)
return 1;
-
+
if (param_getptr(line, &bg, &en, paramnum)) return 1;
- if (en - bg + 1 != hexcnt)
+ if (en - bg + 1 != hexcnt)
return 1;
for(i = 0; i < hexcnt; i += 2) {
- if (!(isxdigit((unsigned char)line[bg + i]) && isxdigit((unsigned char)line[bg + i + 1])) ) return 1;
-
+ if (!(isxdigit((unsigned char)line[bg + i]) && isxdigit((unsigned char)line[bg + i + 1])) ) return 1;
+
sscanf((char[]){line[bg + i], line[bg + i + 1], 0}, "%X", &temp);
data[i / 2] = temp & 0xff;
- }
+ }
return 0;
}
int bg, en, temp, i;
//if (hexcnt % 2)
- // return 1;
-
+ // return 1;
+
if (param_getptr(line, &bg, &en, paramnum)) return 1;
if (en - bg + 1 > *hexcnt) return 1;
-
+
*hexcnt = en - bg + 1;
if (*hexcnt % 2) //error if not complete hex bytes
return 1;
for(i = 0; i < *hexcnt; i += 2) {
- if (!(isxdigit((unsigned char)line[bg + i]) && isxdigit((unsigned char)line[bg + i + 1])) ) return 1;
-
+ if (!(isxdigit((unsigned char)line[bg + i]) && isxdigit((unsigned char)line[bg + i + 1])) ) return 1;
+
sscanf((char[]){line[bg + i], line[bg + i + 1], 0}, "%X", &temp);
data[i / 2] = temp & 0xff;
- }
+ }
return 0;
}
if (param_getptr(line, &bg, &en, paramnum)) return 1;
*datalen = 0;
-
+
int indx = bg;
while (line[indx]) {
if (line[indx] == '\t' || line[indx] == ' ') {
indx++;
continue;
}
-
+
if (isxdigit((unsigned char)line[indx])) {
buf[strlen(buf) + 1] = 0x00;
buf[strlen(buf)] = line[indx];
} else {
// if we have symbols other than spaces and hex
return 1;
- }
+ }
if (*datalen >= maxdatalen) {
// if we dont have space in buffer and have symbols to translate
*buf = 0;
(*datalen)++;
}
-
+
indx++;
}
- if (strlen(buf) > 0)
+ if (strlen(buf) > 0)
//error when not completed hex bytes
return 3;
-
+
return 0;
}
{
int bg, en;
- if (param_getptr(line, &bg, &en, paramnum)) {
+ if (param_getptr(line, &bg, &en, paramnum)) {
return 0;
}
printf("out of bounds error: want %d bytes have %zd bytes\n", en - bg + 1 + 1, buffersize);
return 0;
}
-
+
memcpy(str, line + bg, en - bg + 1);
str[en - bg + 1] = 0;
-
+
return en - bg + 1;
}
// returns number of bits converted
int hextobinarray(char *target, char *source)
{
- int length, i, count= 0;
- char* start = source;
- char x;
-
- length = strlen(source);
- // process 4 bits (1 hex digit) at a time
- while(length--)
- {
- x= *(source++);
- // capitalize
- if (x >= 'a' && x <= 'f')
- x -= 32;
- // convert to numeric value
- if (x >= '0' && x <= '9')
- x -= '0';
- else if (x >= 'A' && x <= 'F')
- x -= 'A' - 10;
- else {
- printf("Discovered unknown character %c %d at idx %tu of %s\n", x, x, source - start, start);
- return 0;
- }
- // output
- for(i= 0 ; i < 4 ; ++i, ++count)
- *(target++)= (x >> (3 - i)) & 1;
- }
-
- return count;
+ int length, i, count= 0;
+ char* start = source;
+ char x;
+
+ length = strlen(source);
+ // process 4 bits (1 hex digit) at a time
+ while(length--)
+ {
+ x= *(source++);
+ // capitalize
+ if (x >= 'a' && x <= 'f')
+ x -= 32;
+ // convert to numeric value
+ if (x >= '0' && x <= '9')
+ x -= '0';
+ else if (x >= 'A' && x <= 'F')
+ x -= 'A' - 10;
+ else {
+ printf("Discovered unknown character %c %d at idx %tu of %s\n", x, x, source - start, start);
+ return 0;
+ }
+ // output
+ for(i= 0 ; i < 4 ; ++i, ++count)
+ *(target++)= (x >> (3 - i)) & 1;
+ }
+
+ return count;
}
// convert binary array of 0x00/0x01 values to hex (safe to do in place as target will always be shorter than source)
// return number of bits converted
int binarraytohex(char *target,char *source, int length)
{
- unsigned char i, x;
- int j = length;
+ unsigned char i, x;
+ int j = length;
- if(j % 4)
- return 0;
+ if(j % 4)
+ return 0;
- while(j)
- {
- for(i= x= 0 ; i < 4 ; ++i)
- x += ( source[i] << (3 - i));
- sprintf(target,"%X", (unsigned int)x);
- ++target;
- source += 4;
- j -= 4;
- }
- return length;
+ while(j)
+ {
+ for(i= x= 0 ; i < 4 ; ++i)
+ x += ( source[i] << (3 - i));
+ sprintf(target,"%X", (unsigned int)x);
+ ++target;
+ source += 4;
+ j -= 4;
+ }
+ return length;
}
// return parity bit required to match type
uint8_t GetParity( uint8_t *bits, uint8_t type, int length)
{
- int x;
+ int x;
- for(x= 0 ; length > 0 ; --length)
- x += bits[length - 1];
- x %= 2;
+ for(x= 0 ; length > 0 ; --length)
+ x += bits[length - 1];
+ x %= 2;
- return x ^ type;
+ return x ^ type;
}
// add HID parity to binary array: EVEN prefix for 1st half of ID, ODD suffix for 2nd half
void wiegand_add_parity(uint8_t *target, uint8_t *source, uint8_t length)
{
- *(target++)= GetParity(source, EVEN, length / 2);
- memcpy(target, source, length);
- target += length;
- *(target)= GetParity(source + length / 2, ODD, length / 2);
+ *(target++)= GetParity(source, EVEN, length / 2);
+ memcpy(target, source, length);
+ target += length;
+ *(target)= GetParity(source + length / 2, ODD, length / 2);
}
// xor two arrays together for len items. The dst array contains the new xored values.
void xor(unsigned char *dst, unsigned char *src, size_t len) {
for( ; len > 0; len--,dst++,src++)
- *dst ^= *src;
+ *dst ^= *src;
}
// RotateLeft - Ultralight, Desfire, works on byte level
// 00-01-02 >> 01-02-00
void rol(uint8_t *data, const size_t len){
- uint8_t first = data[0];
- for (size_t i = 0; i < len-1; i++) {
- data[i] = data[i+1];
- }
- data[len-1] = first;
+ uint8_t first = data[0];
+ for (size_t i = 0; i < len-1; i++) {
+ data[i] = data[i+1];
+ }
+ data[len-1] = first;
}
// Replace unprintable characters with a dot in char buffer
void clean_ascii(unsigned char *buf, size_t len) {
for (size_t i = 0; i < len; i++) {
- if (!isprint(buf[i]))
- buf[i] = '.';
+ if (!isprint(buf[i]))
+ buf[i] = '.';
}
}
// replace char in buffer
void strcreplace(char *buf, size_t len, char from, char to) {
for (size_t i = 0; i < len; i++) {
- if (buf[i] == from)
- buf[i] = to;
+ if (buf[i] == from)
+ buf[i] = to;
}
}
if ((str = (char*) malloc(strlen(buf) + 1)) != NULL) {
memset(str, 0, strlen(buf) + 1);
strcpy(str, buf);
- }
+ }
return str;
}
#define MIFARE_CMD_TRANSFER 0xB0
#define MIFARE_EV1_PERSONAL_UID 0x40
+#define MIFARE_EV1_UIDF0 0x00
+#define MIFARE_EV1_UIDF1 0x40
+#define MIFARE_EV1_UIDF2 0x20
+#define MIFARE_EV1_UIDF3 0x60
#define MIFARE_EV1_SETMODE 0x43
#define MIFARE_ULC_WRITE 0xA2
#define TOPAZ_WRITE_E8 0x54 // Write-with-erase (eight bytes)
#define TOPAZ_WRITE_NE8 0x1B // Write-no-erase (eight bytes)
+// HITAG1 commands
+#define HITAG1_SET_CCNEW 0xC2 // left 5 bits only
+#define HITAG1_READ_ID 0x00 // not a real command, consists of 5 bits length, <length> bits partial SN, 8 bits CRC
+#define HITAG1_SELECT 0x00 // left 5 bits only, followed by 32 bits SN and 8 bits CRC
+#define HITAG1_WRPPAGE 0x80 // left 4 bits only, followed by 8 bits page and 8 bits CRC
+#define HITAG1_WRPBLK 0x90 // left 4 bits only, followed by 8 bits block and 8 bits CRC
+#define HITAG1_WRCPAGE 0xA0 // left 4 bits only, followed by 8 bits page or key information and 8 bits CRC
+#define HITAG1_WRCBLK 0xB0 // left 4 bits only, followed by 8 bits block and 8 bits CRC
+#define HITAG1_RDPPAGE 0xC0 // left 4 bits only, followed by 8 bits page and 8 bits CRC
+#define HITAG1_RDPBLK 0xD0 // left 4 bits only, followed by 8 bits block and 8 bits CRC
+#define HITAG1_RDCPAGE 0xE0 // left 4 bits only, followed by 8 bits page and 8 bits CRC
+#define HITAG1_RDCBLK 0xF0 // left 4 bits only, followed by 8 bits block and 8 bits CRC
+#define HITAG1_HALT 0x70 // left 4 bits only, followed by 8 bits (dummy) page and 8 bits CRC
+
+// HITAG2 commands
+#define HITAG2_START_AUTH 0xC0 // left 5 bits only
+#define HITAG2_READ_PAGE 0xC0 // page number in bits 5 to 3, page number inverted in bit 0 and following 2 bits
+#define HITAG2_READ_PAGE_INVERTED 0x44 // page number in bits 5 to 3, page number inverted in bit 0 and following 2 bits
+#define HITAG2_WRITE_PAGE 0x82 // page number in bits 5 to 3, page number inverted in bit 0 and following 2 bits
+#define HITAG2_HALT 0x00 // left 5 bits only
#define ISO_14443A 0
#define ICLASS 1
WHT2F_CRYPTO = 24,
RHT2F_TEST_AUTH_ATTEMPTS = 25,
RHT2F_UID_ONLY = 26,
+ WHT2F_PASSWORD = 27,
} hitag_function;
typedef struct {
#define CMD_MIFARE_ACQUIRE_ENCRYPTED_NONCES 0x0613
#define CMD_MIFARE_READBL 0x0620
-#define CMD_MIFAREU_READBL 0x0720
#define CMD_MIFARE_READSC 0x0621
-#define CMD_MIFAREU_READCARD 0x0721
#define CMD_MIFARE_WRITEBL 0x0622
-#define CMD_MIFAREU_WRITEBL 0x0722
-#define CMD_MIFAREU_WRITEBL_COMPAT 0x0723
-
#define CMD_MIFARE_CHKKEYS 0x0623
-
+#define CMD_MIFARE_PERSONALIZE_UID 0x0624
#define CMD_MIFARE_SNIFFER 0x0630
+
//ultralightC
+#define CMD_MIFAREU_READBL 0x0720
+#define CMD_MIFAREU_READCARD 0x0721
+#define CMD_MIFAREU_WRITEBL 0x0722
+#define CMD_MIFAREU_WRITEBL_COMPAT 0x0723
#define CMD_MIFAREUC_AUTH 0x0724
//0x0725 and 0x0726 no longer used
#define CMD_MIFAREUC_SETPWD 0x0727