#include "BigBuf.h"
static bool bQuiet;
-
static bool bCrypto;
static bool bAuthenticating;
static bool bPwd;
static bool bSuccessful;
-
-
struct hitag2_tag {
uint32_t uid;
enum {
#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))
static const u32 ht2_f4a = 0x2C79; // 0010 1100 0111 1001
static u32 _f20 (const u64 x)
{
- u32 i5;
+ u32 i5;
i5 = ((ht2_f4a >> i4 (x, 1, 2, 4, 5)) & 1)* 1
+ ((ht2_f4b >> i4 (x, 7,11,13,14)) & 1)* 2
static u64 _hitag2_init (const u64 key, const u32 serial, const u32 IV)
{
- u32 i;
- u64 x = ((key & 0xFFFF) << 32) + serial;
+ u32 i;
+ u64 x = ((key & 0xFFFF) << 32) + serial;
for (i = 0; i < 32; i++)
{
static u64 _hitag2_round (u64 *state)
{
- u64 x = *state;
+ u64 x = *state;
x = (x >> 1) +
((((x >> 0) ^ (x >> 2) ^ (x >> 3) ^ (x >> 6)
return _f20 (x);
}
+// "MIKRON" = O N M I K R
+// Key = 4F 4E 4D 49 4B 52 - Secret 48-bit key
+// Serial = 49 43 57 69 - Serial number of the tag, transmitted in clear
+// Random = 65 6E 45 72 - Random IV, transmitted in clear
+//~28~DC~80~31 = D7 23 7F CE - Authenticator value = inverted first 4 bytes of the keystream
+
+// The code below must print out "D7 23 7F CE 8C D0 37 A9 57 49 C1 E6 48 00 8A B6".
+// The inverse of the first 4 bytes is sent to the tag to authenticate.
+// The rest is encrypted by XORing it with the subsequent keystream.
+
static u32 _hitag2_byte (u64 * x)
{
- u32 i, c;
+ u32 i, c;
for (i = 0, c = 0; i < 8; i++) c += (u32) _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;
}
#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_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_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
// Binary puls length modulation (BPLM) is used to encode the data stream
// This means that a transmission of a one takes longer than that of a zero
- // Enable modulation, which means, drop the the field
+ // Enable modulation, which means, drop the field
HIGH(GPIO_SSC_DOUT);
// Wait for 4-10 times the carrier period
if(bit == 0) {
// Zero bit: |_-|
while(AT91C_BASE_TC0->TC_CV < T0*22);
- // SpinDelayUs(16*8);
+
} else {
// One bit: |_--|
while(AT91C_BASE_TC0->TC_CV < T0*28);
- // SpinDelayUs(22*8);
}
LED_A_OFF();
}
}
// Send EOF
AT91C_BASE_TC0->TC_CCR = AT91C_TC_SWTRG;
- // Enable modulation, which means, drop the the field
+ // 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);
*txlen = 32;
memcpy(tx,password,4);
bPwd = true;
- memcpy(tag.sectors[blocknr],rx,4);
- blocknr++;
+ memcpy(tag.sectors[blocknr],rx,4);
+ blocknr++;
} else {
- if(blocknr == 1){
- //store password in block1, the TAG answers with Block3, but we need the password in memory
- memcpy(tag.sectors[blocknr],tx,4);
- }else{
- memcpy(tag.sectors[blocknr],rx,4);
- }
-
- blocknr++;
- if (blocknr > 7) {
- DbpString("Read succesful!");
- bSuccessful = true;
- return false;
- }
- *txlen = 10;
- tx[0] = 0xc0 | (blocknr << 3) | ((blocknr^7) >> 2);
- tx[1] = ((blocknr^7) << 6);
+ if(blocknr == 1){
+ //store password in block1, the TAG answers with Block3, but we need the password in memory
+ memcpy(tag.sectors[blocknr],tx,4);
+ } else {
+ memcpy(tag.sectors[blocknr],rx,4);
+ }
+
+ blocknr++;
+ if (blocknr > 7) {
+ DbpString("Read succesful!");
+ bSuccessful = true;
+ return false;
+ }
+ *txlen = 10;
+ tx[0] = 0xc0 | (blocknr << 3) | ((blocknr^7) >> 2);
+ tx[1] = ((blocknr^7) << 6);
}
} break;
bCrypto = false;
}
} else {
- *txlen = 5;
- memcpy(tx,"\xc0",nbytes(*txlen));
- }
+ *txlen = 5;
+ memcpy(tx,"\xc0",nbytes(*txlen));
+ }
} break;
// Received UID, crypto tag answer
hitag2_cipher_transcrypt(&cipher_state,tx+4,4,0);
*txlen = 64;
bCrypto = true;
- bAuthenticating = true;
+ bAuthenticating = true;
} else {
// Check if we received answer tag (at)
if (bAuthenticating) {
- bAuthenticating = false;
+ bAuthenticating = false;
} else {
- // Store the received block
- memcpy(tag.sectors[blocknr],rx,4);
- blocknr++;
+ // Store the received block
+ memcpy(tag.sectors[blocknr],rx,4);
+ blocknr++;
}
if (blocknr > 7) {
- DbpString("Read succesful!");
- bSuccessful = true;
- return false;
+ DbpString("Read succesful!");
+ bSuccessful = true;
+ return false;
}
*txlen = 10;
tx[0] = 0xc0 | (blocknr << 3) | ((blocknr^7) >> 2);
}
- if(bCrypto) {
- // We have to return now to avoid double encryption
- if (!bAuthenticating) {
- hitag2_cipher_transcrypt(&cipher_state,tx,*txlen/8,*txlen%8);
- }
+ if(bCrypto) {
+ // We have to return now to avoid double encryption
+ if (!bAuthenticating) {
+ hitag2_cipher_transcrypt(&cipher_state, tx, *txlen/8, *txlen%8);
+ }
}
return true;
bCrypto = true;
} else {
DbpString("Authentication succesful!");
- // We are done... for now
- return false;
+ return true;
}
} break;
return true;
}
+static bool hitag2_read_uid(byte_t* rx, const size_t rxlen, byte_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;
+ // 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++;
+ }
+ if (blocknr > 0) {
+ //DbpString("Read successful!");
+ bSuccessful = true;
+ return false;
+ }
+ } break;
+ // Unexpected response
+ default: {
+ Dbprintf("Uknown frame length: %d",rxlen);
+ return false;
+ } break;
+ }
+ return true;
+}
void SnoopHitag(uint32_t type) {
int frame_count;
size_t rxlen=0;
FpgaDownloadAndGo(FPGA_BITSTREAM_LF);
-
+
+ // free eventually allocated BigBuf memory
+ BigBuf_free(); BigBuf_Clear_ext(false);
+
// Clean up trace and prepare it for storing frames
- set_tracing(TRUE);
clear_trace();
+ set_tracing(TRUE);
auth_table_len = 0;
auth_table_pos = 0;
- BigBuf_free();
auth_table = (byte_t *)BigBuf_malloc(AUTH_TABLE_LENGTH);
memset(auth_table, 0x00, AUTH_TABLE_LENGTH);
AT91C_BASE_TC0->TC_CCR = AT91C_TC_CLKDIS;
FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
LED_A_OFF();
-
+ set_tracing(TRUE);
// Dbprintf("frame received: %d",frame_count);
// Dbprintf("Authentication Attempts: %d",(auth_table_len/8));
// DbpString("All done");
FpgaDownloadAndGo(FPGA_BITSTREAM_LF);
+ // free eventually allocated BigBuf memory
+ BigBuf_free(); BigBuf_Clear_ext(false);
+
// Clean up trace and prepare it for storing frames
- set_tracing(TRUE);
clear_trace();
-
+ set_tracing(TRUE);
+
auth_table_len = 0;
auth_table_pos = 0;
byte_t* auth_table;
- BigBuf_free();
+
auth_table = (byte_t *)BigBuf_malloc(AUTH_TABLE_LENGTH);
memset(auth_table, 0x00, AUTH_TABLE_LENGTH);
FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
DbpString("Sim Stopped");
-
+ set_tracing(TRUE);
}
void ReaderHitag(hitag_function htf, hitag_data* htd) {
bSuccessful = false;
// Clean up trace and prepare it for storing frames
- set_tracing(TRUE);
clear_trace();
-
- DbpString("Starting Hitag reader family");
+ set_tracing(TRUE);
+
+ //DbpString("Starting Hitag reader family");
// Check configuration
switch(htf) {
case RHT2F_CRYPTO: {
DbpString("Authenticating using key:");
- memcpy(key,htd->crypto.key,4); //HACK; 4 or 6?? I read both in the code.
+ memcpy(key,htd->crypto.key,6); //HACK; 4 or 6?? I read both in the code.
Dbhexdump(6,key,false);
blocknr = 0;
bQuiet = 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);
+ set_tracing(FALSE);
return;
} break;
}
lastbit = 1;
bStop = false;
- // Tag specific configuration settings (sof, timings, etc.)
- if (htf < 10){
- // hitagS settings
- reset_sof = 1;
- t_wait = 200;
- DbpString("Configured for hitagS reader");
- } else if (htf < 20) {
- // hitag1 settings
- reset_sof = 1;
- t_wait = 200;
- DbpString("Configured for hitag1 reader");
- } else if (htf < 30) {
- // hitag2 settings
- reset_sof = 4;
- t_wait = HITAG_T_WAIT_2;
- DbpString("Configured for hitag2 reader");
+ // Tag specific configuration settings (sof, timings, etc.)
+ if (htf < 10){
+ // hitagS settings
+ reset_sof = 1;
+ t_wait = 200;
+ //DbpString("Configured for hitagS reader");
+ } else if (htf < 20) {
+ // hitag1 settings
+ reset_sof = 1;
+ t_wait = 200;
+ //DbpString("Configured for hitag1 reader");
+ } else if (htf < 30) {
+ // hitag2 settings
+ reset_sof = 4;
+ 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);
+ set_tracing(FALSE);
+ return;
+ }
+ uint8_t attempt_count=0;
while(!bStop && !BUTTON_PRESS()) {
// Watchdog hit
WDT_HIT();
case RHT2F_TEST_AUTH_ATTEMPTS: {
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;
default: {
Dbprintf("Error, unknown function: %d",htf);
+ set_tracing(FALSE);
return;
} break;
}
bSkip = true;
tag_sof = reset_sof;
response = 0;
+ //Dbprintf("DEBUG: Waiting to receive frame");
+ uint32_t errorCount = 0;
// Receive frame, watch for at most T0*EOF periods
while (AT91C_BASE_TC1->TC_CV < T0*HITAG_T_WAIT_MAX) {
rxlen++;
}
} else {
+ //Dbprintf("DEBUG: Wierd2");
+ errorCount++;
// Ignore wierd value, is to small to mean anything
}
}
-
+ //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;
AT91C_BASE_TC1->TC_CCR = AT91C_TC_CLKDIS;
AT91C_BASE_TC0->TC_CCR = AT91C_TC_CLKDIS;
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);
-}
+// Dbprintf("DONE: frame received: %d",frame_count);
+ cmd_send(CMD_ACK,bSuccessful,0,0,(byte_t*)tag.sectors,48);
+ set_tracing(FALSE);
+}
\ No newline at end of file