X-Git-Url: https://git.zerfleddert.de/cgi-bin/gitweb.cgi/proxmark3-svn/blobdiff_plain/f71f4deb8f8f1e932c81f3e62e6ab67012e07b33..09181a54620f1f8feda0cada2daf7058cf482ad3:/armsrc/hitag2.c diff --git a/armsrc/hitag2.c b/armsrc/hitag2.c index 4a2d9d9d..12bea2e5 100644 --- a/armsrc/hitag2.c +++ b/armsrc/hitag2.c @@ -21,42 +21,14 @@ #include "util.h" #include "hitag2.h" #include "string.h" +#include "BigBuf.h" static bool bQuiet; - static bool bCrypto; static bool bAuthenticating; static bool bPwd; static bool bSuccessful; - -static int LogTraceHitag(const uint8_t * btBytes, int iBits, int iSamples, uint32_t dwParity, int bReader) -{ - static uint16_t traceLen = 0; - uint8_t *trace = BigBuf_get_addr(); - - // Return when trace is full - if (traceLen + sizeof(rsamples) + sizeof(dwParity) + sizeof(iBits) + nbytes(iBits) > BigBuf_max_traceLen()) 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 { @@ -169,6 +141,16 @@ static u64 _hitag2_round (u64 *state) 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; @@ -177,16 +159,13 @@ static u32 _hitag2_byte (u64 * x) 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; } @@ -248,16 +227,16 @@ static int hitag2_cipher_transcrypt(uint64_t* cs, byte_t *data, unsigned int byt #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 @@ -449,11 +428,10 @@ static void hitag_reader_send_bit(int bit) { 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(); } @@ -500,26 +478,26 @@ static bool hitag2_password(byte_t* rx, const size_t rxlen, byte_t* tx, size_t* *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; @@ -569,9 +547,9 @@ static bool hitag2_crypto(byte_t* rx, const size_t rxlen, byte_t* tx, size_t* tx bCrypto = false; } } else { - *txlen = 5; - memcpy(tx,"\xc0",nbytes(*txlen)); - } + *txlen = 5; + memcpy(tx,"\xc0",nbytes(*txlen)); + } } break; // Received UID, crypto tag answer @@ -585,20 +563,20 @@ static bool hitag2_crypto(byte_t* rx, const size_t rxlen, byte_t* tx, size_t* tx 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); @@ -614,11 +592,11 @@ static bool hitag2_crypto(byte_t* rx, const size_t rxlen, byte_t* tx, size_t* tx } - 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; @@ -650,8 +628,7 @@ static bool hitag2_authenticate(byte_t* rx, const size_t rxlen, byte_t* tx, size bCrypto = true; } else { DbpString("Authentication succesful!"); - // We are done... for now - return false; + return true; } } break; @@ -735,22 +712,24 @@ void SnoopHitag(uint32_t type) { byte_t rx[HITAG_FRAME_LEN]; size_t rxlen=0; + FpgaDownloadAndGo(FPGA_BITSTREAM_LF); + + // Clean up trace and prepare it for storing frames + set_tracing(TRUE); + clear_trace(); + 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); - - // Clean up trace and prepare it for storing frames - iso14a_set_tracing(TRUE); - iso14a_clear_trace(); DbpString("Starting Hitag2 snoop"); LED_D_ON(); // 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 | FPGA_LF_EDGE_DETECT_TOGGLE_MODE); FpgaSendCommand(FPGA_CMD_SET_DIVISOR, 95); //125Khz SetAdcMuxFor(GPIO_MUXSEL_LOPKD); @@ -788,7 +767,7 @@ void SnoopHitag(uint32_t type) { bSkip = true; tag_sof = 4; - while(!BUTTON_PRESS()) { + while(!BUTTON_PRESS() && !usb_poll_validate_length()) { // Watchdog hit WDT_HIT(); @@ -930,7 +909,7 @@ void SnoopHitag(uint32_t type) { 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"); @@ -947,6 +926,12 @@ void SimulateHitagTag(bool tag_mem_supplied, byte_t* data) { bool bQuitTraceFull = false; bQuiet = false; + FpgaDownloadAndGo(FPGA_BITSTREAM_LF); + + // Clean up trace and prepare it for storing frames + set_tracing(TRUE); + clear_trace(); + auth_table_len = 0; auth_table_pos = 0; byte_t* auth_table; @@ -954,10 +939,6 @@ void SimulateHitagTag(bool tag_mem_supplied, byte_t* data) { auth_table = (byte_t *)BigBuf_malloc(AUTH_TABLE_LENGTH); memset(auth_table, 0x00, AUTH_TABLE_LENGTH); - // Clean up trace and prepare it for storing frames - iso14a_set_tracing(TRUE); - iso14a_clear_trace(); - DbpString("Starting Hitag2 simulation"); LED_D_ON(); hitag2_init(); @@ -978,7 +959,6 @@ void SimulateHitagTag(bool tag_mem_supplied, byte_t* data) { // 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 | FPGA_LF_EDGE_DETECT_READER_FIELD); FpgaSendCommand(FPGA_CMD_SET_DIVISOR, 95); //125Khz SetAdcMuxFor(GPIO_MUXSEL_LOPKD); @@ -998,7 +978,7 @@ void SimulateHitagTag(bool tag_mem_supplied, byte_t* data) { AT91C_BASE_PMC->PMC_PCER = (1 << AT91C_ID_TC1); AT91C_BASE_PIOA->PIO_BSR = GPIO_SSC_FRAME; - // Disable timer during configuration + // Disable timer during configuration AT91C_BASE_TC1->TC_CCR = AT91C_TC_CLKDIS; // Capture mode, default timer source = MCK/2 (TIMER_CLOCK1), TIOA is external trigger, @@ -1014,7 +994,7 @@ void SimulateHitagTag(bool tag_mem_supplied, byte_t* data) { // Enable and reset counter AT91C_BASE_TC1->TC_CCR = AT91C_TC_CLKEN | AT91C_TC_SWTRG; - while(!BUTTON_PRESS()) { + while(!BUTTON_PRESS() && !usb_poll_validate_length()) { // Watchdog hit WDT_HIT(); @@ -1118,7 +1098,7 @@ void SimulateHitagTag(bool tag_mem_supplied, byte_t* data) { FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); DbpString("Sim Stopped"); - + set_tracing(TRUE); } void ReaderHitag(hitag_function htf, hitag_data* htd) { @@ -1142,8 +1122,8 @@ void ReaderHitag(hitag_function htf, hitag_data* htd) { bSuccessful = false; // Clean up trace and prepare it for storing frames - iso14a_set_tracing(TRUE); - iso14a_clear_trace(); + set_tracing(TRUE); + clear_trace(); DbpString("Starting Hitag reader family"); @@ -1190,6 +1170,7 @@ void ReaderHitag(hitag_function htf, hitag_data* htd) { default: { Dbprintf("Error, unknown function: %d",htf); + set_tracing(FALSE); return; } break; } @@ -1239,26 +1220,27 @@ void ReaderHitag(hitag_function htf, hitag_data* htd) { 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; + } while(!bStop && !BUTTON_PRESS()) { // Watchdog hit @@ -1296,6 +1278,7 @@ void ReaderHitag(hitag_function htf, hitag_data* htd) { } break; default: { Dbprintf("Error, unknown function: %d",htf); + set_tracing(FALSE); return; } break; } @@ -1403,7 +1386,7 @@ void ReaderHitag(hitag_function htf, hitag_data* htd) { 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