bool bPwd;
bool bSuccessful;
+int LogTraceHitag(const uint8_t * btBytes, int iBits, int iSamples, uint32_t dwParity, int bReader)
+{
+ // Return when trace is full
+ if (traceLen >= TRACE_SIZE) return FALSE;
+
+ // Trace the random, i'm curious
+ rsamples += iSamples;
+ trace[traceLen++] = ((rsamples >> 0) & 0xff);
+ trace[traceLen++] = ((rsamples >> 8) & 0xff);
+ trace[traceLen++] = ((rsamples >> 16) & 0xff);
+ trace[traceLen++] = ((rsamples >> 24) & 0xff);
+ if (!bReader) {
+ trace[traceLen - 1] |= 0x80;
+ }
+ trace[traceLen++] = ((dwParity >> 0) & 0xff);
+ trace[traceLen++] = ((dwParity >> 8) & 0xff);
+ trace[traceLen++] = ((dwParity >> 16) & 0xff);
+ trace[traceLen++] = ((dwParity >> 24) & 0xff);
+ trace[traceLen++] = iBits;
+ memcpy(trace + traceLen, btBytes, nbytes(iBits));
+ traceLen += nbytes(iBits);
+ return TRUE;
+}
+
struct hitag2_tag {
uint32_t uid;
enum {
return c;
}
-size_t nbytes(size_t nbits) {
- return (nbits/8)+((nbits%8)>0);
-}
-
int hitag2_reset(void)
{
tag.state = TAG_STATE_RESET;
break;
}
-// LogTrace(rx,nbytes(rxlen),0,0,false);
-// LogTrace(tx,nbytes(*txlen),0,0,true);
+// LogTraceHitag(rx,rxlen,0,0,false);
+// LogTraceHitag(tx,*txlen,0,0,true);
if(tag.crypto_active) {
hitag2_cipher_transcrypt(&(tag.cs), tx, *txlen/8, *txlen%8);
case 0: {
// Stop if there is no answer while we are in crypto mode (after sending NrAr)
if (bCrypto) {
- DbpString("Authentication failed!");
- return false;
- }
- *txlen = 5;
- memcpy(tx,"\xc0",nbytes(*txlen));
+ // 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 {
+ *txlen = 5;
+ memcpy(tx,"\xc0",nbytes(*txlen));
+ }
} break;
// Received UID, crypto tag answer
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!",NrAr[0],NrAr[1],NrAr[2],NrAr[3],NrAr[4],NrAr[5],NrAr[6],NrAr[7]);
+ 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;
+
+ // Return if we reached the end of the authentiactions table
bCrypto = false;
- if ((auth_table_pos+8) == auth_table_len) {
+ if (auth_table_pos == auth_table_len) {
return false;
}
- 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);
}
*txlen = 5;
// Set up eavesdropping mode, frequency divisor which will drive the FPGA
// and analog mux selection.
+ FpgaDownloadAndGo(FPGA_BITSTREAM_LF);
FpgaWriteConfWord(FPGA_MAJOR_MODE_LF_EDGE_DETECT);
FpgaSendCommand(FPGA_CMD_SET_DIVISOR, 95); //125Khz
SetAdcMuxFor(GPIO_MUXSEL_LOPKD);
// Check if frame was captured
if(rxlen > 0) {
frame_count++;
- if (!LogTrace(rx,nbytes(rxlen),response,0,reader_frame)) {
+ if (!LogTraceHitag(rx,rxlen,response,0,reader_frame)) {
DbpString("Trace full");
break;
}
// Set up simulator mode, frequency divisor which will drive the FPGA
// and analog mux selection.
+ FpgaDownloadAndGo(FPGA_BITSTREAM_LF);
FpgaWriteConfWord(FPGA_MAJOR_MODE_LF_EDGE_DETECT);
FpgaSendCommand(FPGA_CMD_SET_DIVISOR, 95); //125Khz
SetAdcMuxFor(GPIO_MUXSEL_LOPKD);
if(rxlen > 4) {
frame_count++;
if (!bQuiet) {
- if (!LogTrace(rx,nbytes(rxlen),response,0,true)) {
+ if (!LogTraceHitag(rx,rxlen,response,0,true)) {
DbpString("Trace full");
if (bQuitTraceFull) {
break;
hitag_send_frame(tx,txlen);
// Store the frame in the trace
if (!bQuiet) {
- if (!LogTrace(tx,nbytes(txlen),0,0,false)) {
+ if (!LogTraceHitag(tx,txlen,0,0,false)) {
DbpString("Trace full");
if (bQuitTraceFull) {
break;
bool bStop;
bool bQuitTraceFull = false;
+ FpgaDownloadAndGo(FPGA_BITSTREAM_LF);
// Reset the return status
bSuccessful = false;
case RHT2F_PASSWORD: {
Dbprintf("List identifier in password mode");
memcpy(password,htd->pwd.password,4);
- blocknr = 0;
+ blocknr = 0;
bQuitTraceFull = false;
bQuiet = false;
bPwd = false;
case RHT2F_CRYPTO: {
DbpString("Authenticating using key:");
- memcpy(key,htd->crypto.key,6);
+ memcpy(key,htd->crypto.key,4);
Dbhexdump(6,key,false);
blocknr = 0;
bQuiet = false;
if(rxlen > 0) {
frame_count++;
if (!bQuiet) {
- if (!LogTrace(rx,nbytes(rxlen),response,0,false)) {
+ if (!LogTraceHitag(rx,rxlen,response,0,false)) {
DbpString("Trace full");
if (bQuitTraceFull) {
break;
frame_count++;
if (!bQuiet) {
// Store the frame in the trace
- if (!LogTrace(tx,nbytes(txlen),HITAG_T_WAIT_2,0,true)) {
+ if (!LogTraceHitag(tx,txlen,HITAG_T_WAIT_2,0,true)) {
if (bQuitTraceFull) {
break;
} else {