version.c
lua
luac
+fpga_compress
fpga/*
!fpga/tests
## [unreleased][unreleased]
### Added
+- Added lf pyramid commands (iceman)
+- Added lf presco commands - some bits not fully understood... (iceman)
+- Added experimental HitagS support (Oguzhan Cicek, Hendrik Schwartke, Ralf Spenneberg)
+ see https://media.ccc.de/v/32c3-7166-sicherheit_von_125khz_transpondern_am_beispiel_hitag_s
+ English video available
+- Added a LF ASK Sequence Terminator detection option to the standard ask demod - and applied it to `lf search u`, `lf t55xx detect`, and `data rawdemod am s` (marshmellow)
- `lf t55xx bruteforce <start password> <end password> [i <*.dic>]` - Simple bruteforce attack to find password - (iceman and others)
- `lf viking clone`- clone viking tag to t55x7 or Q5 from 4byte hex ID input
- `lf viking sim` - sim full viking tag from 4byte hex ID input
- `lf t55xx wipe` - sets t55xx back to factory defaults
- Added viking demod to `lf search` (marshmellow)
- `data askvikingdemod` demod viking id tag from graphbuffer (marshmellow)
-- `lf t55xx resetread` added reset then read command - should allow determining start
-of stream transmissions (marshmellow)
+- `lf t55xx resetread` added reset then read command - should allow determining start of stream transmissions (marshmellow)
- `lf t55xx wakeup` added wake with password (AOR) to allow lf search or standard lf read after (iceman, marshmellow)
- `hf iclass managekeys` to save, load and manage iclass keys. (adjusted most commands to accept a loaded key in memory) (marshmellow)
- `hf iclass readblk` to select, authenticate, and read 1 block from an iclass card (marshmellow)
- Added 'hf snoop'. This command take digitalized signal from FPGA and put in BigBuffer. (pwpiwi + enio)
- Added Topaz (NFC type 1) protocol support ('hf topaz reader', 'hf list topaz', 'hf 14a raw -T', 'hf topaz snoop'). (piwi)
- Added option c to 'hf list' (mark CRC bytes) (piwi)
+- Added option `l` or `h` to `hw tune` to save time and unnecessary fpga writes if you are only interested in lf or hf.
### Changed
-- Added `[l] <length>` option to data printdemodbuffer
-- Adjusted lf awid clone to optionally clone to Q5 tags
-- Adjusted lf t55xx detect to find Q5 tags (t5555) instead of just t55x7
-- Adjusted all lf NRZ demods - works more accurately and consistently (as long as you have strong signal)
-- Adjusted lf pskindalademod to reduce false positive reads.
-- Small adjustments to psk, nrz, and ask clock detect routines - more reliable.
-- Adjusted lf em410x em410xsim to accept a clock argument
+- Fixed bug in lf biphase sim - `lf simask b` (and any tagtype that relies on it - gproxii...) (marshmellow)
+- Fixed bug in lf viking clone/sim (iceman)
+- Fixed broken `data askedgedetect` (marshmellow)
+- Adjusted hf mf sim command (marshmellow)
+ added auto run mfkey32 to extract all keys
+ also added f parameter to allow attacking with UIDs from a file (implies x and i parameters)
+ also added e parameter to allow adding the extracted keys to emulator memory for the next simulation
+ added 10 byte uid option
+- Added `[l] <length>` option to data printdemodbuffer (marshmellow)
+- Adjusted lf awid clone to optionally clone to Q5 tags (marshmellow)
+- Adjusted lf t55xx detect to find Q5 tags (t5555) instead of just t55x7 (marshmellow)
+- Adjusted all lf NRZ demods - works more accurately and consistently (as long as you have strong signal) (marshmellow)
+- Adjusted lf pskindalademod to reduce false positive reads. (marshmellow)
+- Small adjustments to psk, nrz, and ask clock detect routines - more reliable. (marshmellow)
+- Adjusted lf em410x em410xsim to accept a clock argument (marshmellow)
- Adjusted lf t55xx dump to allow overriding the safety check and warning text (marshmellow)
- Adjusted lf t55xx write input variables (marshmellow)
- Adjusted lf t55xx read with password safety check and warning text and adjusted the input variables (marshmellow & iceman)
-- Adjusted LF FSK demod to account for cross threshold fluctuations (898 count waves will adjust the 9 to 8 now...) more accurate.
+- Adjusted LF FSK demod to account for cross threshold fluctuations (898 count waves will adjust the 9 to 8 now...) more accurate. (marshmellow)
- Adjusted timings for t55xx commands. more reliable now. (marshmellow & iceman)
- `lf cmdread` adjusted input methods and added help text (marshmellow & iceman)
- changed `lf config t <threshold>` to be 0 - 128 and will trigger on + or - threshold value (marshmellow)
-- `hf iclass dump` cli options - can now dump AA1 and AA2 with different keys in one run (does not go to multiple pages for the larger tags yet)
+- `hf iclass dump` cli options - can now dump AA1 and AA2 with different keys in one run (does not go to multiple pages for the larger tags yet) (marshmellow)
- Revised workflow for StandAloneMode14a (Craig Young)
- EPA functions (`hf epa`) now support both ISO 14443-A and 14443-B cards (frederikmoellers)
- 'hw version' only talks to ARM at startup, after that the info is cached. (pwpiwi)
1 - Install Xcode and Xcode Command Line Tools
2 - Install Homebrew and dependencies
- brew install readline
- brew instal libusb
+ brew install readline libusb p7zip libusb-compat wget qt5 pkgconfig
-3 - Download DevKitARM for OSX
- http://sourceforge.net/projects/devkitpro/files/devkitARM/devkitARM_r44/
- Unpack devkitARM_r44-osx.tar.bz2 to proxmark3 directory.
+3 - Install DevKitARM for OSX
+ Option 1:
+ http://sourceforge.net/projects/devkitpro/files/devkitARM/devkitARM_r44/
+ Unpack devkitARM_r44-osx.tar.bz2 to proxmark3 directory.
+ Option 2:
+ brew tap nitsky/stm32
+ brew install arm-none-eabi-gcc
-4 - Edit proxmark3/client/Makefile adding path to readline
+4 - Edit proxmark3/client/Makefile adding path to readline and qt5
- LDLIBS = -L/usr/local/Cellar/readline/6.3.8/lib/ -L/opt/local/lib -L/usr/local/lib ../liblua/liblua.a -lreadline -lpthread -lm
- CFLAGS = -std=c99 -I/usr/local/Cellar/readline/6.3.8/include/ -I. -I../include -I../common -I/opt/local/include -I../liblua -Wall $(COMMON_FLAGS) -g -O4
+ LDLIBS = -L/usr/local/opt/readline/lib -L/usr/local/opt/qt5/lib -L/opt/local/lib -L/usr/local/lib ../liblua/liblua.a -lreadline -lpthread -lm
+ CFLAGS = -std=c99 -I/usr/local/opt/qt5/include -I/usr/local/opt/readline/include -I. -I../include -I../common -I../zlib -I/opt/local/include -I../liblua -Wall $(COMMON_FLAGS) -g -O4
- Replace path /usr/local/Cellar/readline/6.3.8 with your actuall readline path. See homebrew manuals.
+ If your old brew intallation use /usr/local/Cellar/ path replace /usr/local/opt/readline/lib with your actuall readline and qt5 path. See homebrew manuals.
5 - Set Environment
* http://proxmark3.com/
* http://www.xfpga.com/
+ * http://radiowar.taobao.com/
+ * http://www.elechouse.com/
+ * https://lab401.com/
Most of the ultra-low-volume contract assemblers could put
something like this together with a reasonable yield. A run of around
Dbprintf("Buffer cleared (%i bytes)",BIGBUF_SIZE);
}
+void BigBuf_Clear_keep_EM(void)
+{
+ memset(BigBuf,0,BigBuf_hi);
+}
// allocate a chunk of memory from BigBuf. We allocate high memory first. The unallocated memory
// at the beginning of BigBuf is always for traces/samples
#ifndef __BIGBUF_H
#define __BIGBUF_H
+#include <stdbool.h> // for bool
+#include "common.h" // for ramfunc
#define BIGBUF_SIZE 40000
#define MAX_FRAME_SIZE 256 // maximum allowed ISO14443 frame
extern uint16_t BigBuf_max_traceLen(void);
extern void BigBuf_Clear(void);
extern void BigBuf_Clear_ext(bool verbose);
+extern void BigBuf_Clear_keep_EM(void);
extern uint8_t *BigBuf_malloc(uint16_t);
extern void BigBuf_free(void);
extern void BigBuf_free_keep_EM(void);
#-DWITH_LCD
#SRC_LCD = fonts.c LCD.c
-SRC_LF = lfops.c hitag2.c lfsampling.c pcf7931.c lfdemod.c protocols.c
+SRC_LF = lfops.c hitag2.c hitagS.c lfsampling.c pcf7931.c lfdemod.c protocols.c
SRC_ISO15693 = iso15693.c iso15693tools.c
SRC_ISO14443a = epa.c iso14443a.c mifareutil.c mifarecmd.c mifaresniff.c
SRC_ISO14443b = iso14443b.c
#include "legicrf.h"
#include <hitag2.h>
+#include <hitagS.h>
#include "lfsampling.h"
#include "BigBuf.h"
#include "mifareutil.h"
#include "iso14443a.h"
#endif
-#define abs(x) ( ((x)<0) ? -(x) : (x) )
-
//=============================================================================
// A buffer where we can queue things up to be sent through the FPGA, for
// any purpose (fake tag, as reader, whatever). We go MSB first, since that
return (a + 15) >> 5;
}
-void MeasureAntennaTuning(void)
+void MeasureAntennaTuningLfOnly(int *vLf125, int *vLf134, int *peakf, int *peakv, uint8_t LF_Results[])
{
- uint8_t LF_Results[256];
- int i, adcval = 0, peak = 0, peakv = 0, peakf = 0; //ptr = 0
- int vLf125 = 0, vLf134 = 0, vHf = 0; // in mV
-
- LED_B_ON();
+ int i, adcval = 0, peak = 0;
/*
* Sweeps the useful LF range of the proxmark from
* the resonating frequency of your LF antenna
* ( hopefully around 95 if it is tuned to 125kHz!)
*/
-
- FpgaDownloadAndGo(FPGA_BITSTREAM_LF);
+
+ FpgaDownloadAndGo(FPGA_BITSTREAM_LF);
FpgaWriteConfWord(FPGA_MAJOR_MODE_LF_ADC | FPGA_LF_ADC_READER_FIELD);
for (i=255; i>=19; i--) {
- WDT_HIT();
+ WDT_HIT();
FpgaSendCommand(FPGA_CMD_SET_DIVISOR, i);
SpinDelay(20);
adcval = ((MAX_ADC_LF_VOLTAGE * AvgAdc(ADC_CHAN_LF)) >> 10);
- if (i==95) vLf125 = adcval; // voltage at 125Khz
- if (i==89) vLf134 = adcval; // voltage at 134Khz
+ if (i==95) *vLf125 = adcval; // voltage at 125Khz
+ if (i==89) *vLf134 = adcval; // voltage at 134Khz
LF_Results[i] = adcval>>8; // scale int to fit in byte for graphing purposes
if(LF_Results[i] > peak) {
- peakv = adcval;
+ *peakv = adcval;
peak = LF_Results[i];
- peakf = i;
+ *peakf = i;
//ptr = i;
}
}
for (i=18; i >= 0; i--) LF_Results[i] = 0;
-
- LED_A_ON();
+
+ return;
+}
+
+void MeasureAntennaTuningHfOnly(int *vHf)
+{
// Let the FPGA drive the high-frequency antenna around 13.56 MHz.
- FpgaDownloadAndGo(FPGA_BITSTREAM_HF);
+ LED_A_ON();
+ FpgaDownloadAndGo(FPGA_BITSTREAM_HF);
FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_READER_RX_XCORR);
SpinDelay(20);
- vHf = (MAX_ADC_HF_VOLTAGE * AvgAdc(ADC_CHAN_HF)) >> 10;
+ *vHf = (MAX_ADC_HF_VOLTAGE * AvgAdc(ADC_CHAN_HF)) >> 10;
+ LED_A_OFF();
+
+ return;
+}
+
+void MeasureAntennaTuning(int mode)
+{
+ uint8_t LF_Results[256] = {0};
+ int peakv = 0, peakf = 0;
+ int vLf125 = 0, vLf134 = 0, vHf = 0; // in mV
+
+ LED_B_ON();
+
+ if (((mode & FLAG_TUNE_ALL) == FLAG_TUNE_ALL) && (FpgaGetCurrent() == FPGA_BITSTREAM_HF)) {
+ // Reverse "standard" order if HF already loaded, to avoid unnecessary swap.
+ MeasureAntennaTuningHfOnly(&vHf);
+ MeasureAntennaTuningLfOnly(&vLf125, &vLf134, &peakf, &peakv, LF_Results);
+ } else {
+ if (mode & FLAG_TUNE_LF) {
+ MeasureAntennaTuningLfOnly(&vLf125, &vLf134, &peakf, &peakv, LF_Results);
+ }
+ if (mode & FLAG_TUNE_HF) {
+ MeasureAntennaTuningHfOnly(&vHf);
+ }
+ }
cmd_send(CMD_MEASURED_ANTENNA_TUNING, vLf125 | (vLf134<<16), vHf, peakf | (peakv<<16), LF_Results, 256);
FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
- LED_A_OFF();
LED_B_OFF();
return;
}
if (limit != HF_ONLY) {
if(mode == 1) {
- if (abs(lf_av - lf_baseline) > REPORT_CHANGE)
+ if (ABS(lf_av - lf_baseline) > REPORT_CHANGE)
LED_D_ON();
else
LED_D_OFF();
lf_av_new = AvgAdc(ADC_CHAN_LF);
// see if there's a significant change
- if(abs(lf_av - lf_av_new) > REPORT_CHANGE) {
+ if(ABS(lf_av - lf_av_new) > REPORT_CHANGE) {
Dbprintf("LF 125/134kHz Field Change: %5dmV", (MAX_ADC_LF_VOLTAGE * lf_av_new) >> 10);
lf_av = lf_av_new;
if (lf_av > lf_max)
if (limit != LF_ONLY) {
if (mode == 1){
- if (abs(hf_av - hf_baseline) > REPORT_CHANGE)
+ if (ABS(hf_av - hf_baseline) > REPORT_CHANGE)
LED_B_ON();
else
LED_B_OFF();
hf_av_new = AvgAdc(ADC_CHAN_HF);
// see if there's a significant change
- if(abs(hf_av - hf_av_new) > REPORT_CHANGE) {
+ if(ABS(hf_av - hf_av_new) > REPORT_CHANGE) {
Dbprintf("HF 13.56MHz Field Change: %5dmV", (MAX_ADC_HF_VOLTAGE * hf_av_new) >> 10);
hf_av = hf_av_new;
if (hf_av > hf_max)
case CMD_READER_HITAG: // Reader for Hitag tags, args = type and function
ReaderHitag((hitag_function)c->arg[0],(hitag_data*)c->d.asBytes);
break;
+ case CMD_SIMULATE_HITAG_S:// Simulate Hitag s tag, args = memory content
+ SimulateHitagSTag((bool)c->arg[0],(byte_t*)c->d.asBytes);
+ break;
+ case CMD_TEST_HITAGS_TRACES:// Tests every challenge within the given file
+ check_challenges((bool)c->arg[0],(byte_t*)c->d.asBytes);
+ break;
+ case CMD_READ_HITAG_S://Reader for only Hitag S tags, args = key or challenge
+ ReadHitagS((hitag_function)c->arg[0],(hitag_data*)c->d.asBytes);
+ break;
+ case CMD_WR_HITAG_S://writer for Hitag tags args=data to write,page and key or challenge
+ WritePageHitagS((hitag_function)c->arg[0],(hitag_data*)c->d.asBytes,c->arg[2]);
+ break;
#endif
#ifdef WITH_ISO15693
break;
case CMD_MEASURE_ANTENNA_TUNING:
- MeasureAntennaTuning();
+ MeasureAntennaTuning(c->arg[0]);
break;
case CMD_MEASURE_ANTENNA_TUNING_HF:
#include <stddef.h>
#include "common.h"
#include "hitag2.h"
+#include "hitagS.h"
#include "mifare.h"
#include "../common/crc32.h"
#include "BigBuf.h"
void SimulateHitagTag(bool tag_mem_supplied, byte_t* data);
void ReaderHitag(hitag_function htf, hitag_data* htd);
+//hitagS.h
+void SimulateHitagSTag(bool tag_mem_supplied, byte_t* data);
+void ReadHitagS(hitag_function htf, hitag_data* htd);
+void WritePageHitagS(hitag_function htf, hitag_data* htd,int page);
+void check_challenges(bool file_given, byte_t* data);
+
+
// cmd.h
bool cmd_receive(UsbCommand* cmd);
bool cmd_send(uint32_t cmd, uint32_t arg0, uint32_t arg1, uint32_t arg2, void* data, size_t len);
else if(downloaded_bitstream == FPGA_BITSTREAM_LF) Dbprintf(" mode.............LF");
else Dbprintf(" mode.............%d", downloaded_bitstream);
}
+
+int FpgaGetCurrent() {
+ return downloaded_bitstream;
+}
void SetupSpi(int mode);
bool FpgaSetupSscDma(uint8_t *buf, int len);
void Fpga_print_status();
+int FpgaGetCurrent();
#define FpgaDisableSscDma(void) AT91C_BASE_PDC_SSC->PDC_PTCR = AT91C_PDC_RXTDIS;
#define FpgaEnableSscDma(void) AT91C_BASE_PDC_SSC->PDC_PTCR = AT91C_PDC_RXTEN;
void SetAdcMuxFor(uint32_t whichGpio);
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;
--- /dev/null
+//-----------------------------------------------------------------------------
+// This code is licensed to you under the terms of the GNU GPL, version 2 or,
+// at your option, any later version. See the LICENSE.txt file for the text of
+// the license.
+//-----------------------------------------------------------------------------
+// HitagS emulation (preliminary test version)
+//
+// (c) 2016 Oguzhan Cicek, Hendrik Schwartke, Ralf Spenneberg
+// <info@os-s.de>
+//-----------------------------------------------------------------------------
+// Some code was copied from Hitag2.c
+//-----------------------------------------------------------------------------
+
+
+#include <stdlib.h>
+#include "proxmark3.h"
+#include "apps.h"
+#include "util.h"
+#include "hitagS.h"
+#include "hitag2.h"
+#include "string.h"
+#include "BigBuf.h"
+
+#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;
+static byte_t page_to_be_written = 0;
+static int block_data_left = 0;
+typedef enum modulation {
+ AC2K = 0, AC4K, MC4K, MC8K
+} MOD;
+static MOD m = AC2K; //used modulation
+static uint32_t temp_uid;
+static int temp2 = 0;
+static int sof_bits; //number of start-of-frame bits
+static byte_t pwdh0, pwdl0, pwdl1; //password bytes
+static uint32_t rnd = 0x74124485; //randomnumber
+static int test = 0;
+size_t blocknr;
+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 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
+
+static u32 f20(const u64 x) {
+ u32 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;
+
+ return (ht2_f5c >> i5) & 1;
+}
+static u64 hitag2_round(u64 *state) {
+ u64 x = *state;
+
+ x = (x >> 1)
+ + ((((x >> 0) ^ (x >> 2) ^ (x >> 3) ^ (x >> 6) ^ (x >> 7) ^ (x >> 8)
+ ^ (x >> 16) ^ (x >> 22) ^ (x >> 23) ^ (x >> 26) ^ (x >> 30)
+ ^ (x >> 41) ^ (x >> 42) ^ (x >> 43) ^ (x >> 46) ^ (x >> 47))
+ & 1) << 47);
+
+ *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;
+
+ for (i = 0, c = 0; i < 8; i++)
+ c += (u32) hitag2_round(x) << (i ^ 7);
+ return c;
+}
+
+// Sam7s has several timers, we will use the source TIMER_CLOCK1 (aka AT91C_TC_CLKS_TIMER_DIV1_CLOCK)
+// TIMER_CLOCK1 = MCK/2, MCK is running at 48 MHz, Timer is running at 48/2 = 24 MHz
+// Hitag units (T0) have duration of 8 microseconds (us), which is 1/125000 per second (carrier)
+// 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_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_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_THREE_HALF 41
+#define HITAG_T_TAG_CAPTURE_FOUR_HALF 57
+
+#define DEBUG 0
+
+/*
+ * Implementation of the crc8 calculation from Hitag S
+ * from http://www.proxmark.org/files/Documents/125%20kHz%20-%20Hitag/HitagS.V11.pdf
+ */
+void calc_crc(unsigned char * crc, unsigned char data, unsigned char Bitcount) {
+ *crc ^= data; // crc = crc (exor) data
+ do {
+ if (*crc & 0x80) // if (MSB-CRC == 1)
+ {
+ *crc <<= 1; // CRC = CRC Bit-shift left
+ *crc ^= CRC_POLYNOM; // CRC = CRC (exor) CRC_POLYNOM
+ } else {
+ *crc <<= 1; // CRC = CRC Bit-shift left
+ }
+ } while (--Bitcount);
+}
+
+static void hitag_send_bit(int bit) {
+ LED_A_ON();
+ // Reset clock for the next bit
+ AT91C_BASE_TC0->TC_CCR = AT91C_TC_SWTRG;
+
+ switch (m) {
+ case AC2K:
+ if (bit == 0) {
+ // AC Coding --__
+ HIGH(GPIO_SSC_DOUT);
+ while (AT91C_BASE_TC0->TC_CV < T0 * 32)
+ ;
+ LOW(GPIO_SSC_DOUT);
+ while (AT91C_BASE_TC0->TC_CV < T0 * 64)
+ ;
+ } else {
+ // AC coding -_-_
+ HIGH(GPIO_SSC_DOUT);
+ while (AT91C_BASE_TC0->TC_CV < T0 * 16)
+ ;
+ LOW(GPIO_SSC_DOUT);
+ while (AT91C_BASE_TC0->TC_CV < T0 * 32)
+ ;
+ HIGH(GPIO_SSC_DOUT);
+ while (AT91C_BASE_TC0->TC_CV < T0 * 48)
+ ;
+ LOW(GPIO_SSC_DOUT);
+ while (AT91C_BASE_TC0->TC_CV < T0 * 64)
+ ;;
+ }
+ LED_A_OFF();
+ break;
+ case AC4K:
+ if (bit == 0) {
+ // AC Coding --__
+ HIGH(GPIO_SSC_DOUT);
+ 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)
+ ;
+ } else {
+ // AC coding -_-_
+ HIGH(GPIO_SSC_DOUT);
+ while (AT91C_BASE_TC0->TC_CV < T0 * 8)
+ ;
+ LOW(GPIO_SSC_DOUT);
+ while (AT91C_BASE_TC0->TC_CV < T0 * 16)
+ ;
+ HIGH(GPIO_SSC_DOUT);
+ while (AT91C_BASE_TC0->TC_CV < T0 * 24)
+ ;
+ LOW(GPIO_SSC_DOUT);
+ while (AT91C_BASE_TC0->TC_CV < T0 * 32)
+ ;;
+ }
+ LED_A_OFF();
+ break;
+ case MC4K:
+ if (bit == 0) {
+ // Manchester: Unloaded, then loaded |__--|
+ LOW(GPIO_SSC_DOUT);
+ while (AT91C_BASE_TC0->TC_CV < T0 * 16)
+ ;
+ HIGH(GPIO_SSC_DOUT);
+ while (AT91C_BASE_TC0->TC_CV < T0 * 32)
+ ;
+ } else {
+ // Manchester: Loaded, then unloaded |--__|
+ HIGH(GPIO_SSC_DOUT);
+ while (AT91C_BASE_TC0->TC_CV < T0 * 16)
+ ;
+ LOW(GPIO_SSC_DOUT);
+ while (AT91C_BASE_TC0->TC_CV < T0 * 32)
+ ;
+ }
+ LED_A_OFF();
+ break;
+ case MC8K:
+ if (bit == 0) {
+ // Manchester: Unloaded, then loaded |__--|
+ LOW(GPIO_SSC_DOUT);
+ while (AT91C_BASE_TC0->TC_CV < T0 * 8)
+ ;
+ HIGH(GPIO_SSC_DOUT);
+ while (AT91C_BASE_TC0->TC_CV < T0 * 16)
+ ;
+ } else {
+ // Manchester: Loaded, then unloaded |--__|
+ HIGH(GPIO_SSC_DOUT);
+ while (AT91C_BASE_TC0->TC_CV < T0 * 8)
+ ;
+ LOW(GPIO_SSC_DOUT);
+ while (AT91C_BASE_TC0->TC_CV < T0 * 16)
+ ;
+ }
+ LED_A_OFF();
+ break;
+ default:
+ break;
+ }
+}
+
+static void hitag_send_frame(const byte_t* frame, size_t frame_len) {
+// Send start of frame
+
+ for (size_t i = 0; i < sof_bits; 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);
+ }
+// Drop the modulation
+ LOW(GPIO_SSC_DOUT);
+}
+
+static void hitag_reader_send_bit(int bit) {
+//Dbprintf("BIT: %d",bit);
+ LED_A_ON();
+// Reset clock for the next bit
+ AT91C_BASE_TC0->TC_CCR = AT91C_TC_SWTRG;
+
+// 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
+ HIGH(GPIO_SSC_DOUT);
+ if (test == 1) {
+ // Wait for 4-10 times the carrier period
+ while (AT91C_BASE_TC0->TC_CV < T0 * 6)
+ ;
+ // SpinDelayUs(8*8);
+
+ // Disable modulation, just activates the field again
+ LOW(GPIO_SSC_DOUT);
+
+ if (bit == 0) {
+ // Zero bit: |_-|
+ while (AT91C_BASE_TC0->TC_CV < T0 * 11)
+ ;
+ // SpinDelayUs(16*8);
+ } else {
+ // One bit: |_--|
+ while (AT91C_BASE_TC0->TC_CV < T0 * 14)
+ ;
+ // SpinDelayUs(22*8);
+ }
+ } else {
+ // Wait for 4-10 times the carrier period
+ while (AT91C_BASE_TC0->TC_CV < T0 * 6)
+ ;
+ // SpinDelayUs(8*8);
+
+ // 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);
+ } else {
+ // One bit: |_--|
+ while (AT91C_BASE_TC0->TC_CV < T0 * 28)
+ ;
+ // SpinDelayUs(22*8);
+ }
+ }
+
+ LED_A_OFF();
+}
+
+static void hitag_reader_send_frame(const byte_t* frame, size_t frame_len) {
+// Send the content of the frame
+ for (size_t i = 0; i < frame_len; i++) {
+ if (frame[0] == 0xf8) {
+ //Dbprintf("BIT: %d",(frame[i / 8] >> (7 - (i % 8))) & 1);
+ }
+ hitag_reader_send_bit((frame[i / 8] >> (7 - (i % 8))) & 1);
+ }
+// Send EOF
+ AT91C_BASE_TC0->TC_CCR = AT91C_TC_SWTRG;
+// Enable modulation, which means, drop the the field
+ HIGH(GPIO_SSC_DOUT);
+// Wait for 4-10 times the carrier period
+ while (AT91C_BASE_TC0->TC_CV < T0 * 6)
+ ;
+// Disable modulation, just activates the field again
+ LOW(GPIO_SSC_DOUT);
+}
+
+/*
+ * to check if the right uid was selected
+ */
+static int check_select(byte_t* rx, uint32_t uid) {
+ unsigned char resp[48];
+ int i;
+ uint32_t ans = 0x0;
+ for (i = 0; i < 48; i++)
+ resp[i] = (rx[i / 8] >> (7 - (i % 8))) & 0x1;
+ for (i = 0; i < 32; i++)
+ ans += resp[5 + i] << (31 - i);
+ /*if (rx[0] == 0x01 && rx[1] == 0x15 && rx[2] == 0xc1 && rx[3] == 0x14
+ && rx[4] == 0x65 && rx[5] == 0x38)
+ Dbprintf("got uid %X", ans);*/
+ temp_uid = ans;
+ if (ans == tag.uid)
+ return 1;
+ return 0;
+}
+
+/*
+ * handles all commands from a reader
+ */
+static void hitagS_handle_reader_command(byte_t* rx, const size_t rxlen,
+ byte_t* tx, size_t* txlen) {
+ byte_t rx_air[HITAG_FRAME_LEN];
+ byte_t page;
+ int i;
+ u64 state;
+ unsigned char crc;
+
+// Copy the (original) received frame how it is send over the air
+ memcpy(rx_air, rx, nbytes(rxlen));
+// Reset the transmission frame length
+ *txlen = 0;
+// Try to find out which command was send by selecting on length (in bits)
+ switch (rxlen) {
+ case 5: {
+ //UID request with a selected response protocol mode
+ tag.pstate = READY;
+ tag.tstate = NO_OP;
+ if ((rx[0] & 0xf0) == 0x30) {
+ tag.mode = STANDARD;
+ sof_bits = 1;
+ m = AC2K;
+ }
+ if ((rx[0] & 0xf0) == 0xc0) {
+ tag.mode = ADVANCED;
+ sof_bits = 3;
+ m = AC2K;
+ }
+
+ if ((rx[0] & 0xf0) == 0xd0) {
+ tag.mode = FAST_ADVANCED;
+ sof_bits = 3;
+ m = AC4K;
+ }
+ //send uid as a response
+ *txlen = 32;
+ for (i = 0; i < 4; i++)
+ tx[i] = (tag.uid >> (24 - (i * 8))) & 0xff;
+ }
+ break;
+ case 45: {
+ //select command from reader received
+ if (check_select(rx, tag.uid) == 1) {
+ //if the right tag was selected
+ *txlen = 32;
+ switch (tag.mode) {
+ case STANDARD:
+ sof_bits = 1;
+ m = MC4K;
+ break;
+ case ADVANCED:
+ sof_bits = 6;
+ m = MC4K;
+ break;
+ case FAST_ADVANCED:
+ sof_bits = 6;
+ m = MC8K;
+ break;
+ default:
+ break;
+ }
+
+ //send configuration
+ for (i = 0; i < 4; i++)
+ tx[i] = (tag.pages[0][1] >> (i * 8)) & 0xff;
+ tx[3] = 0xff;
+ if (tag.mode != STANDARD) {
+ *txlen = 40;
+ crc = CRC_PRESET;
+ for (i = 0; i < 4; i++)
+ calc_crc(&crc, tx[i], 8);
+ tx[4] = crc;
+ }
+ }
+ }
+ break;
+ case 64: {
+ //challenge message received
+ Dbprintf("Challenge for UID: %X", temp_uid);
+ temp2++;
+ *txlen = 32;
+ 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]);
+ switch (tag.mode) {
+ case STANDARD:
+ sof_bits = 1;
+ m = MC4K;
+ break;
+ case ADVANCED:
+ sof_bits = 6;
+ m = MC4K;
+ break;
+ case FAST_ADVANCED:
+ sof_bits = 6;
+ m = MC8K;
+ break;
+ default:
+ break;
+ }
+
+ for (i = 0; i < 4; i++)
+ hitag2_byte(&state);
+ //send con2,pwdh0,pwdl0,pwdl1 encrypted as a response
+ tx[0] = hitag2_byte(&state) ^ ((tag.pages[0][1] >> 16) & 0xff);
+ tx[1] = hitag2_byte(&state) ^ tag.pwdh0;
+ tx[2] = hitag2_byte(&state) ^ tag.pwdl0;
+ tx[3] = hitag2_byte(&state) ^ tag.pwdl1;
+ if (tag.mode != STANDARD) {
+ //add crc8
+ *txlen = 40;
+ crc = CRC_PRESET;
+ calc_crc(&crc, ((tag.pages[0][1] >> 16) & 0xff), 8);
+ calc_crc(&crc, tag.pwdh0, 8);
+ calc_crc(&crc, tag.pwdl0, 8);
+ calc_crc(&crc, tag.pwdl1, 8);
+ tx[4] = (crc ^ hitag2_byte(&state));
+ }
+ /*
+ * some readers do not allow to authenticate multiple times in a row with the same tag.
+ * use this to change the uid between authentications.
+ */
+
+ /*
+ if (temp2 % 2 == 0) {
+ tag.uid = 0x11223344;
+ tag.pages[0][0] = 0x44332211;
+ } else {
+ tag.uid = 0x55667788;
+ tag.pages[0][0] = 0x88776655;
+ }
+ */
+ }
+ case 40:
+ //data received to be written
+ if (tag.tstate == WRITING_PAGE_DATA) {
+ tag.tstate = NO_OP;
+ tag.pages[page_to_be_written / 4][page_to_be_written % 4] = (rx[0]
+ << 0) + (rx[1] << 8) + (rx[2] << 16) + (rx[3] << 24);
+ //send ack
+ *txlen = 2;
+ tx[0] = 0x40;
+ page_to_be_written = 0;
+ switch (tag.mode) {
+ case STANDARD:
+ sof_bits = 1;
+ m = MC4K;
+ break;
+ case ADVANCED:
+ sof_bits = 6;
+ m = MC4K;
+ break;
+ case FAST_ADVANCED:
+ sof_bits = 6;
+ m = MC8K;
+ break;
+ default:
+ break;
+ }
+ } else if (tag.tstate == WRITING_BLOCK_DATA) {
+ tag.pages[page_to_be_written / 4][page_to_be_written % 4] = (rx[0]
+ << 24) + (rx[1] << 16) + (rx[2] << 8) + rx[3];
+ //send ack
+ *txlen = 2;
+ tx[0] = 0x40;
+ switch (tag.mode) {
+ case STANDARD:
+ sof_bits = 1;
+ m = MC4K;
+ break;
+ case ADVANCED:
+ sof_bits = 6;
+ m = MC4K;
+ break;
+ case FAST_ADVANCED:
+ sof_bits = 6;
+ m = MC8K;
+ break;
+ default:
+ break;
+ }
+ page_to_be_written++;
+ block_data_left--;
+ if (block_data_left == 0) {
+ tag.tstate = NO_OP;
+ page_to_be_written = 0;
+ }
+ }
+ break;
+ case 20: {
+ //write page, write block, read page or read block command received
+ if ((rx[0] & 0xf0) == 0xc0) //read page
+ {
+ //send page data
+ page = ((rx[0] & 0x0f) * 16) + ((rx[1] & 0xf0) / 16);
+ *txlen = 32;
+ tx[0] = (tag.pages[page / 4][page % 4]) & 0xff;
+ tx[1] = (tag.pages[page / 4][page % 4] >> 8) & 0xff;
+ tx[2] = (tag.pages[page / 4][page % 4] >> 16) & 0xff;
+ tx[3] = (tag.pages[page / 4][page % 4] >> 24) & 0xff;
+ if (tag.LKP && page == 1)
+ tx[3] = 0xff;
+
+ switch (tag.mode) {
+ case STANDARD:
+ sof_bits = 1;
+ m = MC4K;
+ break;
+ case ADVANCED:
+ sof_bits = 6;
+ m = MC4K;
+ break;
+ case FAST_ADVANCED:
+ sof_bits = 6;
+ m = MC8K;
+ break;
+ default:
+ break;
+ }
+
+ if (tag.mode != STANDARD) {
+ //add crc8
+ *txlen = 40;
+ crc = CRC_PRESET;
+ for (i = 0; i < 4; i++)
+ calc_crc(&crc, tx[i], 8);
+ tx[4] = crc;
+ }
+
+ if (tag.LKP && (page == 2 || page == 3)) {
+ //if reader asks for key or password and the LKP-mark is set do not respond
+ sof_bits = 0;
+ *txlen = 0;
+ }
+ } else if ((rx[0] & 0xf0) == 0xd0) //read block
+ {
+ page = ((rx[0] & 0x0f) * 16) + ((rx[1] & 0xf0) / 16);
+ *txlen = 32 * 4;
+ //send page,...,page+3 data
+ for (i = 0; i < 4; i++) {
+ tx[0 + i * 4] = (tag.pages[page / 4][page % 4]) & 0xff;
+ tx[1 + i * 4] = (tag.pages[page / 4][page % 4] >> 8) & 0xff;
+ tx[2 + i * 4] = (tag.pages[page / 4][page % 4] >> 16) & 0xff;
+ tx[3 + i * 4] = (tag.pages[page / 4][page % 4] >> 24) & 0xff;
+ page++;
+ }
+
+ switch (tag.mode) {
+ case STANDARD:
+ sof_bits = 1;
+ m = MC4K;
+ break;
+ case ADVANCED:
+ sof_bits = 6;
+ m = MC4K;
+ break;
+ case FAST_ADVANCED:
+ sof_bits = 6;
+ m = MC8K;
+ break;
+ default:
+ break;
+ }
+
+ if (tag.mode != STANDARD) {
+ //add crc8
+ *txlen = 32 * 4 + 8;
+ crc = CRC_PRESET;
+ for (i = 0; i < 16; i++)
+ calc_crc(&crc, tx[i], 8);
+ tx[16] = crc;
+ }
+
+ if ((page - 4) % 4 != 0 || (tag.LKP && (page - 4) == 0)) {
+ sof_bits = 0;
+ *txlen = 0;
+ }
+ } else if ((rx[0] & 0xf0) == 0x80) //write page
+ {
+ page = ((rx[0] & 0x0f) * 16) + ((rx[1] & 0xf0) / 16);
+
+ switch (tag.mode) {
+ case STANDARD:
+ sof_bits = 1;
+ m = MC4K;
+ break;
+ case ADVANCED:
+ sof_bits = 6;
+ m = MC4K;
+ break;
+ case FAST_ADVANCED:
+ sof_bits = 6;
+ m = MC8K;
+ break;
+ default:
+ break;
+ }
+ if ((tag.LCON && page == 1)
+ || (tag.LKP && (page == 2 || page == 3))) {
+ //deny
+ *txlen = 0;
+ } else {
+ //allow
+ *txlen = 2;
+ tx[0] = 0x40;
+ page_to_be_written = page;
+ tag.tstate = WRITING_PAGE_DATA;
+ }
+
+ } else if ((rx[0] & 0xf0) == 0x90) //write block
+ {
+ page = ((rx[0] & 0x0f) * 6) + ((rx[1] & 0xf0) / 16);
+ switch (tag.mode) {
+ case STANDARD:
+ sof_bits = 1;
+ m = MC4K;
+ break;
+ case ADVANCED:
+ sof_bits = 6;
+ m = MC4K;
+ break;
+ case FAST_ADVANCED:
+ sof_bits = 6;
+ m = MC8K;
+ break;
+ default:
+ break;
+ }
+ if (page % 4 != 0 || page == 0) {
+ //deny
+ *txlen = 0;
+ } else {
+ //allow
+ *txlen = 2;
+ tx[0] = 0x40;
+ page_to_be_written = page;
+ block_data_left = 4;
+ tag.tstate = WRITING_BLOCK_DATA;
+ }
+ }
+ }
+ break;
+ default:
+
+ break;
+ }
+}
+
+/*
+ * to autenticate to a tag with the given key or challenge
+ */
+static int hitagS_handle_tag_auth(hitag_function htf,uint64_t key, uint64_t NrAr, byte_t* rx, const size_t rxlen, byte_t* tx,
+ size_t* txlen) {
+ byte_t rx_air[HITAG_FRAME_LEN];
+ int response_bit[200];
+ int i, j, z, k;
+ unsigned char mask = 1;
+ unsigned char uid[32];
+ byte_t uid1 = 0x00, uid2 = 0x00, uid3 = 0x00, uid4 = 0x00;
+ unsigned char crc;
+ u64 state;
+ byte_t auth_ks[4];
+ byte_t conf_pages[3];
+ memcpy(rx_air, rx, nbytes(rxlen));
+ *txlen = 0;
+
+ if (tag.pstate == READY && rxlen >= 67) {
+ //received uid
+ if(end==true) {
+ Dbprintf("authentication failed!");
+ return -1;
+ }
+ z = 0;
+ for (i = 0; i < 10; i++) {
+ for (j = 0; j < 8; j++) {
+ response_bit[z] = 0;
+ if ((rx[i] & ((mask << 7) >> j)) != 0)
+ response_bit[z] = 1;
+ z++;
+ }
+ }
+ k = 0;
+ for (i = 5; i < z; i += 2) {
+ uid[k] = response_bit[i];
+ k++;
+ if (k > 31)
+ break;
+ }
+ uid1 = (uid[0] << 7) | (uid[1] << 6) | (uid[2] << 5) | (uid[3] << 4)
+ | (uid[4] << 3) | (uid[5] << 2) | (uid[6] << 1) | uid[7];
+ uid2 = (uid[8] << 7) | (uid[9] << 6) | (uid[10] << 5) | (uid[11] << 4)
+ | (uid[12] << 3) | (uid[13] << 2) | (uid[14] << 1) | uid[15];
+ uid3 = (uid[16] << 7) | (uid[17] << 6) | (uid[18] << 5) | (uid[19] << 4)
+ | (uid[20] << 3) | (uid[21] << 2) | (uid[22] << 1) | uid[23];
+ uid4 = (uid[24] << 7) | (uid[25] << 6) | (uid[26] << 5) | (uid[27] << 4)
+ | (uid[28] << 3) | (uid[29] << 2) | (uid[30] << 1) | uid[31];
+ if (DEBUG)
+ Dbprintf("UID: %02X %02X %02X %02X", uid1, uid2, uid3, uid4);
+ tag.uid = (uid4 << 24 | uid3 << 16 | uid2 << 8 | uid1);
+
+ //select uid
+ *txlen = 45;
+ crc = CRC_PRESET;
+ calc_crc(&crc, 0x00, 5);
+ calc_crc(&crc, uid1, 8);
+ calc_crc(&crc, uid2, 8);
+ calc_crc(&crc, uid3, 8);
+ calc_crc(&crc, uid4, 8);
+ for (i = 0; i < 100; i++) {
+ response_bit[i] = 0;
+ }
+ for (i = 0; i < 5; i++) {
+ response_bit[i] = 0;
+ }
+ for (i = 5; i < 37; i++) {
+ response_bit[i] = uid[i - 5];
+ }
+ for (j = 0; j < 8; j++) {
+ response_bit[i] = 0;
+ if ((crc & ((mask << 7) >> j)) != 0)
+ response_bit[i] = 1;
+ i++;
+ }
+ k = 0;
+ for (i = 0; i < 6; i++) {
+ tx[i] = (response_bit[k] << 7) | (response_bit[k + 1] << 6)
+ | (response_bit[k + 2] << 5) | (response_bit[k + 3] << 4)
+ | (response_bit[k + 4] << 3) | (response_bit[k + 5] << 2)
+ | (response_bit[k + 6] << 1) | response_bit[k + 7];
+ k += 8;
+ }
+ tag.pstate = INIT;
+ } else if (tag.pstate == INIT && rxlen == 44) {
+ // received configuration after select command
+ z = 0;
+ for (i = 0; i < 6; i++) {
+ for (j = 0; j < 8; j++) {
+ response_bit[z] = 0;
+ if ((rx[i] & ((mask << 7) >> j)) != 0)
+ response_bit[z] = 1;
+ z++;
+ }
+ }
+ conf_pages[0] = ((response_bit[4] << 7) | (response_bit[5] << 6)
+ | (response_bit[6] << 5) | (response_bit[7] << 4)
+ | (response_bit[8] << 3) | (response_bit[9] << 2)
+ | (response_bit[10] << 1) | response_bit[11]);
+ //check wich memorysize this tag has
+ if (response_bit[10] == 0 && response_bit[11] == 0)
+ tag.max_page = 32 / 32;
+ if (response_bit[10] == 0 && response_bit[11] == 1)
+ tag.max_page = 256 / 32;
+ if (response_bit[10] == 1 && response_bit[11] == 0)
+ tag.max_page = 2048 / 32;
+ conf_pages[1] = ((response_bit[12] << 7) | (response_bit[13] << 6)
+ | (response_bit[14] << 5) | (response_bit[15] << 4)
+ | (response_bit[16] << 3) | (response_bit[17] << 2)
+ | (response_bit[18] << 1) | response_bit[19]);
+ tag.auth = response_bit[12];
+ tag.TTFC = response_bit[13];
+ //tag.TTFDR in response_bit[14] and response_bit[15]
+ //tag.TTFM in response_bit[16] and response_bit[17]
+ tag.LCON = response_bit[18];
+ tag.LKP = response_bit[19];
+ conf_pages[2] = ((response_bit[20] << 7) | (response_bit[21] << 6)
+ | (response_bit[22] << 5) | (response_bit[23] << 4)
+ | (response_bit[24] << 3) | (response_bit[25] << 2)
+ | (response_bit[26] << 1) | response_bit[27]);
+ tag.LCK7 = response_bit[20];
+ tag.LCK6 = response_bit[21];
+ tag.LCK5 = response_bit[22];
+ tag.LCK4 = response_bit[23];
+ tag.LCK3 = response_bit[24];
+ tag.LCK2 = response_bit[25];
+ tag.LCK1 = response_bit[26];
+ tag.LCK0 = response_bit[27];
+
+ if (DEBUG)
+ Dbprintf("conf0: %02X conf1: %02X conf2: %02X", conf_pages[0],
+ conf_pages[1], conf_pages[2]);
+ if (tag.auth == 1) {
+ //if the tag is in authentication mode try the key or challenge
+ *txlen = 64;
+ if(end!=true){
+ if(htf==02||htf==04){ //RHTS_KEY //WHTS_KEY
+ state = hitag2_init(rev64(key), rev32(tag.uid),
+ rev32(rnd));
+
+ for (i = 0; i < 4; i++) {
+ auth_ks[i] = hitag2_byte(&state) ^ 0xff;
+ }
+ *txlen = 64;
+ tx[0] = rnd & 0xff;
+ tx[1] = (rnd >> 8) & 0xff;
+ tx[2] = (rnd >> 16) & 0xff;
+ tx[3] = (rnd >> 24) & 0xff;
+
+ tx[4] = auth_ks[0];
+ tx[5] = auth_ks[1];
+ tx[6] = auth_ks[2];
+ tx[7] = auth_ks[3];
+ if (DEBUG)
+ Dbprintf("%02X %02X %02X %02X %02X %02X %02X %02X", tx[0],
+ tx[1], tx[2], tx[3], tx[4], tx[5], tx[6], tx[7]);
+ } else if(htf==01 || htf==03) { //RHTS_CHALLENGE //WHTS_CHALLENGE
+ for (i = 0; i < 8; i++)
+ tx[i]=((NrAr>>(56-(i*8)))&0xff);
+ }
+ end=true;
+ tag.pstate = AUTHENTICATE;
+ } else {
+ Dbprintf("authentication failed!");
+ return -1;
+ }
+ } else if (tag.auth == 0) {
+ tag.pstate = SELECTED;
+ }
+
+ } else if (tag.pstate == AUTHENTICATE && rxlen == 44) {
+ //encrypted con2,password received.
+ crc = CRC_PRESET;
+ calc_crc(&crc, 0x80, 1);
+ calc_crc(&crc, ((rx[0] & 0x0f) * 16 + ((rx[1] & 0xf0) / 16)), 8);
+ calc_crc(&crc, ((rx[1] & 0x0f) * 16 + ((rx[2] & 0xf0) / 16)), 8);
+ calc_crc(&crc, ((rx[2] & 0x0f) * 16 + ((rx[3] & 0xf0) / 16)), 8);
+ calc_crc(&crc, ((rx[3] & 0x0f) * 16 + ((rx[4] & 0xf0) / 16)), 8);
+ if (DEBUG) {
+ Dbprintf("UID:::%X", tag.uid);
+ Dbprintf("RND:::%X", rnd);
+ }
+
+ //decrypt password
+ pwdh0=0;
+ pwdl0=0;
+ pwdl1=0;
+ if(htf==02 || htf==04){ //RHTS_KEY //WHTS_KEY
+ {
+ state = hitag2_init(rev64(key), rev32(tag.uid), rev32(rnd));
+ for (i = 0; i < 5; i++)
+ hitag2_byte(&state);
+ pwdh0 = ((rx[1] & 0x0f) * 16 + ((rx[2] & 0xf0) / 16))
+ ^ hitag2_byte(&state);
+ pwdl0 = ((rx[2] & 0x0f) * 16 + ((rx[3] & 0xf0) / 16))
+ ^ hitag2_byte(&state);
+ pwdl1 = ((rx[3] & 0x0f) * 16 + ((rx[4] & 0xf0) / 16))
+ ^ hitag2_byte(&state);
+ }
+
+ if (DEBUG)
+ Dbprintf("pwdh0 %02X pwdl0 %02X pwdl1 %02X", pwdh0, pwdl0, pwdl1);
+
+
+ //Dbprintf("%X %02X", rnd, ((rx[4] & 0x0f) * 16) + ((rx[5] & 0xf0) / 16));
+ //rnd += 1;
+ }
+ tag.pstate = SELECTED; //tag is now ready for read/write commands
+ }
+ return 0;
+
+}
+
+/*
+ * Emulates a Hitag S Tag with the given data from the .hts file
+ */
+void SimulateHitagSTag(bool tag_mem_supplied, byte_t* data) {
+ int frame_count;
+ int response;
+ int overflow;
+ int i, j;
+ byte_t rx[HITAG_FRAME_LEN];
+ size_t rxlen = 0;
+//bool bQuitTraceFull = false;
+ bQuiet = false;
+ byte_t txbuf[HITAG_FRAME_LEN];
+ byte_t* tx = txbuf;
+ size_t txlen = 0;
+ BigBuf_free();
+
+// Clean up trace and prepare it for storing frames
+ set_tracing(TRUE);
+ clear_trace();
+
+ DbpString("Starting HitagS simulation");
+ LED_D_ON();
+
+ tag.pstate = READY;
+ tag.tstate = NO_OP;
+ for (i = 0; i < 16; i++)
+ for (j = 0; j < 4; j++)
+ tag.pages[i][j] = 0x0;
+ //read tag data into memory
+ if (tag_mem_supplied) {
+ DbpString("Loading hitagS memory...");
+ memcpy((byte_t*)tag.pages,data,4*64);
+ }
+ tag.uid=(uint32_t)tag.pages[0];
+ Dbprintf("Hitag S simulation started");
+ tag.key=(intptr_t)tag.pages[3];
+ tag.key<<=16;
+ tag.key+=((tag.pages[2][0])<<8)+tag.pages[2][1];
+ tag.pwdl0=tag.pages[2][3];
+ tag.pwdl1=tag.pages[2][2];
+ tag.pwdh0=tag.pages[1][0];
+ //con0
+ tag.max_page=64;
+ if((tag.pages[1][3]&0x2)==0 && (tag.pages[1][3]&0x1)==1)
+ tag.max_page=8;
+ if((tag.pages[1][3]&0x2)==0 && (tag.pages[1][3]&0x1)==0)
+ tag.max_page=0;
+ //con1
+ tag.auth=0;
+ if((tag.pages[1][2]&0x80)==1)
+ tag.auth=1;
+ tag.LCON=0;
+ if((tag.pages[1][2]&0x2)==1)
+ tag.LCON=1;
+ tag.LKP=0;
+ if((tag.pages[1][2]&0x1)==1)
+ tag.LKP=1;
+ //con2
+ //0=read write 1=read only
+ tag.LCK7=0;
+ if((tag.pages[1][1]&0x80)==1)
+ tag.LCK7=1;
+ tag.LCK6=0;
+ if((tag.pages[1][1]&0x40)==1)
+ tag.LCK6=1;
+ tag.LCK5=0;
+ if((tag.pages[1][1]&0x20)==1)
+ tag.LCK5=1;
+ tag.LCK4=0;
+ if((tag.pages[1][1]&0x10)==1)
+ tag.LCK4=1;
+ tag.LCK3=0;
+ if((tag.pages[1][1]&0x8)==1)
+ tag.LCK3=1;
+ tag.LCK2=0;
+ if((tag.pages[1][1]&0x4)==1)
+ tag.LCK2=1;
+ tag.LCK1=0;
+ if((tag.pages[1][1]&0x2)==1)
+ tag.LCK1=1;
+ tag.LCK0=0;
+ if((tag.pages[1][1]&0x1)==1)
+ tag.LCK0=1;
+
+// 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);
+ RELAY_OFF();
+
+// Configure output pin that is connected to the FPGA (for modulating)
+ AT91C_BASE_PIOA->PIO_OER = GPIO_SSC_DOUT;
+ AT91C_BASE_PIOA->PIO_PER = GPIO_SSC_DOUT;
+
+// Disable modulation at default, which means release resistance
+ LOW(GPIO_SSC_DOUT);
+
+// Enable Peripheral Clock for TIMER_CLOCK0, used to measure exact timing before answering
+ AT91C_BASE_PMC->PMC_PCER = (1 << AT91C_ID_TC0);
+
+// Enable Peripheral Clock for TIMER_CLOCK1, used to capture edges of the reader frames
+ AT91C_BASE_PMC->PMC_PCER = (1 << AT91C_ID_TC1);
+ AT91C_BASE_PIOA->PIO_BSR = GPIO_SSC_FRAME;
+
+// 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,
+// external trigger rising edge, load RA on rising edge of TIOA.
+ 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;
+ response = 0;
+ overflow = 0;
+
+// Enable and reset counter
+ AT91C_BASE_TC1->TC_CCR = AT91C_TC_CLKEN | AT91C_TC_SWTRG;
+
+ 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) {
+ // Retrieve the new timing values
+ int ra = (AT91C_BASE_TC1->TC_RA / T0) + overflow;
+ overflow = 0;
+
+ // Reset timer every frame, we have to capture the last edge for timing
+ AT91C_BASE_TC0->TC_CCR = AT91C_TC_CLKEN | AT91C_TC_SWTRG;
+
+ LED_B_ON();
+
+ // Capture reader frame
+ 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) {
+ // '1' bit
+ rx[rxlen / 8] |= 1 << (7 - (rxlen % 8));
+ rxlen++;
+ } else if (ra >= HITAG_T_0_MIN) {
+ // '0' bit
+ rx[rxlen / 8] |= 0 << (7 - (rxlen % 8));
+ rxlen++;
+ } else {
+ // Ignore wierd value, is to small to mean anything
+ }
+ }
+ }
+
+ // Check if frame was captured
+ if (rxlen > 0) {
+ frame_count++;
+ if (!bQuiet) {
+ if (!LogTraceHitag(rx, rxlen, response, 0, true)) {
+ DbpString("Trace full");
+ clear_trace();
+ }
+ }
+
+ // Disable timer 1 with external trigger to avoid triggers during our own modulation
+ AT91C_BASE_TC1->TC_CCR = AT91C_TC_CLKDIS;
+
+ // Process the incoming frame (rx) and prepare the outgoing frame (tx)
+ hitagS_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))
+ ;
+
+ // Send and store the tag answer (if there is any)
+ if (txlen > 0) {
+ // Transmit the tag frame
+ hitag_send_frame(tx, txlen);
+ // Store the frame in the trace
+ if (!bQuiet) {
+ if (!LogTraceHitag(tx, txlen, 0, 0, false)) {
+ DbpString("Trace full");
+ clear_trace();
+ }
+ }
+ }
+
+ // Reset the received frame and response timing info
+ memset(rx, 0x00, sizeof(rx));
+ response = 0;
+
+ // Enable and reset external trigger in timer for capturing future frames
+ AT91C_BASE_TC1->TC_CCR = AT91C_TC_CLKEN | AT91C_TC_SWTRG;
+ LED_B_OFF();
+ }
+ // Reset the frame length
+ rxlen = 0;
+ // Save the timer overflow, will be 0 when frame was received
+ overflow += (AT91C_BASE_TC1->TC_CV / T0);
+ // Reset the timer to restart while-loop that receives frames
+ AT91C_BASE_TC1->TC_CCR = AT91C_TC_SWTRG;
+ }
+ LED_B_OFF();
+ LED_D_OFF();
+ AT91C_BASE_TC1->TC_CCR = AT91C_TC_CLKDIS;
+ AT91C_BASE_TC0->TC_CCR = AT91C_TC_CLKDIS;
+ FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
+}
+
+/*
+ * Authenticates to the Tag with the given key or challenge.
+ * If the key was given the password will be decrypted.
+ * Reads every page of a hitag S transpoder.
+ */
+void ReadHitagS(hitag_function htf, hitag_data* htd) {
+ int i, j, z, k;
+ int frame_count;
+ int response_bit[200];
+ 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;
+ int lastbit;
+ bool bSkip;
+ int reset_sof;
+ int tag_sof;
+ int t_wait = HITAG_T_WAIT_MAX;
+ bool bStop;
+ bool bQuitTraceFull = false;
+ int sendNum = 0;
+ unsigned char mask = 1;
+ unsigned char crc;
+ unsigned char pageData[32];
+ page_to_be_written = 0;
+
+ //read given key/challenge
+ byte_t NrAr_[8];
+ uint64_t key=0;
+ uint64_t NrAr=0;
+ byte_t key_[6];
+ switch(htf) {
+ case 01: { //RHTS_CHALLENGE
+ DbpString("Authenticating using nr,ar pair:");
+ memcpy(NrAr_,htd->auth.NrAr,8);
+ Dbhexdump(8,NrAr_,false);
+ NrAr=NrAr_[7] | ((uint64_t)NrAr_[6]) << 8 | ((uint64_t)NrAr_[5]) << 16 | ((uint64_t)NrAr_[4]) << 24 | ((uint64_t)NrAr_[3]) << 32 |
+ ((uint64_t)NrAr_[2]) << 40| ((uint64_t)NrAr_[1]) << 48 | ((uint64_t)NrAr_[0]) << 56;
+ } break;
+ case 02: { //RHTS_KEY
+ DbpString("Authenticating using key:");
+ memcpy(key_,htd->crypto.key,6);
+ Dbhexdump(6,key_,false);
+ key=key_[5] | ((uint64_t)key_[4]) << 8 | ((uint64_t)key_[3]) << 16 | ((uint64_t)key_[2]) << 24 | ((uint64_t)key_[1]) << 32 | ((uint64_t)key_[0]) << 40;
+ } break;
+ default: {
+ Dbprintf("Error , unknown function: %d",htf);
+ return;
+ } break;
+ }
+
+
+
+ FpgaDownloadAndGo(FPGA_BITSTREAM_LF);
+// Reset the return status
+ bSuccessful = false;
+
+// Clean up trace and prepare it for storing frames
+ set_tracing(TRUE);
+ clear_trace();
+
+ bQuiet = false;
+ bQuitTraceFull = true;
+
+ LED_D_ON();
+
+// Configure output and enable pin that is connected to the FPGA (for modulating)
+ AT91C_BASE_PIOA->PIO_OER = GPIO_SSC_DOUT;
+ AT91C_BASE_PIOA->PIO_PER = GPIO_SSC_DOUT;
+
+// Set fpga in edge detect with reader field, we can modulate as reader now
+ FpgaWriteConfWord(
+ FPGA_MAJOR_MODE_LF_EDGE_DETECT | FPGA_LF_EDGE_DETECT_READER_FIELD);
+
+// 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);
+
+// Enable Peripheral Clock for TIMER_CLOCK1, used to capture edges of the tag frames
+ AT91C_BASE_PMC->PMC_PCER = (1 << AT91C_ID_TC1);
+ AT91C_BASE_PIOA->PIO_BSR = GPIO_SSC_FRAME;
+
+// Disable timer during configuration
+ AT91C_BASE_TC1->TC_CCR = AT91C_TC_CLKDIS;
+
+// Capture mode, defaul timer source = MCK/2 (TIMER_CLOCK1), TIOA is external trigger,
+// external trigger rising edge, load RA on falling edge of TIOA.
+ AT91C_BASE_TC1->TC_CMR = AT91C_TC_CLKS_TIMER_DIV1_CLOCK
+
+ | AT91C_TC_ETRGEDG_FALLING | AT91C_TC_ABETRG | AT91C_TC_LDRA_FALLING;
+
+// Enable and reset counters
+ AT91C_BASE_TC0->TC_CCR = AT91C_TC_CLKEN | AT91C_TC_SWTRG;
+ AT91C_BASE_TC1->TC_CCR = AT91C_TC_CLKEN | AT91C_TC_SWTRG;
+
+// Reset the received frame, frame count and timing info
+ frame_count = 0;
+ response = 0;
+ lastbit = 1;
+ bStop = false;
+
+ reset_sof = 1;
+ t_wait = 200;
+
+ while (!bStop && !BUTTON_PRESS()) {
+ // Watchdog hit
+ WDT_HIT();
+
+ // Check if frame was captured and store it
+ if (rxlen > 0) {
+ frame_count++;
+ if (!bQuiet) {
+ if (!LogTraceHitag(rx, rxlen, response, 0, false)) {
+ DbpString("Trace full");
+ if (bQuitTraceFull) {
+ break;
+ } else {
+ bQuiet = true;
+ }
+ }
+ }
+ }
+
+ // By default reset the transmission buffer
+ tx = txbuf;
+ txlen = 0;
+
+ if (rxlen == 0) {
+ //start authentication
+ txlen = 5;
+ memcpy(tx, "\xc0", nbytes(txlen));
+ tag.pstate = READY;
+ tag.tstate = NO_OP;
+ } else if (tag.pstate != SELECTED) {
+ if (hitagS_handle_tag_auth(htf, key,NrAr,rx, rxlen, tx, &txlen) == -1)
+ bStop = !false;
+ }
+ if (tag.pstate == SELECTED && tag.tstate == NO_OP && rxlen > 0) {
+ //send read request
+ tag.tstate = READING_PAGE;
+ txlen = 20;
+ crc = CRC_PRESET;
+ tx[0] = 0xc0 + (sendNum / 16);
+ calc_crc(&crc, tx[0], 8);
+ calc_crc(&crc, 0x00 + ((sendNum % 16) * 16), 4);
+ tx[1] = 0x00 + ((sendNum % 16) * 16) + (crc / 16);
+ tx[2] = 0x00 + (crc % 16) * 16;
+ } else if (tag.pstate == SELECTED && tag.tstate == READING_PAGE
+ && rxlen > 0) {
+ //save received data
+ z = 0;
+ for (i = 0; i < 5; i++) {
+ for (j = 0; j < 8; j++) {
+ response_bit[z] = 0;
+ if ((rx[i] & ((mask << 7) >> j)) != 0)
+ response_bit[z] = 1;
+ z++;
+ }
+ }
+ k = 0;
+ for (i = 4; i < 36; i++) {
+ pageData[k] = response_bit[i];
+ k++;
+ }
+ for (i = 0; i < 4; i++)
+ tag.pages[sendNum / 4][sendNum % 4] = 0x0;
+ for (i = 0; i < 4; i++) {
+ tag.pages[sendNum / 4][sendNum % 4] += ((pageData[i * 8] << 7)
+ | (pageData[1 + (i * 8)] << 6)
+ | (pageData[2 + (i * 8)] << 5)
+ | (pageData[3 + (i * 8)] << 4)
+ | (pageData[4 + (i * 8)] << 3)
+ | (pageData[5 + (i * 8)] << 2)
+ | (pageData[6 + (i * 8)] << 1) | pageData[7 + (i * 8)])
+ << (i * 8);
+ }
+ if (tag.auth && tag.LKP && sendNum == 1) {
+ Dbprintf("Page[%2d]: %02X %02X %02X %02X", sendNum, pwdh0,
+ (tag.pages[sendNum / 4][sendNum % 4] >> 16) & 0xff,
+ (tag.pages[sendNum / 4][sendNum % 4] >> 8) & 0xff,
+ tag.pages[sendNum / 4][sendNum % 4] & 0xff);
+ } else {
+ Dbprintf("Page[%2d]: %02X %02X %02X %02X", sendNum,
+ (tag.pages[sendNum / 4][sendNum % 4] >> 24) & 0xff,
+ (tag.pages[sendNum / 4][sendNum % 4] >> 16) & 0xff,
+ (tag.pages[sendNum / 4][sendNum % 4] >> 8) & 0xff,
+ tag.pages[sendNum / 4][sendNum % 4] & 0xff);
+ }
+
+ sendNum++;
+ //display key and password if possible
+ if (sendNum == 2 && tag.auth == 1 && tag.LKP) {
+ if (htf == 02) { //RHTS_KEY
+ Dbprintf("Page[ 2]: %02X %02X %02X %02X",
+ (byte_t)(key >> 8) & 0xff,
+ (byte_t) key & 0xff, pwdl1, pwdl0);
+ Dbprintf("Page[ 3]: %02X %02X %02X %02X",
+ (byte_t)(key >> 40) & 0xff,
+ (byte_t)(key >> 32) & 0xff,
+ (byte_t)(key >> 24) & 0xff,
+ (byte_t)(key >> 16) & 0xff);
+ } else {
+ //if the authentication is done with a challenge the key and password are unknown
+ Dbprintf("Page[ 2]: __ __ __ __");
+ Dbprintf("Page[ 3]: __ __ __ __");
+ }
+ }
+
+ txlen = 20;
+ crc = CRC_PRESET;
+ tx[0] = 0xc0 + (sendNum / 16);
+ calc_crc(&crc, tx[0], 8);
+ calc_crc(&crc, 0x00 + ((sendNum % 16) * 16), 4);
+ tx[1] = 0x00 + ((sendNum % 16) * 16) + (crc / 16);
+ tx[2] = 0x00 + (crc % 16) * 16;
+ if (sendNum >= tag.max_page) {
+ bStop = !false;
+ }
+ }
+
+ // Send and store the reader command
+ // Disable timer 1 with external trigger to avoid triggers during our own modulation
+ AT91C_BASE_TC1->TC_CCR = AT91C_TC_CLKDIS;
+
+ // Wait for HITAG_T_WAIT_2 carrier periods after the last tag bit before transmitting,
+ // Since the clock counts since the last falling edge, a 'one' means that the
+ // 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)))
+ ;
+
+ // Transmit the reader frame
+ 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 (!bQuiet) {
+ // Store the frame in the trace
+ if (!LogTraceHitag(tx, txlen, HITAG_T_WAIT_2, 0, true)) {
+ if (bQuitTraceFull) {
+ DbpString("Trace full");
+ break;
+ } else {
+ bQuiet = true;
+ }
+ }
+ }
+ }
+
+ // Reset values for receiving frames
+ memset(rx, 0x00, sizeof(rx));
+ rxlen = 0;
+ lastbit = 1;
+ bSkip = true;
+ tag_sof = reset_sof;
+ response = 0;
+
+ // 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) {
+ // Retrieve the new timing values
+ int ra = (AT91C_BASE_TC1->TC_RA / T0);
+
+ // Reset timer every frame, we have to capture the last edge for timing
+ AT91C_BASE_TC0->TC_CCR = AT91C_TC_SWTRG;
+
+ LED_B_ON();
+
+ // Capture tag frame (manchester decoding using only falling edges)
+ 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) {
+ // 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) {
+ // Manchester coding example |_-|...|_-|-_| (0...01)
+ rx[rxlen / 8] |= 0 << (7 - (rxlen % 8));
+ rxlen++;
+ // We have to skip this half period at start and add the 'one' the second time
+ if (!bSkip) {
+ rx[rxlen / 8] |= 1 << (7 - (rxlen % 8));
+ rxlen++;
+ }
+ lastbit = !lastbit;
+ bSkip = !bSkip;
+ } 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
+ tag_sof--;
+ } else {
+ // bit is same as last bit
+ rx[rxlen / 8] |= lastbit << (7 - (rxlen % 8));
+ rxlen++;
+ }
+ } else {
+ // Ignore wierd value, is to small to mean anything
+ }
+ }
+
+ // 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;
+ }
+ }
+ }
+ end=false;
+ LED_B_OFF();
+ LED_D_OFF();
+ AT91C_BASE_TC1->TC_CCR = AT91C_TC_CLKDIS;
+ AT91C_BASE_TC0->TC_CCR = AT91C_TC_CLKDIS;
+ FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
+ cmd_send(CMD_ACK, bSuccessful, 0, 0, 0, 0);
+}
+
+/*
+ * Authenticates to the Tag with the given Key or Challenge.
+ * Writes the given 32Bit data into page_
+ */
+void WritePageHitagS(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;
+ int lastbit;
+ bool bSkip;
+ int reset_sof;
+ int tag_sof;
+ int t_wait = HITAG_T_WAIT_MAX;
+ bool bStop;
+ bool bQuitTraceFull = false;
+ int page = page_;
+ unsigned char crc;
+ byte_t data[4]= {0,0,0,0};
+
+ //read given key/challenge, the page and the data
+ byte_t NrAr_[8];
+ uint64_t key=0;
+ uint64_t NrAr=0;
+ byte_t key_[6];
+ switch(htf) {
+ case 03: { //WHTS_CHALLENGE
+ memcpy(data,htd->auth.data,4);
+ DbpString("Authenticating using nr,ar pair:");
+ memcpy(NrAr_,htd->auth.NrAr,8);
+ Dbhexdump(8,NrAr_,false);
+ NrAr=NrAr_[7] | ((uint64_t)NrAr_[6]) << 8 | ((uint64_t)NrAr_[5]) << 16 | ((uint64_t)NrAr_[4]) << 24 | ((uint64_t)NrAr_[3]) << 32 |
+ ((uint64_t)NrAr_[2]) << 40| ((uint64_t)NrAr_[1]) << 48 | ((uint64_t)NrAr_[0]) << 56;
+ } break;
+ case 04: { //WHTS_KEY
+ memcpy(data,htd->crypto.data,4);
+ DbpString("Authenticating using key:");
+ memcpy(key_,htd->crypto.key,6);
+ Dbhexdump(6,key_,false);
+ key=key_[5] | ((uint64_t)key_[4]) << 8 | ((uint64_t)key_[3]) << 16 | ((uint64_t)key_[2]) << 24 | ((uint64_t)key_[1]) << 32 | ((uint64_t)key_[0]) << 40;
+ } break;
+ default: {
+ Dbprintf("Error , unknown function: %d",htf);
+ return;
+ } break;
+ }
+
+ Dbprintf("Page: %d",page_);
+ Dbprintf("DATA: %02X %02X %02X %02X", data[0], data[1], data[2], data[3]);
+ FpgaDownloadAndGo(FPGA_BITSTREAM_LF);
+// Reset the return status
+ bSuccessful = false;
+
+ tag.pstate = READY;
+ tag.tstate = NO_OP;
+
+// Clean up trace and prepare it for storing frames
+ set_tracing(TRUE);
+ clear_trace();
+
+ bQuiet = false;
+ bQuitTraceFull = true;
+
+ LED_D_ON();
+
+// Configure output and enable pin that is connected to the FPGA (for modulating)
+ AT91C_BASE_PIOA->PIO_OER = GPIO_SSC_DOUT;
+ AT91C_BASE_PIOA->PIO_PER = GPIO_SSC_DOUT;
+
+// Set fpga in edge detect with reader field, we can modulate as reader now
+ FpgaWriteConfWord(
+ FPGA_MAJOR_MODE_LF_EDGE_DETECT | FPGA_LF_EDGE_DETECT_READER_FIELD);
+
+// 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);
+
+// Enable Peripheral Clock for TIMER_CLOCK1, used to capture edges of the tag frames
+ AT91C_BASE_PMC->PMC_PCER = (1 << AT91C_ID_TC1);
+ AT91C_BASE_PIOA->PIO_BSR = GPIO_SSC_FRAME;
+
+// Disable timer during configuration
+ AT91C_BASE_TC1->TC_CCR = AT91C_TC_CLKDIS;
+
+// Capture mode, defaul timer source = MCK/2 (TIMER_CLOCK1), TIOA is external trigger,
+// external trigger rising edge, load RA on falling edge of TIOA.
+ AT91C_BASE_TC1->TC_CMR = AT91C_TC_CLKS_TIMER_DIV1_CLOCK
+ | AT91C_TC_ETRGEDG_FALLING | AT91C_TC_ABETRG
+ | AT91C_TC_LDRA_FALLING;
+
+// Enable and reset counters
+ AT91C_BASE_TC0->TC_CCR = AT91C_TC_CLKEN | AT91C_TC_SWTRG;
+ AT91C_BASE_TC1->TC_CCR = AT91C_TC_CLKEN | AT91C_TC_SWTRG;
+
+// Reset the received frame, frame count and timing info
+ frame_count = 0;
+ response = 0;
+ lastbit = 1;
+ bStop = false;
+
+ reset_sof = 1;
+ t_wait = 200;
+
+ while (!bStop && !BUTTON_PRESS()) {
+ // Watchdog hit
+ WDT_HIT();
+
+ // Check if frame was captured and store it
+ if (rxlen > 0) {
+ frame_count++;
+ if (!bQuiet) {
+ if (!LogTraceHitag(rx, rxlen, response, 0, false)) {
+ DbpString("Trace full");
+ if (bQuitTraceFull) {
+ break;
+ } else {
+ bQuiet = true;
+ }
+ }
+ }
+ }
+
+ //check for valid input
+ if (page == 0) {
+ Dbprintf(
+ "usage: lf hitag writer [03 | 04] [CHALLENGE | KEY] [page] [byte0] [byte1] [byte2] [byte3]");
+ bStop = !false;
+ }
+
+ // By default reset the transmission buffer
+ tx = txbuf;
+ txlen = 0;
+
+ if (rxlen == 0 && tag.tstate == WRITING_PAGE_ACK) {
+ //no write access on this page
+ Dbprintf("no write access on page %d", page_);
+ bStop = !false;
+ } else if (rxlen == 0 && tag.tstate != WRITING_PAGE_DATA) {
+ //start the authetication
+ txlen = 5;
+ memcpy(tx, "\xc0", nbytes(txlen));
+ tag.pstate = READY;
+ tag.tstate = NO_OP;
+ } else if (tag.pstate != SELECTED) {
+ //try to authenticate with the given key or challenge
+ if (hitagS_handle_tag_auth(htf,key,NrAr,rx, rxlen, tx, &txlen) == -1)
+ bStop = !false;
+ }
+ if (tag.pstate == SELECTED && tag.tstate == NO_OP && rxlen > 0) {
+ //check if the given page exists
+ if (page > tag.max_page) {
+ Dbprintf("page number too big");
+ bStop = !false;
+ }
+ //ask Tag for write permission
+ tag.tstate = WRITING_PAGE_ACK;
+ txlen = 20;
+ crc = CRC_PRESET;
+ tx[0] = 0x90 + (page / 16);
+ calc_crc(&crc, tx[0], 8);
+ calc_crc(&crc, 0x00 + ((page % 16) * 16), 4);
+ tx[1] = 0x00 + ((page % 16) * 16) + (crc / 16);
+ tx[2] = 0x00 + (crc % 16) * 16;
+ } else if (tag.pstate == SELECTED && tag.tstate == WRITING_PAGE_ACK
+ && rxlen == 6 && rx[0] == 0xf4) {
+ //ACK recieved to write the page. send data
+ tag.tstate = WRITING_PAGE_DATA;
+ txlen = 40;
+ crc = CRC_PRESET;
+ calc_crc(&crc, data[3], 8);
+ calc_crc(&crc, data[2], 8);
+ calc_crc(&crc, data[1], 8);
+ calc_crc(&crc, data[0], 8);
+ tx[0] = data[3];
+ tx[1] = data[2];
+ tx[2] = data[1];
+ tx[3] = data[0];
+ tx[4] = crc;
+ } else if (tag.pstate == SELECTED && tag.tstate == WRITING_PAGE_DATA
+ && rxlen == 6 && rx[0] == 0xf4) {
+ //received ACK
+ Dbprintf("Successful!");
+ bStop = !false;
+ }
+
+ // Send and store the reader command
+ // Disable timer 1 with external trigger to avoid triggers during our own modulation
+ AT91C_BASE_TC1->TC_CCR = AT91C_TC_CLKDIS;
+
+ // Wait for HITAG_T_WAIT_2 carrier periods after the last tag bit before transmitting,
+ // Since the clock counts since the last falling edge, a 'one' means that the
+ // 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)))
+ ;
+
+ // Transmit the reader frame
+ 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 (!bQuiet) {
+ // Store the frame in the trace
+ if (!LogTraceHitag(tx, txlen, HITAG_T_WAIT_2, 0, true)) {
+ if (bQuitTraceFull) {
+ DbpString("Trace full");
+ break;
+ } else {
+ bQuiet = true;
+ }
+ }
+ }
+ }
+
+ // Reset values for receiving frames
+ memset(rx, 0x00, sizeof(rx));
+ rxlen = 0;
+ lastbit = 1;
+ bSkip = true;
+ tag_sof = reset_sof;
+ response = 0;
+
+ // 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) {
+ // Retrieve the new timing values
+ int ra = (AT91C_BASE_TC1->TC_RA / T0);
+
+ // Reset timer every frame, we have to capture the last edge for timing
+ AT91C_BASE_TC0->TC_CCR = AT91C_TC_SWTRG;
+
+ LED_B_ON();
+
+ // Capture tag frame (manchester decoding using only falling edges)
+ 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) {
+ // 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) {
+ // Manchester coding example |_-|...|_-|-_| (0...01)
+ rx[rxlen / 8] |= 0 << (7 - (rxlen % 8));
+ rxlen++;
+ // We have to skip this half period at start and add the 'one' the second time
+ if (!bSkip) {
+ rx[rxlen / 8] |= 1 << (7 - (rxlen % 8));
+ rxlen++;
+ }
+ lastbit = !lastbit;
+ bSkip = !bSkip;
+ } 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
+ tag_sof--;
+ } else {
+ // bit is same as last bit
+ rx[rxlen / 8] |= lastbit << (7 - (rxlen % 8));
+ rxlen++;
+ }
+ } else {
+ // Ignore wierd value, is to small to mean anything
+ }
+ }
+
+ // 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;
+ }
+ }
+ }
+ end=false;
+ LED_B_OFF();
+ LED_D_OFF();
+ AT91C_BASE_TC1->TC_CCR = AT91C_TC_CLKDIS;
+ AT91C_BASE_TC0->TC_CCR = AT91C_TC_CLKDIS;
+ FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
+ cmd_send(CMD_ACK, bSuccessful, 0, 0, 0, 0);
+}
+
+/*
+ * Tries to authenticate to a Hitag S Transponder with the given challenges from a .cc file.
+ * Displays all Challenges that failed.
+ * When collecting Challenges to break the key it is possible that some data
+ * is not received correctly due to Antenna problems. This function
+ * detects these challenges.
+ */
+void check_challenges(bool file_given, byte_t* data) {
+ int i, j, z, k;
+ byte_t uid_byte[4];
+ int frame_count;
+ int response;
+ byte_t rx[HITAG_FRAME_LEN];
+ byte_t unlocker[60][8];
+ int u1 = 0;
+ size_t rxlen = 0;
+ byte_t txbuf[HITAG_FRAME_LEN];
+ byte_t* tx = txbuf;
+ size_t txlen = 0;
+ int lastbit;
+ bool bSkip;
+ int reset_sof;
+ int tag_sof;
+ int t_wait = HITAG_T_WAIT_MAX;
+ int STATE = 0;
+ bool bStop;
+ bool bQuitTraceFull = false;
+ int response_bit[200];
+ unsigned char mask = 1;
+ unsigned char uid[32];
+ unsigned char crc;
+
+ FpgaDownloadAndGo(FPGA_BITSTREAM_LF);
+// Reset the return status
+ bSuccessful = false;
+
+// Clean up trace and prepare it for storing frames
+ set_tracing(TRUE);
+ clear_trace();
+
+ bQuiet = false;
+ bQuitTraceFull = true;
+
+ LED_D_ON();
+
+// Configure output and enable pin that is connected to the FPGA (for modulating)
+ AT91C_BASE_PIOA->PIO_OER = GPIO_SSC_DOUT;
+ AT91C_BASE_PIOA->PIO_PER = GPIO_SSC_DOUT;
+
+// Set fpga in edge detect with reader field, we can modulate as reader now
+ FpgaWriteConfWord(
+ FPGA_MAJOR_MODE_LF_EDGE_DETECT | FPGA_LF_EDGE_DETECT_READER_FIELD);
+
+// 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);
+
+// Enable Peripheral Clock for TIMER_CLOCK1, used to capture edges of the tag frames
+ AT91C_BASE_PMC->PMC_PCER = (1 << AT91C_ID_TC1);
+ AT91C_BASE_PIOA->PIO_BSR = GPIO_SSC_FRAME;
+
+// Disable timer during configuration
+ AT91C_BASE_TC1->TC_CCR = AT91C_TC_CLKDIS;
+
+// Capture mode, defaul timer source = MCK/2 (TIMER_CLOCK1), TIOA is external trigger,
+// external trigger rising edge, load RA on falling edge of TIOA.
+ AT91C_BASE_TC1->TC_CMR = AT91C_TC_CLKS_TIMER_DIV1_CLOCK
+
+ | AT91C_TC_ETRGEDG_FALLING | AT91C_TC_ABETRG | AT91C_TC_LDRA_FALLING;
+
+// Enable and reset counters
+ AT91C_BASE_TC0->TC_CCR = AT91C_TC_CLKEN | AT91C_TC_SWTRG;
+ AT91C_BASE_TC1->TC_CCR = AT91C_TC_CLKEN | AT91C_TC_SWTRG;
+
+// Reset the received frame, frame count and timing info
+ frame_count = 0;
+ response = 0;
+ lastbit = 1;
+ bStop = false;
+
+ reset_sof = 1;
+ t_wait = 200;
+
+ if (file_given) {
+ DbpString("Loading challenges...");
+ memcpy((byte_t*)unlocker,data,60*8);
+ }
+
+ while (file_given && !bStop && !BUTTON_PRESS()) {
+ // Watchdog hit
+ WDT_HIT();
+
+ // Check if frame was captured and store it
+ if (rxlen > 0) {
+ frame_count++;
+ if (!bQuiet) {
+ if (!LogTraceHitag(rx, rxlen, response, 0, false)) {
+ DbpString("Trace full");
+ if (bQuitTraceFull) {
+ break;
+ } else {
+ bQuiet = true;
+ }
+ }
+ }
+ }
+
+ tx = txbuf;
+ txlen = 0;
+ if (rxlen == 0) {
+ if (STATE == 2)
+ // challenge failed
+ Dbprintf("Challenge failed: %02X %02X %02X %02X %02X %02X %02X %02X",
+ unlocker[u1 - 1][0], unlocker[u1 - 1][1],
+ unlocker[u1 - 1][2], unlocker[u1 - 1][3],
+ unlocker[u1 - 1][4], unlocker[u1 - 1][5],
+ unlocker[u1 - 1][6], unlocker[u1 - 1][7]);
+ STATE = 0;
+ txlen = 5;
+ //start new authentication
+ memcpy(tx, "\xc0", nbytes(txlen));
+ } else if (rxlen >= 67 && STATE == 0) {
+ //received uid
+ z = 0;
+ for (i = 0; i < 10; i++) {
+ for (j = 0; j < 8; j++) {
+ response_bit[z] = 0;
+ if ((rx[i] & ((mask << 7) >> j)) != 0)
+ response_bit[z] = 1;
+ z++;
+ }
+ }
+ k = 0;
+ for (i = 5; i < z; i += 2) {
+ uid[k] = response_bit[i];
+ k++;
+ if (k > 31)
+ break;
+ }
+ uid_byte[0] = (uid[0] << 7) | (uid[1] << 6) | (uid[2] << 5)
+ | (uid[3] << 4) | (uid[4] << 3) | (uid[5] << 2)
+ | (uid[6] << 1) | uid[7];
+ uid_byte[1] = (uid[8] << 7) | (uid[9] << 6) | (uid[10] << 5)
+ | (uid[11] << 4) | (uid[12] << 3) | (uid[13] << 2)
+ | (uid[14] << 1) | uid[15];
+ uid_byte[2] = (uid[16] << 7) | (uid[17] << 6) | (uid[18] << 5)
+ | (uid[19] << 4) | (uid[20] << 3) | (uid[21] << 2)
+ | (uid[22] << 1) | uid[23];
+ uid_byte[3] = (uid[24] << 7) | (uid[25] << 6) | (uid[26] << 5)
+ | (uid[27] << 4) | (uid[28] << 3) | (uid[29] << 2)
+ | (uid[30] << 1) | uid[31];
+ //Dbhexdump(10, rx, rxlen);
+ STATE = 1;
+ txlen = 45;
+ crc = CRC_PRESET;
+ calc_crc(&crc, 0x00, 5);
+ calc_crc(&crc, uid_byte[0], 8);
+ calc_crc(&crc, uid_byte[1], 8);
+ calc_crc(&crc, uid_byte[2], 8);
+ calc_crc(&crc, uid_byte[3], 8);
+ for (i = 0; i < 100; i++) {
+ response_bit[i] = 0;
+ }
+ for (i = 0; i < 5; i++) {
+ response_bit[i] = 0;
+ }
+ for (i = 5; i < 37; i++) {
+ response_bit[i] = uid[i - 5];
+ }
+ for (j = 0; j < 8; j++) {
+ response_bit[i] = 0;
+ if ((crc & ((mask << 7) >> j)) != 0)
+ response_bit[i] = 1;
+ i++;
+ }
+ k = 0;
+ for (i = 0; i < 6; i++) {
+ tx[i] = (response_bit[k] << 7) | (response_bit[k + 1] << 6)
+ | (response_bit[k + 2] << 5)
+ | (response_bit[k + 3] << 4)
+ | (response_bit[k + 4] << 3)
+ | (response_bit[k + 5] << 2)
+ | (response_bit[k + 6] << 1) | response_bit[k + 7];
+ k += 8;
+ }
+
+ } else if (STATE == 1 && rxlen == 44) {
+ //received configuration
+ STATE = 2;
+ z = 0;
+ for (i = 0; i < 6; i++) {
+ for (j = 0; j < 8; j++) {
+ response_bit[z] = 0;
+ if ((rx[i] & ((mask << 7) >> j)) != 0)
+ response_bit[z] = 1;
+ z++;
+ }
+ }
+ txlen = 64;
+
+ if (u1 >= (sizeof(unlocker) / sizeof(unlocker[0])))
+ bStop = !false;
+ for (i = 0; i < 8; i++)
+ tx[i] = unlocker[u1][i];
+ u1++;
+
+ } else if (STATE == 2 && rxlen >= 44) {
+ STATE = 0;
+ }
+
+ // Send and store the reader command
+ // Disable timer 1 with external trigger to avoid triggers during our own modulation
+ AT91C_BASE_TC1->TC_CCR = AT91C_TC_CLKDIS;
+
+ // Wait for HITAG_T_WAIT_2 carrier periods after the last tag bit before transmitting,
+ // Since the clock counts since the last falling edge, a 'one' means that the
+ // 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)))
+ ;
+
+ // Transmit the reader frame
+ 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 (!bQuiet) {
+ // Store the frame in the trace
+ if (!LogTraceHitag(tx, txlen, HITAG_T_WAIT_2, 0, true)) {
+ if (bQuitTraceFull) {
+ DbpString("Trace full");
+ break;
+ } else {
+ bQuiet = true;
+ }
+ }
+ }
+ }
+
+ // Reset values for receiving frames
+ memset(rx, 0x00, sizeof(rx));
+ rxlen = 0;
+ lastbit = 1;
+ bSkip = true;
+ tag_sof = reset_sof;
+ response = 0;
+
+ // 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) {
+ // Retrieve the new timing values
+ int ra = (AT91C_BASE_TC1->TC_RA / T0);
+
+ // Reset timer every frame, we have to capture the last edge for timing
+ AT91C_BASE_TC0->TC_CCR = AT91C_TC_SWTRG;
+
+ LED_B_ON();
+
+ // Capture tag frame (manchester decoding using only falling edges)
+ 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) {
+ // 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) {
+ // Manchester coding example |_-|...|_-|-_| (0...01)
+ rx[rxlen / 8] |= 0 << (7 - (rxlen % 8));
+ rxlen++;
+ // We have to skip this half period at start and add the 'one' the second time
+ if (!bSkip) {
+ rx[rxlen / 8] |= 1 << (7 - (rxlen % 8));
+ rxlen++;
+ }
+ lastbit = !lastbit;
+ bSkip = !bSkip;
+ } 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
+ tag_sof--;
+ } else {
+ // bit is same as last bit
+ rx[rxlen / 8] |= lastbit << (7 - (rxlen % 8));
+ rxlen++;
+ }
+ } else {
+ // Ignore wierd value, is to small to mean anything
+ }
+ }
+
+ // 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;
+ }
+ }
+ }
+ LED_B_OFF();
+ LED_D_OFF();
+ AT91C_BASE_TC1->TC_CCR = AT91C_TC_CLKDIS;
+ AT91C_BASE_TC0->TC_CCR = AT91C_TC_CLKDIS;
+ FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
+ cmd_send(CMD_ACK, bSuccessful, 0, 0, 0, 0);
+}
+
+
+
#include "util.h"
#include "string.h"
#include "cmd.h"
-
#include "iso14443crc.h"
#include "iso14443a.h"
#include "crapto1.h"
#include "mifareutil.h"
#include "BigBuf.h"
+#include "protocols.h"
+
static uint32_t iso14a_timeout;
int rsamples = 0;
uint8_t trigger = 0;
set_tracing(FALSE);
}
+typedef struct {
+ uint32_t cuid;
+ uint8_t sector;
+ uint8_t keytype;
+ uint32_t nonce;
+ uint32_t ar;
+ uint32_t nr;
+ uint32_t nonce2;
+ uint32_t ar2;
+ uint32_t nr2;
+} nonces_t;
+
/**
*MIFARE 1K simulate.
*
*@param flags :
* FLAG_INTERACTIVE - In interactive mode, we are expected to finish the operation with an ACK
- * 4B_FLAG_UID_IN_DATA - means that there is a 4-byte UID in the data-section, we're expected to use that
- * 7B_FLAG_UID_IN_DATA - means that there is a 7-byte UID in the data-section, we're expected to use that
+ * FLAG_4B_UID_IN_DATA - means that there is a 4-byte UID in the data-section, we're expected to use that
+ * FLAG_7B_UID_IN_DATA - means that there is a 7-byte UID in the data-section, we're expected to use that
+ * FLAG_10B_UID_IN_DATA - use 10-byte UID in the data-section not finished
* FLAG_NR_AR_ATTACK - means we should collect NR_AR responses for bruteforcing later
- *@param exitAfterNReads, exit simulation after n blocks have been read, 0 is inifite
+ *@param exitAfterNReads, exit simulation after n blocks have been read, 0 is infinite ...
+ * (unless reader attack mode enabled then it runs util it gets enough nonces to recover all keys attmpted)
*/
void Mifare1ksim(uint8_t flags, uint8_t exitAfterNReads, uint8_t arg2, uint8_t *datain)
{
int cardSTATE = MFEMUL_NOFIELD;
- int _7BUID = 0;
+ int _UID_LEN = 0; // 4, 7, 10
int vHf = 0; // in mV
int res;
uint32_t selTimer = 0;
uint8_t response[MAX_MIFARE_FRAME_SIZE];
uint8_t response_par[MAX_MIFARE_PARITY_SIZE];
- uint8_t rATQA[] = {0x04, 0x00}; // Mifare classic 1k 4BUID
+ uint8_t rATQA[] = {0x04, 0x00}; // Mifare classic 1k 4BUID
uint8_t rUIDBCC1[] = {0xde, 0xad, 0xbe, 0xaf, 0x62};
uint8_t rUIDBCC2[] = {0xde, 0xad, 0xbe, 0xaf, 0x62}; // !!!
- uint8_t rSAK[] = {0x08, 0xb6, 0xdd};
- uint8_t rSAK1[] = {0x04, 0xda, 0x17};
+ uint8_t rUIDBCC3[] = {0xde, 0xad, 0xbe, 0xaf, 0x62};
+
+ uint8_t rSAKfinal[]= {0x08, 0xb6, 0xdd}; // mifare 1k indicated
+ uint8_t rSAK1[] = {0x04, 0xda, 0x17}; // indicate UID not finished
uint8_t rAUTH_NT[] = {0x01, 0x02, 0x03, 0x04};
uint8_t rAUTH_AT[] = {0x00, 0x00, 0x00, 0x00};
- //Here, we collect UID,NT,AR,NR,UID2,NT2,AR2,NR2
- // This can be used in a reader-only attack.
- // (it can also be retrieved via 'hf 14a list', but hey...
- uint32_t ar_nr_responses[] = {0,0,0,0,0,0,0,0};
- uint8_t ar_nr_collected = 0;
+ //Here, we collect UID,sector,keytype,NT,AR,NR,NT2,AR2,NR2
+ // This will be used in the reader-only attack.
+
+ //allow collecting up to 8 sets of nonces to allow recovery of up to 8 keys
+ #define ATTACK_KEY_COUNT 8 // keep same as define in cmdhfmf.c -> readerAttack()
+ nonces_t ar_nr_resp[ATTACK_KEY_COUNT*2]; //*2 for 2 separate attack types (nml, moebius)
+ memset(ar_nr_resp, 0x00, sizeof(ar_nr_resp));
+
+ uint8_t ar_nr_collected[ATTACK_KEY_COUNT*2]; //*2 for 2nd attack type (moebius)
+ memset(ar_nr_collected, 0x00, sizeof(ar_nr_collected));
+ uint8_t nonce1_count = 0;
+ uint8_t nonce2_count = 0;
+ uint8_t moebius_n_count = 0;
+ bool gettingMoebius = false;
+ uint8_t mM = 0; //moebius_modifier for collection storage
// Authenticate response - nonce
uint32_t nonce = bytes_to_num(rAUTH_NT, 4);
// 4B uid comes from data-portion of packet
memcpy(rUIDBCC1,datain,4);
rUIDBCC1[4] = rUIDBCC1[0] ^ rUIDBCC1[1] ^ rUIDBCC1[2] ^ rUIDBCC1[3];
-
+ _UID_LEN = 4;
} else if (flags & FLAG_7B_UID_IN_DATA) {
// 7B uid comes from data-portion of packet
memcpy(&rUIDBCC1[1],datain,3);
memcpy(rUIDBCC2, datain+3, 4);
- _7BUID = true;
+ _UID_LEN = 7;
+ } else if (flags & FLAG_10B_UID_IN_DATA) {
+ memcpy(&rUIDBCC1[1], datain, 3);
+ memcpy(&rUIDBCC2[1], datain+3, 3);
+ memcpy( rUIDBCC3, datain+6, 4);
+ _UID_LEN = 10;
} else {
- // get UID from emul memory
+ // get UID from emul memory - guess at length
emlGetMemBt(receivedCmd, 7, 1);
- _7BUID = !(receivedCmd[0] == 0x00);
- if (!_7BUID) { // ---------- 4BUID
+ if (receivedCmd[0] == 0x00) { // ---------- 4BUID
emlGetMemBt(rUIDBCC1, 0, 4);
+ _UID_LEN = 4;
} else { // ---------- 7BUID
emlGetMemBt(&rUIDBCC1[1], 0, 3);
emlGetMemBt(rUIDBCC2, 3, 4);
+ _UID_LEN = 7;
}
}
- /*
- * Regardless of what method was used to set the UID, set fifth byte and modify
- * the ATQA for 4 or 7-byte UID
- */
- rUIDBCC1[4] = rUIDBCC1[0] ^ rUIDBCC1[1] ^ rUIDBCC1[2] ^ rUIDBCC1[3];
- if (_7BUID) {
- rATQA[0] = 0x44;
- rUIDBCC1[0] = 0x88;
- rUIDBCC1[4] = rUIDBCC1[0] ^ rUIDBCC1[1] ^ rUIDBCC1[2] ^ rUIDBCC1[3];
- rUIDBCC2[4] = rUIDBCC2[0] ^ rUIDBCC2[1] ^ rUIDBCC2[2] ^ rUIDBCC2[3];
- }
-
- if (MF_DBGLEVEL >= 1) {
- if (!_7BUID) {
- Dbprintf("4B UID: %02x%02x%02x%02x",
- rUIDBCC1[0], rUIDBCC1[1], rUIDBCC1[2], rUIDBCC1[3]);
- } else {
- Dbprintf("7B UID: (%02x)%02x%02x%02x%02x%02x%02x%02x",
- rUIDBCC1[0], rUIDBCC1[1], rUIDBCC1[2], rUIDBCC1[3],
- rUIDBCC2[0], rUIDBCC2[1] ,rUIDBCC2[2], rUIDBCC2[3]);
- }
+ switch (_UID_LEN) {
+ case 4:
+ // save CUID
+ cuid = bytes_to_num(rUIDBCC1, 4);
+ // BCC
+ rUIDBCC1[4] = rUIDBCC1[0] ^ rUIDBCC1[1] ^ rUIDBCC1[2] ^ rUIDBCC1[3];
+ if (MF_DBGLEVEL >= 2) {
+ Dbprintf("4B UID: %02x%02x%02x%02x",
+ rUIDBCC1[0],
+ rUIDBCC1[1],
+ rUIDBCC1[2],
+ rUIDBCC1[3]
+ );
+ }
+ break;
+ case 7:
+ rATQA[0] |= 0x40;
+ // save CUID
+ cuid = bytes_to_num(rUIDBCC2, 4);
+ // CascadeTag, CT
+ rUIDBCC1[0] = 0x88;
+ // BCC
+ rUIDBCC1[4] = rUIDBCC1[0] ^ rUIDBCC1[1] ^ rUIDBCC1[2] ^ rUIDBCC1[3];
+ rUIDBCC2[4] = rUIDBCC2[0] ^ rUIDBCC2[1] ^ rUIDBCC2[2] ^ rUIDBCC2[3];
+ if (MF_DBGLEVEL >= 2) {
+ Dbprintf("7B UID: %02x %02x %02x %02x %02x %02x %02x",
+ rUIDBCC1[1],
+ rUIDBCC1[2],
+ rUIDBCC1[3],
+ rUIDBCC2[0],
+ rUIDBCC2[1],
+ rUIDBCC2[2],
+ rUIDBCC2[3]
+ );
+ }
+ break;
+ case 10:
+ rATQA[0] |= 0x80;
+ //sak_10[0] &= 0xFB;
+ // save CUID
+ cuid = bytes_to_num(rUIDBCC3, 4);
+ // CascadeTag, CT
+ rUIDBCC1[0] = 0x88;
+ rUIDBCC2[0] = 0x88;
+ // BCC
+ rUIDBCC1[4] = rUIDBCC1[0] ^ rUIDBCC1[1] ^ rUIDBCC1[2] ^ rUIDBCC1[3];
+ rUIDBCC2[4] = rUIDBCC2[0] ^ rUIDBCC2[1] ^ rUIDBCC2[2] ^ rUIDBCC2[3];
+ rUIDBCC3[4] = rUIDBCC3[0] ^ rUIDBCC3[1] ^ rUIDBCC3[2] ^ rUIDBCC3[3];
+
+ if (MF_DBGLEVEL >= 2) {
+ Dbprintf("10B UID: %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x",
+ rUIDBCC1[1],
+ rUIDBCC1[2],
+ rUIDBCC1[3],
+ rUIDBCC2[1],
+ rUIDBCC2[2],
+ rUIDBCC2[3],
+ rUIDBCC3[0],
+ rUIDBCC3[1],
+ rUIDBCC3[2],
+ rUIDBCC3[3]
+ );
+ }
+ break;
+ default:
+ break;
}
// We need to listen to the high-frequency, peak-detected path.
clear_trace();
set_tracing(TRUE);
-
bool finished = FALSE;
- while (!BUTTON_PRESS() && !finished) {
+ bool button_pushed = BUTTON_PRESS();
+ while (!button_pushed && !finished && !usb_poll_validate_length()) {
WDT_HIT();
// find reader field
cardSTATE_TO_IDLE();
LED_A_ON();
}
- }
- if(cardSTATE == MFEMUL_NOFIELD) continue;
+ }
+ if (cardSTATE == MFEMUL_NOFIELD) continue;
//Now, get data
-
res = EmGetCmd(receivedCmd, &len, receivedCmd_par);
if (res == 2) { //Field is off!
cardSTATE = MFEMUL_NOFIELD;
} else if (res == 1) {
break; //return value 1 means button press
}
-
+
// REQ or WUP request in ANY state and WUP in HALTED state
- if (len == 1 && ((receivedCmd[0] == 0x26 && cardSTATE != MFEMUL_HALTED) || receivedCmd[0] == 0x52)) {
+ if (len == 1 && ((receivedCmd[0] == ISO14443A_CMD_REQA && cardSTATE != MFEMUL_HALTED) || receivedCmd[0] == ISO14443A_CMD_WUPA)) {
selTimer = GetTickCount();
- EmSendCmdEx(rATQA, sizeof(rATQA), (receivedCmd[0] == 0x52));
+ EmSendCmdEx(rATQA, sizeof(rATQA), (receivedCmd[0] == ISO14443A_CMD_WUPA));
cardSTATE = MFEMUL_SELECT1;
// init crypto block
break;
}
case MFEMUL_SELECT1:{
- // select all
- if (len == 2 && (receivedCmd[0] == 0x93 && receivedCmd[1] == 0x20)) {
+ // select all - 0x93 0x20
+ if (len == 2 && (receivedCmd[0] == ISO14443A_CMD_ANTICOLL_OR_SELECT && receivedCmd[1] == 0x20)) {
if (MF_DBGLEVEL >= 4) Dbprintf("SELECT ALL received");
EmSendCmd(rUIDBCC1, sizeof(rUIDBCC1));
break;
}
- if (MF_DBGLEVEL >= 4 && len == 9 && receivedCmd[0] == 0x93 && receivedCmd[1] == 0x70 )
- {
- Dbprintf("SELECT %02x%02x%02x%02x received",receivedCmd[2],receivedCmd[3],receivedCmd[4],receivedCmd[5]);
+ // select card - 0x93 0x70 ...
+ if (len == 9 &&
+ (receivedCmd[0] == ISO14443A_CMD_ANTICOLL_OR_SELECT && receivedCmd[1] == 0x70 && memcmp(&receivedCmd[2], rUIDBCC1, 4) == 0)) {
+ if (MF_DBGLEVEL >= 4)
+ Dbprintf("SELECT %02x%02x%02x%02x received",receivedCmd[2],receivedCmd[3],receivedCmd[4],receivedCmd[5]);
+
+ switch(_UID_LEN) {
+ case 4:
+ cardSTATE = MFEMUL_WORK;
+ LED_B_ON();
+ if (MF_DBGLEVEL >= 4) Dbprintf("--> WORK. anticol1 time: %d", GetTickCount() - selTimer);
+ EmSendCmd(rSAKfinal, sizeof(rSAKfinal));
+ break;
+ case 7:
+ cardSTATE = MFEMUL_SELECT2;
+ EmSendCmd(rSAK1, sizeof(rSAK1));
+ break;
+ case 10:
+ cardSTATE = MFEMUL_SELECT2;
+ EmSendCmd(rSAK1, sizeof(rSAK1));
+ break;
+ default:break;
+ }
+ } else {
+ cardSTATE_TO_IDLE();
+ }
+ break;
+ }
+ case MFEMUL_SELECT3:{
+ if (!len) {
+ LogTrace(Uart.output, Uart.len, Uart.startTime*16 - DELAY_AIR2ARM_AS_TAG, Uart.endTime*16 - DELAY_AIR2ARM_AS_TAG, Uart.parity, TRUE);
+ break;
}
- // select card
+ // select all cl3 - 0x97 0x20
+ if (len == 2 && (receivedCmd[0] == ISO14443A_CMD_ANTICOLL_OR_SELECT_3 && receivedCmd[1] == 0x20)) {
+ EmSendCmd(rUIDBCC3, sizeof(rUIDBCC3));
+ break;
+ }
+ // select card cl3 - 0x97 0x70
if (len == 9 &&
- (receivedCmd[0] == 0x93 && receivedCmd[1] == 0x70 && memcmp(&receivedCmd[2], rUIDBCC1, 4) == 0)) {
- EmSendCmd(_7BUID?rSAK1:rSAK, _7BUID?sizeof(rSAK1):sizeof(rSAK));
- cuid = bytes_to_num(rUIDBCC1, 4);
- if (!_7BUID) {
- cardSTATE = MFEMUL_WORK;
- LED_B_ON();
- if (MF_DBGLEVEL >= 4) Dbprintf("--> WORK. anticol1 time: %d", GetTickCount() - selTimer);
- break;
- } else {
- cardSTATE = MFEMUL_SELECT2;
- }
+ (receivedCmd[0] == ISO14443A_CMD_ANTICOLL_OR_SELECT_3 &&
+ receivedCmd[1] == 0x70 &&
+ memcmp(&receivedCmd[2], rUIDBCC3, 4) == 0) ) {
+
+ EmSendCmd(rSAKfinal, sizeof(rSAKfinal));
+ cardSTATE = MFEMUL_WORK;
+ LED_B_ON();
+ if (MF_DBGLEVEL >= 4) Dbprintf("--> WORK. anticol3 time: %d", GetTickCount() - selTimer);
+ break;
}
+ cardSTATE_TO_IDLE();
break;
}
case MFEMUL_AUTH1:{
- if( len != 8)
- {
+ if( len != 8) {
cardSTATE_TO_IDLE();
LogTrace(Uart.output, Uart.len, Uart.startTime*16 - DELAY_AIR2ARM_AS_TAG, Uart.endTime*16 - DELAY_AIR2ARM_AS_TAG, Uart.parity, TRUE);
break;
}
- uint32_t ar = bytes_to_num(receivedCmd, 4);
- uint32_t nr = bytes_to_num(&receivedCmd[4], 4);
-
- //Collect AR/NR
- if(ar_nr_collected < 2){
- if(ar_nr_responses[2] != ar)
- {// Avoid duplicates... probably not necessary, ar should vary.
- ar_nr_responses[ar_nr_collected*4] = cuid;
- ar_nr_responses[ar_nr_collected*4+1] = nonce;
- ar_nr_responses[ar_nr_collected*4+2] = ar;
- ar_nr_responses[ar_nr_collected*4+3] = nr;
- ar_nr_collected++;
+ uint32_t nr = bytes_to_num(receivedCmd, 4);
+ uint32_t ar = bytes_to_num(&receivedCmd[4], 4);
+
+ // Collect AR/NR per keytype & sector
+ if(flags & FLAG_NR_AR_ATTACK) {
+ for (uint8_t i = 0; i < ATTACK_KEY_COUNT; i++) {
+ if ( ar_nr_collected[i+mM]==0 || ((cardAUTHSC == ar_nr_resp[i+mM].sector) && (cardAUTHKEY == ar_nr_resp[i+mM].keytype) && (ar_nr_collected[i+mM] > 0)) ) {
+ // if first auth for sector, or matches sector and keytype of previous auth
+ if (ar_nr_collected[i+mM] < 2) {
+ // if we haven't already collected 2 nonces for this sector
+ if (ar_nr_resp[ar_nr_collected[i+mM]].ar != ar) {
+ // Avoid duplicates... probably not necessary, ar should vary.
+ if (ar_nr_collected[i+mM]==0) {
+ // first nonce collect
+ ar_nr_resp[i+mM].cuid = cuid;
+ ar_nr_resp[i+mM].sector = cardAUTHSC;
+ ar_nr_resp[i+mM].keytype = cardAUTHKEY;
+ ar_nr_resp[i+mM].nonce = nonce;
+ ar_nr_resp[i+mM].nr = nr;
+ ar_nr_resp[i+mM].ar = ar;
+ nonce1_count++;
+ // add this nonce to first moebius nonce
+ ar_nr_resp[i+ATTACK_KEY_COUNT].cuid = cuid;
+ ar_nr_resp[i+ATTACK_KEY_COUNT].sector = cardAUTHSC;
+ ar_nr_resp[i+ATTACK_KEY_COUNT].keytype = cardAUTHKEY;
+ ar_nr_resp[i+ATTACK_KEY_COUNT].nonce = nonce;
+ ar_nr_resp[i+ATTACK_KEY_COUNT].nr = nr;
+ ar_nr_resp[i+ATTACK_KEY_COUNT].ar = ar;
+ ar_nr_collected[i+ATTACK_KEY_COUNT]++;
+ } else { // second nonce collect (std and moebius)
+ ar_nr_resp[i+mM].nonce2 = nonce;
+ ar_nr_resp[i+mM].nr2 = nr;
+ ar_nr_resp[i+mM].ar2 = ar;
+ if (!gettingMoebius) {
+ nonce2_count++;
+ // check if this was the last second nonce we need for std attack
+ if ( nonce2_count == nonce1_count ) {
+ // done collecting std test switch to moebius
+ // first finish incrementing last sample
+ ar_nr_collected[i+mM]++;
+ // switch to moebius collection
+ gettingMoebius = true;
+ mM = ATTACK_KEY_COUNT;
+ nonce = nonce*7;
+ break;
+ }
+ } else {
+ moebius_n_count++;
+ // if we've collected all the nonces we need - finish.
+ if (nonce1_count == moebius_n_count) finished = true;
+ }
+ }
+ ar_nr_collected[i+mM]++;
+ }
+ }
+ // we found right spot for this nonce stop looking
+ break;
+ }
}
}
// --- crypto
- crypto1_word(pcs, ar , 1);
- cardRr = nr ^ crypto1_word(pcs, 0, 0);
+ crypto1_word(pcs, nr , 1);
+ cardRr = ar ^ crypto1_word(pcs, 0, 0);
// test if auth OK
if (cardRr != prng_successor(nonce, 64)){
break;
}
+ //auth successful
ans = prng_successor(nonce, 96) ^ crypto1_word(pcs, 0, 0);
num_to_bytes(ans, 4, rAUTH_AT);
if (!len) {
LogTrace(Uart.output, Uart.len, Uart.startTime*16 - DELAY_AIR2ARM_AS_TAG, Uart.endTime*16 - DELAY_AIR2ARM_AS_TAG, Uart.parity, TRUE);
break;
- }
- if (len == 2 && (receivedCmd[0] == 0x95 && receivedCmd[1] == 0x20)) {
+ }
+ // select all cl2 - 0x95 0x20
+ if (len == 2 && (receivedCmd[0] == ISO14443A_CMD_ANTICOLL_OR_SELECT_2 && receivedCmd[1] == 0x20)) {
EmSendCmd(rUIDBCC2, sizeof(rUIDBCC2));
break;
}
- // select 2 card
+ // select cl2 card - 0x95 0x70 xxxxxxxxxxxx
if (len == 9 &&
- (receivedCmd[0] == 0x95 && receivedCmd[1] == 0x70 && memcmp(&receivedCmd[2], rUIDBCC2, 4) == 0)) {
- EmSendCmd(rSAK, sizeof(rSAK));
- cuid = bytes_to_num(rUIDBCC2, 4);
- cardSTATE = MFEMUL_WORK;
- LED_B_ON();
- if (MF_DBGLEVEL >= 4) Dbprintf("--> WORK. anticol2 time: %d", GetTickCount() - selTimer);
+ (receivedCmd[0] == ISO14443A_CMD_ANTICOLL_OR_SELECT_2 && receivedCmd[1] == 0x70 && memcmp(&receivedCmd[2], rUIDBCC2, 4) == 0)) {
+ switch(_UID_LEN) {
+ case 7:
+ EmSendCmd(rSAKfinal, sizeof(rSAKfinal));
+ cardSTATE = MFEMUL_WORK;
+ LED_B_ON();
+ if (MF_DBGLEVEL >= 4) Dbprintf("--> WORK. anticol2 time: %d", GetTickCount() - selTimer);
+ break;
+ case 10:
+ EmSendCmd(rSAK1, sizeof(rSAK1));
+ cardSTATE = MFEMUL_SELECT3;
+ break;
+ default:break;
+ }
break;
}
}
if (len == 4 && (receivedCmd[0] == 0x60 || receivedCmd[0] == 0x61)) {
+
+ // if authenticating to a block that shouldn't exist - as long as we are not doing the reader attack
+ if (receivedCmd[1] >= 16 * 4 && !(flags & FLAG_NR_AR_ATTACK)) {
+ //is this the correct response to an auth on a out of range block? marshmellow
+ EmSend4bit(mf_crypto1_encrypt4bit(pcs, CARD_NACK_NA));
+ if (MF_DBGLEVEL >= 2) Dbprintf("Reader tried to operate (0x%02x) on out of range block: %d (0x%02x), nacking",receivedCmd[0],receivedCmd[1],receivedCmd[1]);
+ break;
+ }
+
authTimer = GetTickCount();
cardAUTHSC = receivedCmd[1] / 4; // received block num
cardAUTHKEY = receivedCmd[0] - 0x60;
crypto1_destroy(pcs);//Added by martin
crypto1_create(pcs, emlGetKey(cardAUTHSC, cardAUTHKEY));
+ //uint64_t key=emlGetKey(cardAUTHSC, cardAUTHKEY);
+ //Dbprintf("key: %04x%08x",(uint32_t)(key>>32)&0xFFFF,(uint32_t)(key&0xFFFFFFFF));
if (!encrypted_data) { // first authentication
if (MF_DBGLEVEL >= 4) Dbprintf("Reader authenticating for block %d (0x%02x) with key %d",receivedCmd[1] ,receivedCmd[1],cardAUTHKEY );
break;
}
}
+ button_pushed = BUTTON_PRESS();
}
FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
LEDsoff();
- if(flags & FLAG_INTERACTIVE)// Interactive mode flag, means we need to send ACK
- {
- //May just aswell send the collected ar_nr in the response aswell
- cmd_send(CMD_ACK,CMD_SIMULATE_MIFARE_CARD,0,0,&ar_nr_responses,ar_nr_collected*4*4);
- }
-
- if(flags & FLAG_NR_AR_ATTACK)
- {
- if(ar_nr_collected > 1) {
- Dbprintf("Collected two pairs of AR/NR which can be used to extract keys from reader:");
- Dbprintf("../tools/mfkey/mfkey32 %08x %08x %08x %08x %08x %08x",
- ar_nr_responses[0], // UID
- ar_nr_responses[1], //NT
- ar_nr_responses[2], //AR1
- ar_nr_responses[3], //NR1
- ar_nr_responses[6], //AR2
- ar_nr_responses[7] //NR2
- );
- } else {
- Dbprintf("Failed to obtain two AR/NR pairs!");
- if(ar_nr_collected >0) {
- Dbprintf("Only got these: UID=%08x, nonce=%08x, AR1=%08x, NR1=%08x",
- ar_nr_responses[0], // UID
- ar_nr_responses[1], //NT
- ar_nr_responses[2], //AR1
- ar_nr_responses[3] //NR1
+ if(flags & FLAG_NR_AR_ATTACK && MF_DBGLEVEL >= 1) {
+ for ( uint8_t i = 0; i < ATTACK_KEY_COUNT; i++) {
+ if (ar_nr_collected[i] == 2) {
+ Dbprintf("Collected two pairs of AR/NR which can be used to extract %s from reader for sector %d:", (i<ATTACK_KEY_COUNT/2) ? "keyA" : "keyB", ar_nr_resp[i].sector);
+ Dbprintf("../tools/mfkey/mfkey32 %08x %08x %08x %08x %08x %08x",
+ ar_nr_resp[i].cuid, //UID
+ ar_nr_resp[i].nonce, //NT
+ ar_nr_resp[i].nr, //NR1
+ ar_nr_resp[i].ar, //AR1
+ ar_nr_resp[i].nr2, //NR2
+ ar_nr_resp[i].ar2 //AR2
+ );
+ }
+ }
+ for ( uint8_t i = ATTACK_KEY_COUNT; i < ATTACK_KEY_COUNT*2; i++) {
+ if (ar_nr_collected[i] == 2) {
+ Dbprintf("Collected two pairs of AR/NR which can be used to extract %s from reader for sector %d:", (i<ATTACK_KEY_COUNT/2) ? "keyA" : "keyB", ar_nr_resp[i].sector);
+ Dbprintf("../tools/mfkey/mfkey32v2 %08x %08x %08x %08x %08x %08x %08x",
+ ar_nr_resp[i].cuid, //UID
+ ar_nr_resp[i].nonce, //NT
+ ar_nr_resp[i].nr, //NR1
+ ar_nr_resp[i].ar, //AR1
+ ar_nr_resp[i].nonce2,//NT2
+ ar_nr_resp[i].nr2, //NR2
+ ar_nr_resp[i].ar2 //AR2
);
}
}
}
if (MF_DBGLEVEL >= 1) Dbprintf("Emulator stopped. Tracing: %d trace length: %d ", tracing, BigBuf_get_traceLen());
-
-}
+ if(flags & FLAG_INTERACTIVE) { // Interactive mode flag, means we need to send ACK
+ //Send the collected ar_nr in the response
+ cmd_send(CMD_ACK,CMD_SIMULATE_MIFARE_CARD,button_pushed,0,&ar_nr_resp,sizeof(ar_nr_resp));
+ }
+}
//-----------------------------------------------------------------------------
}
*/
// Subcarrier amplitude v = sqrt(ci^2 + cq^2), approximated here by max(abs(ci),abs(cq)) + 1/2*min(abs(ci),abs(cq)))
+
+ //note: couldn't we just use MAX(ABS(ci),ABS(cq)) + (MIN(ABS(ci),ABS(cq))/2) from common.h - marshmellow
#define CHECK_FOR_SUBCARRIER() { \
+ v = MAX(ABS(ci),ABS(cq)) + (MIN(ABS(ci),ABS(cq))/2); \
+ }
+ /*
if(ci < 0) { \
- if(cq < 0) { /* ci < 0, cq < 0 */ \
+ if(cq < 0) { \ // ci < 0, cq < 0
if (cq < ci) { \
v = -cq - (ci >> 1); \
} else { \
v = -ci - (cq >> 1); \
} \
- } else { /* ci < 0, cq >= 0 */ \
+ } else { \ // ci < 0, cq >= 0
if (cq < -ci) { \
v = -ci + (cq >> 1); \
} else { \
} \
} \
} else { \
- if(cq < 0) { /* ci >= 0, cq < 0 */ \
+ if(cq < 0) { \ // ci >= 0, cq < 0
if (-cq < ci) { \
v = ci - (cq >> 1); \
} else { \
v = -cq + (ci >> 1); \
} \
- } else { /* ci >= 0, cq >= 0 */ \
+ } else { \ // ci >= 0, cq >= 0
if (cq < ci) { \
v = ci + (cq >> 1); \
} else { \
} \
} \
}
+ */
switch(Demod.state) {
case DEMOD_UNSYNCD:
// every other is Q. We just want power, so abs(I) + abs(Q) is
// close to what we want.
if(getNext) {
- int8_t r;
-
- if(b < 0) {
- r = -b;
- } else {
- r = b;
- }
- if(prev < 0) {
- r -= prev;
- } else {
- r += prev;
- }
+ int8_t r = ABS(b) + ABS(prev);
dest[c++] = (uint8_t)r;
// every other is Q. We just want power, so abs(I) + abs(Q) is
// close to what we want.
if(getNext) {
- int8_t r;
-
- if(b < 0) {
- r = -b;
- } else {
- r = b;
- }
- if(prev < 0) {
- r -= prev;
- } else {
- r += prev;
- }
+ int8_t r = ABS(b) + ABS(prev);
dest[c++] = (uint8_t)r;
// every other is Q. We just want power, so abs(I) + abs(Q) is
// close to what we want.
if(getNext) {
- int8_t r;
-
- if(b < 0) {
- r = -b;
- } else {
- r = b;
- }
- if(prev < 0) {
- r -= prev;
- } else {
- r += prev;
- }
+ int8_t r = ABS(b) + ABS(prev);
dest[c++] = (uint8_t)r;
// every other is Q. We just want power, so abs(I) + abs(Q) is
// close to what we want.
if(getNext) {
- int8_t r;
-
- if(b < 0) {
- r = -b;
- } else {
- r = b;
- }
- if(prev < 0) {
- r -= prev;
- } else {
- r += prev;
- }
+ int8_t r = ABS(b) + ABS(prev);
dest[c++] = (uint8_t)r;
uint32_t cmd_sz = addr_sz+1+8+4; //crc+data+cmd
legic_prng_forward(2); /* we wait anyways */
- while(timer->TC_CV < 387) ; /* ~ 258us */
+ while(timer->TC_CV < 387) {}; /* ~ 258us */
frame_send_rwd(cmd, cmd_sz);
//== wait for ack ====================================
}
}
timer->TC_CCR = AT91C_TC_SWTRG;
- while(timer->TC_CV > 1) ; /* Wait till the clock has reset */
+ while(timer->TC_CV > 1) {}; /* Wait till the clock has reset */
return -1;
}
sample_config sc = { 0,0,1, divisor_used, 0};
setSamplingConfig(&sc);
+ //clear read buffer
+ BigBuf_Clear_keep_EM();
/* Make sure the tag is reset */
FpgaDownloadAndGo(FPGA_BITSTREAM_LF);
AcquireTiType();
FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
- DbpString("Now use tiread to check");
+ DbpString("Now use `lf ti read` to check");
}
void SimulateTagLowFrequency(int period, int gap, int ledcontrol)
memset(dest+(*n), c ^ *phase, clock);
*phase ^= 1;
}
+ *n += clock;
+}
+
+static void stAskSimBit(int *n, uint8_t clock) {
+ uint8_t *dest = BigBuf_get_addr();
+ uint8_t halfClk = clock/2;
+ //ST = .5 high .5 low 1.5 high .5 low 1 high
+ memset(dest+(*n), 1, halfClk);
+ memset(dest+(*n) + halfClk, 0, halfClk);
+ memset(dest+(*n) + clock, 1, clock + halfClk);
+ memset(dest+(*n) + clock*2 + halfClk, 0, halfClk);
+ memset(dest+(*n) + clock*3, 1, clock);
+ *n += clock*4;
}
// args clock, ask/man or askraw, invert, transmission separator
for (i=0; i<size; i++){
biphaseSimBit(BitStream[i]^invert, &n, clk, &phase);
}
- if (BitStream[0]==BitStream[size-1]){ //run a second set inverted to keep phase in check
+ if (phase==1) { //run a second set inverted to keep phase in check
for (i=0; i<size; i++){
biphaseSimBit(BitStream[i]^invert, &n, clk, &phase);
}
}
}
}
-
- if (separator==1) Dbprintf("sorry but separator option not yet available");
+ if (separator==1 && encoding == 1)
+ stAskSimBit(&n, clk);
+ else if (separator==1)
+ Dbprintf("sorry but separator option not yet available");
Dbprintf("Simulating with clk: %d, invert: %d, encoding: %d, separator: %d, n: %d",clk, invert, encoding, separator, n);
//DEBUG
//Dbprintf("%d%d%d%d%d%d%d%d%d%d%d%d%d%d%d%d", dest[i],dest[i+1],dest[i+2],dest[i+3],dest[i+4],dest[i+5],dest[i+6],dest[i+7],dest[i+8],dest[i+9],dest[i+10],dest[i+11],dest[i+12],dest[i+13],dest[i+14],dest[i+15]);
//i+=16;
//Dbprintf("%d%d%d%d%d%d%d%d%d%d%d%d%d%d%d%d", dest[i],dest[i+1],dest[i+2],dest[i+3],dest[i+4],dest[i+5],dest[i+6],dest[i+7],dest[i+8],dest[i+9],dest[i+10],dest[i+11],dest[i+12],dest[i+13],dest[i+14],dest[i+15]);
-
+
if (ledcontrol) LED_A_ON();
SimulateTagLowFrequency(n, 0, ledcontrol);
if (ledcontrol) LED_A_OFF();
// Configure to go in 125Khz listen mode
LFSetupFPGAForADC(95, true);
+ //clear read buffer
+ BigBuf_Clear_keep_EM();
+
while(!BUTTON_PRESS() && !usb_poll_validate_length()) {
WDT_HIT();
uint8_t *dest = BigBuf_get_addr();
size_t size;
int idx=0;
+ //clear read buffer
+ BigBuf_Clear_keep_EM();
// Configure to go in 125Khz listen mode
LFSetupFPGAForADC(95, true);
int clk=0, invert=0, errCnt=0, maxErr=20;
uint32_t hi=0;
uint64_t lo=0;
+ //clear read buffer
+ BigBuf_Clear_keep_EM();
// Configure to go in 125Khz listen mode
LFSetupFPGAForADC(95, true);
uint8_t version=0;
uint8_t facilitycode=0;
uint16_t number=0;
+ //clear read buffer
+ BigBuf_Clear_keep_EM();
// Configure to go in 125Khz listen mode
LFSetupFPGAForADC(95, true);
void T55xxResetRead(void) {
LED_A_ON();
//clear buffer now so it does not interfere with timing later
- BigBuf_Clear_ext(false);
+ BigBuf_Clear_keep_EM();
// Set up FPGA, 125kHz
LFSetupFPGAForADC(95, true);
LED_D_ON();
// Write EM410x ID
- uint32_t data[] = {0, id>>32, id & 0xFFFFFFFF};
+ uint32_t data[] = {0, (uint32_t)(id>>32), (uint32_t)(id & 0xFFFFFFFF)};
clock = (card & 0xFF00) >> 8;
clock = (clock == 0) ? 64 : clock;
uint8_t *dest = BigBuf_get_addr();
int bufsize = BigBuf_max_traceLen();
- memset(dest, 0, bufsize);
+ //memset(dest, 0, bufsize); //creates issues with cmdread (marshmellow)
if(bits_per_sample < 1) bits_per_sample = 1;
if(bits_per_sample > 8) bits_per_sample = 8;
#define MFEMUL_IDLE 1\r
#define MFEMUL_SELECT1 2\r
#define MFEMUL_SELECT2 3\r
-#define MFEMUL_AUTH1 4\r
-#define MFEMUL_AUTH2 5\r
-#define MFEMUL_WORK 6\r
-#define MFEMUL_WRITEBL2 7\r
-#define MFEMUL_INTREG_INC 8\r
-#define MFEMUL_INTREG_DEC 9\r
-#define MFEMUL_INTREG_REST 10\r
-#define MFEMUL_HALTED 11\r
+#define MFEMUL_SELECT3 4\r
+#define MFEMUL_AUTH1 5\r
+#define MFEMUL_AUTH2 6\r
+#define MFEMUL_WORK 7\r
+#define MFEMUL_WRITEBL2 8\r
+#define MFEMUL_INTREG_INC 9\r
+#define MFEMUL_INTREG_DEC 10\r
+#define MFEMUL_INTREG_REST 11\r
+#define MFEMUL_HALTED 12\r
\r
#define cardSTATE_TO_IDLE() cardSTATE = MFEMUL_IDLE; LED_B_OFF(); LED_C_OFF();\r
\r
#define T0_PCF 8 //period for the pcf7931 in us
#define ALLOC 16
-#define abs(x) ( ((x)<0) ? -(x) : (x) )
-#define max(x,y) ( x<y ? y:x)
-
int DemodPCF7931(uint8_t **outBlocks) {
uint8_t bits[256] = {0x00};
int num_blocks = 0;
int lmin=128, lmax=128;
uint8_t dir;
+ //clear read buffer
+ BigBuf_Clear_keep_EM();
LFSetupFPGAForADC(95, true);
DoAcquisition_default(0, true);
// Switch depending on lc length:
// Tolerance is 1/8 of clock rate (arbitrary)
- if (abs(lc-clock/4) < tolerance) {
+ if (ABS(lc-clock/4) < tolerance) {
// 16T0
if((i - pmc) == lc) { /* 16T0 was previous one */
/* It's a PMC ! */
else {
pmc = i;
}
- } else if (abs(lc-clock/2) < tolerance) {
+ } else if (ABS(lc-clock/2) < tolerance) {
// 32TO
if((i - pmc) == lc) { /* 16T0 was previous one */
/* It's a PMC ! */
}
else
half_switch++;
- } else if (abs(lc-clock) < tolerance) {
+ } else if (ABS(lc-clock) < tolerance) {
// 64TO
bits[bitidx++] = 1;
} else {
Blocks[0][ALLOC] = 1;
memcpy(Blocks[1], tmpBlocks[i+1], 16);
Blocks[1][ALLOC] = 1;
- max_blocks = max((Blocks[1][14] & 0x7f), Blocks[1][15]) + 1;
+ max_blocks = MAX((Blocks[1][14] & 0x7f), Blocks[1][15]) + 1;
// Debug print
Dbprintf("(dbg) Max blocks: %d", max_blocks);
num_blocks = 2;
size_t rx_len;
usb_enable();
- for (volatile size_t i=0; i<0x100000; i++);
+ for (volatile size_t i=0; i<0x100000; i++) {};
for(;;) {
WDT_HIT();
CXXFLAGS = $(shell pkg-config --cflags QtCore QtGui 2>/dev/null) -Wall -O4
QTLDLIBS = $(shell pkg-config --libs QtCore QtGui 2>/dev/null)
LUALIB += -ldl
+ LDLIBS += -ltermcap -lncurses
MOC = $(shell pkg-config --variable=moc_location QtCore)
# Below is a variant you can use if you have problems compiling with QT5 on ubuntu. see http://www.proxmark.org/forum/viewtopic.php?id=1661 for more info.
#MOC = /usr/lib/x86_64-linux-gnu/qt4/bin/moc
cmdlft55xx.c \
cmdlfpcf7931.c\
cmdlfviking.c\
+ cmdlfpresco.c\
+ cmdlfpyramid.c\
pm3_binlib.c\
scripting.c\
cmdscript.c\
// Data and Graph commands
//-----------------------------------------------------------------------------
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <limits.h>
-#include "proxmark3.h"
-#include "data.h"
-#include "ui.h"
-#include "graph.h"
-#include "cmdparser.h"
+#include <stdio.h> // also included in util.h
+#include <string.h> // also included in util.h
+#include <limits.h> // for CmdNorm INT_MIN && INT_MAX
+#include "data.h" // also included in util.h
+#include "cmddata.h"
#include "util.h"
#include "cmdmain.h"
-#include "cmddata.h"
-#include "lfdemod.h"
-#include "usb_cmd.h"
-#include "crc.h"
-#include "crc16.h"
-#include "loclass/cipherutils.h"
+#include "proxmark3.h"
+#include "ui.h" // for show graph controls
+#include "graph.h" // for graph data
+#include "cmdparser.h"// already included in cmdmain.h
+#include "usb_cmd.h" // already included in cmdmain.h and proxmark3.h
+#include "lfdemod.h" // for demod code
+#include "crc.h" // for pyramid checksum maxim
+#include "crc16.h" // for FDXB demod checksum
+#include "loclass/cipherutils.h" // for decimating samples in getsamples
uint8_t DemodBuffer[MAX_DEMOD_BUF_LEN];
uint8_t g_debugMode=0;
int AskEm410xDemod(const char *Cmd, uint32_t *hi, uint64_t *lo, bool verbose)
{
- if (!ASKDemod(Cmd, FALSE, FALSE, 1)) return 0;
+ bool st = TRUE;
+ if (!ASKDemod_ext(Cmd, FALSE, FALSE, 1, &st)) return 0;
return AskEm410xDecode(verbose, hi, lo);
}
//verbose will print results and demoding messages
//emSearch will auto search for EM410x format in bitstream
//askType switches decode: ask/raw = 0, ask/manchester = 1
-int ASKDemod(const char *Cmd, bool verbose, bool emSearch, uint8_t askType)
-{
+int ASKDemod_ext(const char *Cmd, bool verbose, bool emSearch, uint8_t askType, bool *stCheck) {
int invert=0;
int clk=0;
int maxErr=100;
if (amp == 'a' || amp == 'A') askAmp=1;
size_t BitLen = getFromGraphBuf(BitStream);
if (g_debugMode) PrintAndLog("DEBUG: Bitlen from grphbuff: %d",BitLen);
- if (BitLen<255) return 0;
- if (maxLen<BitLen && maxLen != 0) BitLen = maxLen;
-
+ if (BitLen < 255) return 0;
+ if (maxLen < BitLen && maxLen != 0) BitLen = maxLen;
+ int foundclk = 0;
+ bool st = false;
+ if (*stCheck) st = DetectST(BitStream, &BitLen, &foundclk);
+ if (st) {
+ *stCheck = st;
+ clk = (clk == 0) ? foundclk : clk;
+ if (verbose || g_debugMode) PrintAndLog("\nFound Sequence Terminator");
+ }
int errCnt = askdemod(BitStream, &BitLen, &clk, &invert, maxErr, askAmp, askType);
if (errCnt<0 || BitLen<16){ //if fatal error (or -1)
if (g_debugMode) PrintAndLog("DEBUG: no data found %d, errors:%d, bitlen:%d, clock:%d",errCnt,invert,BitLen,clk);
return 0;
}
- if (errCnt>maxErr){
+ if (errCnt > maxErr){
if (g_debugMode) PrintAndLog("DEBUG: Too many errors found, errors:%d, bits:%d, clock:%d",errCnt, BitLen, clk);
return 0;
}
}
return 1;
}
+int ASKDemod(const char *Cmd, bool verbose, bool emSearch, uint8_t askType) {
+ bool st = false;
+ return ASKDemod_ext(Cmd, verbose, emSearch, askType, &st);
+}
//by marshmellow
//takes 5 arguments - clock, invert, maxErr, maxLen as integers and amplify as char == 'a'
{
char cmdp = param_getchar(Cmd, 0);
if (strlen(Cmd) > 25 || cmdp == 'h' || cmdp == 'H') {
- PrintAndLog("Usage: data rawdemod am [clock] <invert> [maxError] [maxLen] [amplify]");
+ PrintAndLog("Usage: data rawdemod am <s> [clock] <invert> [maxError] [maxLen] [amplify]");
+ PrintAndLog(" ['s'] optional, check for Sequence Terminator");
PrintAndLog(" [set clock as integer] optional, if not set, autodetect");
PrintAndLog(" <invert>, 1 to invert output");
PrintAndLog(" [set maximum allowed errors], default = 100");
PrintAndLog(" : data rawdemod am 64 1 0 = demod an ask/manchester tag from GraphBuffer using a clock of RF/64, inverting data and allowing 0 demod errors");
return 0;
}
- return ASKDemod(Cmd, TRUE, TRUE, 1);
+ bool st = TRUE;
+ if (Cmd[0]=='s')
+ return ASKDemod_ext(Cmd++, TRUE, TRUE, 1, &st);
+ else if (Cmd[1] == 's')
+ return ASKDemod_ext(Cmd+=2, TRUE, TRUE, 1, &st);
+ else
+ return ASKDemod(Cmd, TRUE, TRUE, 1);
}
//by marshmellow
int CmdG_Prox_II_Demod(const char *Cmd)
{
if (!ASKbiphaseDemod(Cmd, FALSE)){
- if (g_debugMode) PrintAndLog("ASKbiphaseDemod failed 1st try");
+ if (g_debugMode) PrintAndLog("Error gProxII: ASKbiphaseDemod failed 1st try");
return 0;
}
size_t size = DemodBufferLen;
if (g_debugMode) PrintAndLog("Error gProxII_Demod");
return 0;
}
- //got a good demod
- uint32_t ByteStream[65] = {0x00};
+ //got a good demod of 96 bits
+ uint8_t ByteStream[8] = {0x00};
uint8_t xorKey=0;
- uint8_t keyCnt=0;
- uint8_t bitCnt=0;
- uint8_t ByteCnt=0;
- size_t startIdx = ans + 6; //start after preamble
- for (size_t idx = 0; idx<size-6; idx++){
- if ((idx+1) % 5 == 0){
- //spacer bit - should be 0
- if (DemodBuffer[startIdx+idx] != 0) {
- if (g_debugMode) PrintAndLog("Error spacer not 0: %d, pos: %d",DemodBuffer[startIdx+idx],startIdx+idx);
- return 0;
- }
- continue;
- }
- if (keyCnt<8){ //lsb first
- xorKey = xorKey | (DemodBuffer[startIdx+idx]<<keyCnt);
- keyCnt++;
- if (keyCnt==8 && g_debugMode) PrintAndLog("xorKey Found: %02x", xorKey);
- continue;
- }
- //lsb first
- ByteStream[ByteCnt] = ByteStream[ByteCnt] | (DemodBuffer[startIdx+idx]<<bitCnt);
- bitCnt++;
- if (bitCnt % 8 == 0){
- if (g_debugMode) PrintAndLog("byte %d: %02x",ByteCnt,ByteStream[ByteCnt]);
- bitCnt=0;
- ByteCnt++;
- }
+ size_t startIdx = ans + 6; //start after 6 bit preamble
+
+ uint8_t bits_no_spacer[90];
+ //so as to not mess with raw DemodBuffer copy to a new sample array
+ memcpy(bits_no_spacer, DemodBuffer + startIdx, 90);
+ // remove the 18 (90/5=18) parity bits (down to 72 bits (96-6-18=72))
+ size_t bitLen = removeParity(bits_no_spacer, 0, 5, 3, 90); //source, startloc, paritylen, ptype, length_to_run
+ if (bitLen != 72) {
+ if (g_debugMode) PrintAndLog("Error gProxII: spacer removal did not produce 72 bits: %u, start: %u", bitLen, startIdx);
+ return 0;
}
- for (uint8_t i = 0; i < ByteCnt; i++){
- ByteStream[i] ^= xorKey; //xor
- if (g_debugMode) PrintAndLog("byte %d after xor: %02x", i, ByteStream[i]);
+ // get key and then get all 8 bytes of payload decoded
+ xorKey = (uint8_t)bytebits_to_byteLSBF(bits_no_spacer, 8);
+ for (size_t idx = 0; idx < 8; idx++) {
+ ByteStream[idx] = ((uint8_t)bytebits_to_byteLSBF(bits_no_spacer+8 + (idx*8),8)) ^ xorKey;
+ if (g_debugMode) PrintAndLog("byte %u after xor: %02x", (unsigned int)idx, ByteStream[idx]);
}
- //now ByteStream contains 64 bytes of decrypted raw tag data
+ //now ByteStream contains 8 Bytes (64 bits) of decrypted raw tag data
//
uint8_t fmtLen = ByteStream[0]>>2;
uint32_t FC = 0;
uint32_t Card = 0;
+ //get raw 96 bits to print
uint32_t raw1 = bytebits_to_byte(DemodBuffer+ans,32);
uint32_t raw2 = bytebits_to_byte(DemodBuffer+ans+32, 32);
uint32_t raw3 = bytebits_to_byte(DemodBuffer+ans+64, 32);
if (fmtLen==36){
FC = ((ByteStream[3] & 0x7F)<<7) | (ByteStream[4]>>1);
Card = ((ByteStream[4]&1)<<19) | (ByteStream[5]<<11) | (ByteStream[6]<<3) | (ByteStream[7]>>5);
- PrintAndLog("G-Prox-II Found: FmtLen %d, FC %d, Card %d",fmtLen,FC,Card);
+ PrintAndLog("G-Prox-II Found: FmtLen %d, FC %u, Card %u", (int)fmtLen, FC, Card);
} else if(fmtLen==26){
FC = ((ByteStream[3] & 0x7F)<<1) | (ByteStream[4]>>7);
Card = ((ByteStream[4]&0x7F)<<9) | (ByteStream[5]<<1) | (ByteStream[6]>>7);
- PrintAndLog("G-Prox-II Found: FmtLen %d, FC %d, Card %d",fmtLen,FC,Card);
+ PrintAndLog("G-Prox-II Found: FmtLen %d, FC %u, Card %u", (int)fmtLen, FC, Card);
} else {
- PrintAndLog("Unknown G-Prox-II Fmt Found: FmtLen %d",fmtLen);
+ PrintAndLog("Unknown G-Prox-II Fmt Found: FmtLen %d",(int)fmtLen);
+ PrintAndLog("Decoded Raw: %s", sprint_hex(ByteStream, 8));
}
PrintAndLog("Raw: %08x%08x%08x", raw1,raw2,raw3);
setDemodBuf(DemodBuffer+ans, 96, 0);
uint32_t raw2 = bytebits_to_byte(DemodBuffer+ans+32, 32);
uint32_t cardid = bytebits_to_byte(DemodBuffer+ans+24, 32);
uint8_t checksum = bytebits_to_byte(DemodBuffer+ans+32+24, 8);
- PrintAndLog("Viking Tag Found: Card ID %08X, Checksum: %02X", cardid, checksum);
+ PrintAndLog("Viking Tag Found: Card ID %08X, Checksum: %02X", cardid, (unsigned int) checksum);
PrintAndLog("Raw: %08X%08X", raw1,raw2);
setDemodBuf(DemodBuffer+ans, 64, 0);
return 1;
uint8_t factor = param_get8ex(Cmd, 0,2, 10);
//We have memory, don't we?
int swap[MAX_GRAPH_TRACE_LEN] = { 0 };
- uint32_t g_index = 0 ,s_index = 0;
- while(g_index < GraphTraceLen && s_index < MAX_GRAPH_TRACE_LEN)
+ uint32_t g_index = 0, s_index = 0;
+ while(g_index < GraphTraceLen && s_index + factor < MAX_GRAPH_TRACE_LEN)
{
int count = 0;
- for(count = 0; count < factor && s_index+count < MAX_GRAPH_TRACE_LEN; count ++)
+ for(count = 0; count < factor && s_index + count < MAX_GRAPH_TRACE_LEN; count++)
swap[s_index+count] = GraphBuffer[g_index];
- s_index+=count;
+
+ s_index += count;
+ g_index++;
}
- memcpy(GraphBuffer,swap, s_index * sizeof(int));
+ memcpy(GraphBuffer, swap, s_index * sizeof(int));
GraphTraceLen = s_index;
RepaintGraphWindow();
return 0;
int CmdAskEdgeDetect(const char *Cmd)
{
int thresLen = 25;
+ int Last = 0;
sscanf(Cmd, "%i", &thresLen);
for(int i = 1; i<GraphTraceLen; i++){
if (GraphBuffer[i]-GraphBuffer[i-1]>=thresLen) //large jump up
- GraphBuffer[i-1] = 127;
+ Last = 127;
else if(GraphBuffer[i]-GraphBuffer[i-1]<=-1*thresLen) //large jump down
- GraphBuffer[i-1] = -127;
+ Last = -127;
+ GraphBuffer[i-1] = Last;
}
RepaintGraphWindow();
return 0;
char *GetFSKType(uint8_t fchigh, uint8_t fclow, uint8_t invert)
{
- char *fskType;
+ static char fType[8];
+ memset(fType, 0x00, 8);
+ char *fskType = fType;
if (fchigh==10 && fclow==8){
if (invert) //fsk2a
- fskType = "FSK2a";
+ memcpy(fskType, "FSK2a", 5);
else //fsk2
- fskType = "FSK2";
+ memcpy(fskType, "FSK2", 4);
} else if (fchigh == 8 && fclow == 5) {
if (invert)
- fskType = "FSK1";
+ memcpy(fskType, "FSK1", 4);
else
- fskType = "FSK1a";
+ memcpy(fskType, "FSK1a", 5);
} else {
- fskType = "FSK??";
+ memcpy(fskType, "FSK??", 5);
}
return fskType;
}
invert = param_get8(Cmd, 1);
fchigh = param_get8(Cmd, 2);
fclow = param_get8(Cmd, 3);
+
if (strlen(Cmd)>0 && strlen(Cmd)<=2) {
- if (rfLen==1){
+ if (rfLen==1) {
invert = 1; //if invert option only is used
rfLen = 0;
- }
+ }
}
uint8_t BitStream[MAX_GRAPH_TRACE_LEN]={0};
size_t BitLen = getFromGraphBuf(BitStream);
if (BitLen==0) return 0;
//get field clock lengths
- uint8_t fc1=0, fc2=0, rf1=0;
+ uint16_t fcs=0;
if (!fchigh || !fclow) {
- uint8_t ans = fskClocks(&fc1, &fc2, &rf1, false);
- if (ans == 0) {
- if (g_debugMode) PrintAndLog("\nError: cannot detect valid fsk field clocks");
- return 0; // can't detect field clock
+ fcs = countFC(BitStream, BitLen, 1);
+ if (!fcs) {
+ fchigh = 10;
+ fclow = 8;
+ } else {
+ fchigh = (fcs >> 8) & 0x00FF;
+ fclow = fcs & 0x00FF;
}
- fchigh = fc1;
- fclow = fc2;
- if (rfLen == 0) rfLen = rf1;
}
//get bit clock length
- if (!rfLen){
+ if (!rfLen) {
rfLen = detectFSKClk(BitStream, BitLen, fchigh, fclow);
if (!rfLen) rfLen = 50;
}
int size = fskdemod(BitStream, BitLen, rfLen, invert, fchigh, fclow);
- if (size > 0){
+ if (size > 0) {
setDemodBuf(BitStream,size,0);
// Now output the bitstream to the scrollback by line of 16 bits
if (verbose || g_debugMode) {
- PrintAndLog("\nUsing Clock:%hu, invert:%hu, fchigh:%hu, fclow:%hu", rfLen, invert, fchigh, fclow);
+ PrintAndLog("\nUsing Clock:%u, invert:%u, fchigh:%u, fclow:%u", (unsigned int)rfLen, (unsigned int)invert, (unsigned int)fchigh, (unsigned int)fclow);
PrintAndLog("%s decoded bitstream:",GetFSKType(fchigh,fclow,invert));
printDemodBuff();
}
//get binary from fsk wave
int idx = AWIDdemodFSK(BitStream, &size);
if (idx<=0){
- if (g_debugMode==1){
+ if (g_debugMode){
if (idx == -1)
PrintAndLog("DEBUG: Error - not enough samples");
else if (idx == -2)
size = removeParity(BitStream, idx+8, 4, 1, 88);
if (size != 66){
- if (g_debugMode==1) PrintAndLog("DEBUG: Error - at parity check-tag size does not match AWID format");
+ if (g_debugMode) PrintAndLog("DEBUG: Error - at parity check-tag size does not match AWID format");
return 0;
}
// ok valid card found!
//get binary from fsk wave
int idx = PyramiddemodFSK(BitStream, &size);
if (idx < 0){
- if (g_debugMode==1){
+ if (g_debugMode){
if (idx == -5)
PrintAndLog("DEBUG: Error - not enough samples");
else if (idx == -1)
size = removeParity(BitStream, idx+8, 8, 1, 120);
if (size != 105){
- if (g_debugMode==1)
+ if (g_debugMode)
PrintAndLog("DEBUG: Error at parity check - tag size does not match Pyramid format, SIZE: %d, IDX: %d, hi3: %x",size, idx, rawHi3);
return 0;
}
}
if (!ans){
- if (g_debugMode==1)
+ if (g_debugMode)
PrintAndLog("Error1: %d",ans);
return 0;
}
uint8_t invert=0;
size_t size = DemodBufferLen;
- size_t startIdx = indala26decode(DemodBuffer, &size, &invert);
- if (startIdx < 1 || size > 224) {
- if (g_debugMode==1)
+ int startIdx = indala26decode(DemodBuffer, &size, &invert);
+ if (startIdx < 0 || size > 224) {
+ if (g_debugMode)
PrintAndLog("Error2: %d",ans);
return -1;
}
- setDemodBuf(DemodBuffer, size, startIdx);
+ setDemodBuf(DemodBuffer, size, (size_t)startIdx);
if (invert)
- if (g_debugMode==1)
+ if (g_debugMode)
PrintAndLog("Had to invert bits");
PrintAndLog("BitLen: %d",DemodBufferLen);
int CmdTuneSamples(const char *Cmd)
{
- int timeout = 0;
+ int timeout = 0, arg = FLAG_TUNE_ALL;
+
+ if(*Cmd == 'l') {
+ arg = FLAG_TUNE_LF;
+ } else if (*Cmd == 'h') {
+ arg = FLAG_TUNE_HF;
+ } else if (*Cmd != '\0') {
+ PrintAndLog("use 'tune' or 'tune l' or 'tune h'");
+ return 0;
+ }
+
printf("\nMeasuring antenna characteristics, please wait...");
- UsbCommand c = {CMD_MEASURE_ANTENNA_TUNING};
+ UsbCommand c = {CMD_MEASURE_ANTENNA_TUNING, {arg, 0, 0}};
SendCommand(&c);
UsbCommand resp;
return 0;
}
-int usage_data_hex2bin(){
-
- PrintAndLog("Usage: data bin2hex <binary_digits>");
+int usage_data_hex2bin() {
+ PrintAndLog("Usage: data hex2bin <hex_digits>");
PrintAndLog(" This function will ignore all non-hexadecimal characters (but stop reading on whitespace)");
return 0;
#ifndef CMDDATA_H__
#define CMDDATA_H__
+#include <stdlib.h> //size_t
+#include <stdint.h> //uint_32+
+#include <stdbool.h> //bool
+
+#include "cmdparser.h" // for command_t
+
command_t * CmdDataCommands();
int CmdData(const char *Cmd);
int AskEm410xDemod(const char *Cmd, uint32_t *hi, uint64_t *lo, bool verbose);
int ASKbiphaseDemod(const char *Cmd, bool verbose);
int ASKDemod(const char *Cmd, bool verbose, bool emSearch, uint8_t askType);
+int ASKDemod_ext(const char *Cmd, bool verbose, bool emSearch, uint8_t askType, bool *stCheck);
int FSKrawDemod(const char *Cmd, bool verbose);
int PSKDemod(const char *Cmd, bool verbose);
int NRZrawDemod(const char *Cmd, bool verbose);
c.arg[2] = 13560000 / 1000 / (8*16) * timeout; // timeout in ETUs (time to transfer 1 bit, approx. 9.4 us)
}
- if(power)
+ if(power) {
c.arg[0] |= ISO14A_NO_DISCONNECT;
+ }
- if(datalen > 0)
+ if(datalen > 0) {
c.arg[0] |= ISO14A_RAW;
+ }
- if(topazmode)
+ if(topazmode) {
c.arg[0] |= ISO14A_TOPAZMODE;
+ }
// Max buffer is USB_CMD_DATA_SIZE
c.arg[1] = (datalen & 0xFFFF) | (numbits << 16);
//-----------------------------------------------------------------------------\r
\r
#include "cmdhfmf.h"\r
+#include "./nonce2key/nonce2key.h"\r
\r
static int CmdHelp(const char *Cmd);\r
\r
printf("-------------------------------------------------------------------------\n");\r
\r
\r
-start:\r
+ start:\r
clearCommandBuffer();\r
SendCommand(&c);\r
\r
return 0;\r
}\r
\r
-int CmdHF14AMf1kSim(const char *Cmd)\r
-{\r
- uint8_t uid[7] = {0, 0, 0, 0, 0, 0, 0};\r
+void readerAttack(nonces_t ar_resp[], bool setEmulatorMem) {\r
+ #define ATTACK_KEY_COUNT 8 // keep same as define in iso14443a.c -> Mifare1ksim()\r
+ uint64_t key = 0;\r
+ typedef struct {\r
+ uint64_t keyA;\r
+ uint64_t keyB;\r
+ } st_t;\r
+ st_t sector_trailer[ATTACK_KEY_COUNT];\r
+ memset(sector_trailer, 0x00, sizeof(sector_trailer));\r
+\r
+ uint8_t stSector[ATTACK_KEY_COUNT];\r
+ memset(stSector, 0x00, sizeof(stSector));\r
+ uint8_t key_cnt[ATTACK_KEY_COUNT];\r
+ memset(key_cnt, 0x00, sizeof(key_cnt));\r
+\r
+ for (uint8_t i = 0; i<ATTACK_KEY_COUNT; i++) {\r
+ if (ar_resp[i].ar2 > 0) {\r
+ //PrintAndLog("DEBUG: Trying sector %d, cuid %08x, nt %08x, ar %08x, nr %08x, ar2 %08x, nr2 %08x",ar_resp[i].sector, ar_resp[i].cuid,ar_resp[i].nonce,ar_resp[i].ar,ar_resp[i].nr,ar_resp[i].ar2,ar_resp[i].nr2);\r
+ if (mfkey32(ar_resp[i], &key)) {\r
+ PrintAndLog(" Found Key%s for sector %02d: [%04x%08x]", (ar_resp[i].keytype) ? "B" : "A", ar_resp[i].sector, (uint32_t) (key>>32), (uint32_t) (key &0xFFFFFFFF));\r
+\r
+ for (uint8_t ii = 0; ii<ATTACK_KEY_COUNT; ii++) {\r
+ if (key_cnt[ii]==0 || stSector[ii]==ar_resp[i].sector) {\r
+ if (ar_resp[i].keytype==0) {\r
+ //keyA\r
+ sector_trailer[ii].keyA = key;\r
+ stSector[ii] = ar_resp[i].sector;\r
+ key_cnt[ii]++;\r
+ break;\r
+ } else {\r
+ //keyB\r
+ sector_trailer[ii].keyB = key;\r
+ stSector[ii] = ar_resp[i].sector;\r
+ key_cnt[ii]++;\r
+ break;\r
+ }\r
+ }\r
+ }\r
+ }\r
+ }\r
+ }\r
+ //set emulator memory for keys\r
+ if (setEmulatorMem) {\r
+ for (uint8_t i = 0; i<ATTACK_KEY_COUNT; i++) {\r
+ if (key_cnt[i]>0) {\r
+ uint8_t memBlock[16];\r
+ memset(memBlock, 0x00, sizeof(memBlock));\r
+ char cmd1[36];\r
+ memset(cmd1,0x00,sizeof(cmd1));\r
+ snprintf(cmd1,sizeof(cmd1),"%04x%08xFF078069%04x%08x",(uint32_t) (sector_trailer[i].keyA>>32), (uint32_t) (sector_trailer[i].keyA &0xFFFFFFFF),(uint32_t) (sector_trailer[i].keyB>>32), (uint32_t) (sector_trailer[i].keyB &0xFFFFFFFF));\r
+ PrintAndLog("Setting Emulator Memory Block %02d: [%s]",stSector[i]*4+3, cmd1);\r
+ if (param_gethex(cmd1, 0, memBlock, 32)) {\r
+ PrintAndLog("block data must include 32 HEX symbols");\r
+ return;\r
+ }\r
+ \r
+ UsbCommand c = {CMD_MIFARE_EML_MEMSET, {(stSector[i]*4+3), 1, 0}};\r
+ memcpy(c.d.asBytes, memBlock, 16);\r
+ clearCommandBuffer();\r
+ SendCommand(&c); \r
+ }\r
+ }\r
+ }\r
+ /*\r
+ //un-comment to use as well moebius attack\r
+ for (uint8_t i = ATTACK_KEY_COUNT; i<ATTACK_KEY_COUNT*2; i++) {\r
+ if (ar_resp[i].ar2 > 0) {\r
+ if (tryMfk32_moebius(ar_resp[i], &key)) {\r
+ PrintAndLog("M-Found Key%s for sector %02d: [%04x%08x]", (ar_resp[i].keytype) ? "B" : "A", ar_resp[i].sector, (uint32_t) (key>>32), (uint32_t) (key &0xFFFFFFFF));\r
+ }\r
+ }\r
+ }*/\r
+}\r
+\r
+int usage_hf14_mf1ksim(void) {\r
+ PrintAndLog("Usage: hf mf sim h u <uid (8, 14, or 20 hex symbols)> n <numreads> i x");\r
+ PrintAndLog("options:");\r
+ PrintAndLog(" h this help");\r
+ PrintAndLog(" u (Optional) UID 4,7 or 10 bytes. If not specified, the UID 4B from emulator memory will be used");\r
+ PrintAndLog(" n (Optional) Automatically exit simulation after <numreads> blocks have been read by reader. 0 = infinite");\r
+ PrintAndLog(" i (Optional) Interactive, means that console will not be returned until simulation finishes or is aborted");\r
+ PrintAndLog(" x (Optional) Crack, performs the 'reader attack', nr/ar attack against a legitimate reader, fishes out the key(s)");\r
+ PrintAndLog(" e (Optional) set keys found from 'reader attack' to emulator memory (implies x and i)");\r
+ PrintAndLog(" f (Optional) get UIDs to use for 'reader attack' from file 'f <filename.txt>' (implies x and i)");\r
+ PrintAndLog("samples:");\r
+ PrintAndLog(" hf mf sim u 0a0a0a0a");\r
+ PrintAndLog(" hf mf sim u 11223344556677");\r
+ PrintAndLog(" hf mf sim u 112233445566778899AA");\r
+ PrintAndLog(" hf mf sim f uids.txt");\r
+ PrintAndLog(" hf mf sim u 0a0a0a0a e");\r
+ \r
+ return 0;\r
+}\r
+\r
+int CmdHF14AMf1kSim(const char *Cmd) {\r
+ UsbCommand resp;\r
+ uint8_t uid[10] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0};\r
uint8_t exitAfterNReads = 0;\r
uint8_t flags = 0;\r
-\r
- uint8_t cmdp = param_getchar(Cmd, 0);\r
- \r
- if (cmdp == 'h' || cmdp == 'H') {\r
- PrintAndLog("Usage: hf mf sim u <uid (8 hex symbols)> n <numreads> i x");\r
- PrintAndLog(" h this help");\r
- PrintAndLog(" u (Optional) UID. If not specified, the UID from emulator memory will be used");\r
- PrintAndLog(" n (Optional) Automatically exit simulation after <numreads> blocks have been read by reader. 0 = infinite");\r
- PrintAndLog(" i (Optional) Interactive, means that console will not be returned until simulation finishes or is aborted");\r
- PrintAndLog(" x (Optional) Crack, performs the 'reader attack', nr/ar attack against a legitimate reader, fishes out the key(s)");\r
- PrintAndLog("");\r
- PrintAndLog(" sample: hf mf sim u 0a0a0a0a ");\r
- return 0;\r
- }\r
+ int uidlen = 0;\r
uint8_t pnr = 0;\r
- if (param_getchar(Cmd, pnr) == 'u') {\r
- if(param_gethex(Cmd, pnr+1, uid, 8) == 0)\r
- {\r
- flags |= FLAG_4B_UID_IN_DATA; // UID from packet\r
- } else if(param_gethex(Cmd,pnr+1,uid,14) == 0) {\r
- flags |= FLAG_7B_UID_IN_DATA;// UID from packet\r
- } else {\r
- PrintAndLog("UID, if specified, must include 8 or 14 HEX symbols");\r
- return 1;\r
+ bool setEmulatorMem = false;\r
+ bool attackFromFile = false;\r
+ FILE *f;\r
+ char filename[FILE_PATH_SIZE];\r
+ memset(filename, 0x00, sizeof(filename));\r
+ int len = 0;\r
+ char buf[64];\r
+\r
+ uint8_t cmdp = 0;\r
+ bool errors = false;\r
+\r
+ while(param_getchar(Cmd, cmdp) != 0x00) {\r
+ switch(param_getchar(Cmd, cmdp)) {\r
+ case 'e':\r
+ case 'E':\r
+ setEmulatorMem = true;\r
+ //implies x and i\r
+ flags |= FLAG_INTERACTIVE;\r
+ flags |= FLAG_NR_AR_ATTACK;\r
+ cmdp++;\r
+ break;\r
+ case 'f':\r
+ case 'F':\r
+ len = param_getstr(Cmd, cmdp+1, filename);\r
+ if (len < 1) {\r
+ PrintAndLog("error no filename found");\r
+ return 0;\r
+ }\r
+ attackFromFile = true;\r
+ //implies x and i\r
+ flags |= FLAG_INTERACTIVE;\r
+ flags |= FLAG_NR_AR_ATTACK;\r
+ cmdp += 2;\r
+ break;\r
+ case 'h':\r
+ case 'H':\r
+ return usage_hf14_mf1ksim();\r
+ case 'i':\r
+ case 'I':\r
+ flags |= FLAG_INTERACTIVE;\r
+ cmdp++;\r
+ break;\r
+ case 'n':\r
+ case 'N':\r
+ exitAfterNReads = param_get8(Cmd, pnr+1);\r
+ cmdp += 2;\r
+ break;\r
+ case 'u':\r
+ case 'U':\r
+ param_gethex_ex(Cmd, cmdp+1, uid, &uidlen);\r
+ switch(uidlen) {\r
+ case 20: flags = FLAG_10B_UID_IN_DATA; break; //not complete\r
+ case 14: flags = FLAG_7B_UID_IN_DATA; break;\r
+ case 8: flags = FLAG_4B_UID_IN_DATA; break;\r
+ default: return usage_hf14_mf1ksim();\r
+ }\r
+ cmdp += 2;\r
+ break;\r
+ case 'x':\r
+ case 'X':\r
+ flags |= FLAG_NR_AR_ATTACK;\r
+ cmdp++;\r
+ break;\r
+ default:\r
+ PrintAndLog("Unknown parameter '%c'", param_getchar(Cmd, cmdp));\r
+ errors = true;\r
+ break;\r
}\r
- pnr +=2;\r
- }\r
- if (param_getchar(Cmd, pnr) == 'n') {\r
- exitAfterNReads = param_get8(Cmd,pnr+1);\r
- pnr += 2;\r
- }\r
- if (param_getchar(Cmd, pnr) == 'i' ) {\r
- //Using a flag to signal interactiveness, least significant bit\r
- flags |= FLAG_INTERACTIVE;\r
- pnr++;\r
+ if(errors) break;\r
}\r
+ //Validations\r
+ if(errors) return usage_hf14_mf1ksim();\r
\r
- if (param_getchar(Cmd, pnr) == 'x' ) {\r
- //Using a flag to signal interactiveness, least significant bit\r
- flags |= FLAG_NR_AR_ATTACK;\r
- }\r
- PrintAndLog(" uid:%s, numreads:%d, flags:%d (0x%02x) ",\r
- flags & FLAG_4B_UID_IN_DATA ? sprint_hex(uid,4):\r
- flags & FLAG_7B_UID_IN_DATA ? sprint_hex(uid,7): "N/A"\r
- , exitAfterNReads, flags,flags);\r
+ //get uid from file\r
+ if (attackFromFile) {\r
+ int count = 0;\r
+ // open file\r
+ f = fopen(filename, "r");\r
+ if (f == NULL) {\r
+ PrintAndLog("File %s not found or locked", filename);\r
+ return 1;\r
+ }\r
+ PrintAndLog("Loading file and simulating. Press keyboard to abort");\r
+ while(!feof(f) && !ukbhit()){\r
+ memset(buf, 0, sizeof(buf));\r
+ memset(uid, 0, sizeof(uid));\r
\r
+ if (fgets(buf, sizeof(buf), f) == NULL) { \r
+ if (count > 0) break;\r
+ \r
+ PrintAndLog("File reading error.");\r
+ fclose(f);\r
+ return 2;\r
+ }\r
+ if(!strlen(buf) && feof(f)) break;\r
+\r
+ uidlen = strlen(buf)-1;\r
+ switch(uidlen) {\r
+ case 20: flags |= FLAG_10B_UID_IN_DATA; break; //not complete\r
+ case 14: flags |= FLAG_7B_UID_IN_DATA; break;\r
+ case 8: flags |= FLAG_4B_UID_IN_DATA; break;\r
+ default: \r
+ PrintAndLog("uid in file wrong length at %d (length: %d) [%s]",count, uidlen, buf);\r
+ fclose(f);\r
+ return 2;\r
+ }\r
\r
- UsbCommand c = {CMD_SIMULATE_MIFARE_CARD, {flags, exitAfterNReads,0}};\r
- memcpy(c.d.asBytes, uid, sizeof(uid));\r
- SendCommand(&c);\r
+ for (uint8_t i = 0; i < uidlen; i += 2) {\r
+ sscanf(&buf[i], "%02x", (unsigned int *)&uid[i / 2]);\r
+ }\r
+ \r
+ PrintAndLog("mf 1k sim uid: %s, numreads:%d, flags:%d (0x%02x) - press button to abort",\r
+ flags & FLAG_4B_UID_IN_DATA ? sprint_hex(uid,4):\r
+ flags & FLAG_7B_UID_IN_DATA ? sprint_hex(uid,7): \r
+ flags & FLAG_10B_UID_IN_DATA ? sprint_hex(uid,10): "N/A"\r
+ , exitAfterNReads, flags, flags);\r
+\r
+ UsbCommand c = {CMD_SIMULATE_MIFARE_CARD, {flags, exitAfterNReads,0}};\r
+ memcpy(c.d.asBytes, uid, sizeof(uid));\r
+ clearCommandBuffer();\r
+ SendCommand(&c);\r
\r
- if(flags & FLAG_INTERACTIVE)\r
- {\r
- UsbCommand resp;\r
- PrintAndLog("Press pm3-button to abort simulation");\r
- while(! WaitForResponseTimeout(CMD_ACK,&resp,1500)) {\r
- //We're waiting only 1.5 s at a time, otherwise we get the\r
- // annoying message about "Waiting for a response... "\r
+ while(! WaitForResponseTimeout(CMD_ACK,&resp,1500)) {\r
+ //We're waiting only 1.5 s at a time, otherwise we get the\r
+ // annoying message about "Waiting for a response... "\r
+ }\r
+ //got a response\r
+ nonces_t ar_resp[ATTACK_KEY_COUNT*2];\r
+ memcpy(ar_resp, resp.d.asBytes, sizeof(ar_resp));\r
+ readerAttack(ar_resp, setEmulatorMem);\r
+ if ((bool)resp.arg[1]) {\r
+ PrintAndLog("Device button pressed - quitting");\r
+ fclose(f);\r
+ return 4;\r
+ }\r
+ count++;\r
+ }\r
+ fclose(f);\r
+ } else { //not from file\r
+\r
+ PrintAndLog("mf 1k sim uid: %s, numreads:%d, flags:%d (0x%02x) ",\r
+ flags & FLAG_4B_UID_IN_DATA ? sprint_hex(uid,4):\r
+ flags & FLAG_7B_UID_IN_DATA ? sprint_hex(uid,7): \r
+ flags & FLAG_10B_UID_IN_DATA ? sprint_hex(uid,10): "N/A"\r
+ , exitAfterNReads, flags, flags);\r
+\r
+ UsbCommand c = {CMD_SIMULATE_MIFARE_CARD, {flags, exitAfterNReads,0}};\r
+ memcpy(c.d.asBytes, uid, sizeof(uid));\r
+ clearCommandBuffer();\r
+ SendCommand(&c);\r
+\r
+ if(flags & FLAG_INTERACTIVE) {\r
+ PrintAndLog("Press pm3-button to abort simulation");\r
+ while(! WaitForResponseTimeout(CMD_ACK,&resp,1500)) {\r
+ //We're waiting only 1.5 s at a time, otherwise we get the\r
+ // annoying message about "Waiting for a response... "\r
+ }\r
+ //got a response\r
+ if (flags & FLAG_NR_AR_ATTACK) {\r
+ nonces_t ar_resp[ATTACK_KEY_COUNT*2];\r
+ memcpy(ar_resp, resp.d.asBytes, sizeof(ar_resp));\r
+ readerAttack(ar_resp, setEmulatorMem);\r
+ }\r
}\r
}\r
- \r
+\r
return 0;\r
}\r
\r
{"reset", CmdReset, 0, "Reset the Proxmark3"},
{"setlfdivisor", CmdSetDivisor, 0, "<19 - 255> -- Drive LF antenna at 12Mhz/(divisor+1)"},
{"setmux", CmdSetMux, 0, "<loraw|hiraw|lopkd|hipkd> -- Set the ADC mux to a specific value"},
- {"tune", CmdTune, 0, "Measure antenna tuning"},
+ {"tune", CmdTune, 0, "['l'|'h'] -- Measure antenna tuning (option 'l' or 'h' to limit to LF or HF)"},
{"version", CmdVersion, 0, "Show version information about the connected Proxmark"},
{"status", CmdStatus, 0, "Show runtime status information about the connected Proxmark"},
{"ping", CmdPing, 0, "Test if the pm3 is responsive"},
#include <string.h>
#include <limits.h>
#include "proxmark3.h"
-#include "data.h"
-#include "graph.h"
-#include "ui.h"
-#include "cmdparser.h"
-#include "cmdmain.h"
-#include "cmddata.h"
-#include "util.h"
#include "cmdlf.h"
-#include "cmdlfhid.h"
-#include "cmdlfawid.h"
-#include "cmdlfti.h"
-#include "cmdlfem4x.h"
-#include "cmdlfhitag.h"
-#include "cmdlft55xx.h"
-#include "cmdlfpcf7931.h"
-#include "cmdlfio.h"
-#include "cmdlfviking.h"
-#include "lfdemod.h"
+#include "lfdemod.h" // for psk2TOpsk1
+#include "util.h" // for parsing cli command utils
+#include "ui.h" // for show graph controls
+#include "graph.h" // for graph data
+#include "cmdparser.h" // for getting cli commands included in cmdmain.h
+#include "cmdmain.h" // for sending cmds to device
+#include "data.h" // for GetFromBigBuf
+#include "cmddata.h" // for `lf search`
+#include "cmdlfawid.h" // for awid menu
+#include "cmdlfem4x.h" // for em4x menu
+#include "cmdlfhid.h" // for hid menu
+#include "cmdlfhitag.h" // for hitag menu
+#include "cmdlfio.h" // for ioprox menu
+#include "cmdlft55xx.h" // for t55xx menu
+#include "cmdlfti.h" // for ti menu
+#include "cmdlfpresco.h" // for presco menu
+#include "cmdlfpcf7931.h"// for pcf7931 menu
+#include "cmdlfpyramid.h"// for pyramid menu
+#include "cmdlfviking.h" // for viking menu
static int CmdHelp(const char *Cmd);
bool errors = FALSE;
//uint8_t divisor = 95; //125khz
uint8_t cmdp = 0;
- int strLength = 0;
while(param_getchar(Cmd, cmdp) != 0x00)
{
switch(param_getchar(Cmd, cmdp))
cmdp++;
break;
case 'c':
- strLength = param_getstr(Cmd, cmdp+1, (char *)&c.d.asBytes);
+ param_getstr(Cmd, cmdp+1, (char *)&c.d.asBytes);
cmdp+=2;
break;
case 'd':
return usage_lf_config();
}
//Bps is limited to 8, so fits in lower half of arg1
- if(bps >> 8) bps = 8;
+ if(bps >> 4) bps = 8;
sample_config config = {
decimation,bps,averaging,divisor,trigger_threshold
PrintAndLog(" b sim ask/biphase");
PrintAndLog(" m sim ask/manchester - Default");
PrintAndLog(" r sim ask/raw");
- PrintAndLog(" s TBD- -to enable a gap between playback repetitions - default: no gap");
+ PrintAndLog(" s add t55xx Sequence Terminator gap - default: no gaps (only manchester)");
PrintAndLog(" d <hexdata> Data to sim as hex - omit to sim from DemodBuffer");
return 0;
}
return 1;
}
}
- ans=ASKDemod("0 0 0",TRUE,FALSE,1);
+ bool st = TRUE;
+ ans=ASKDemod_ext("0 0 0",TRUE,FALSE,1,&st);
if (ans>0) {
PrintAndLog("\nUnknown ASK Modulated and Manchester encoded Tag Found!");
PrintAndLog("\nif it does not look right it could instead be ASK/Biphase - try 'data rawdemod ab'");
{"hid", CmdLFHID, 1, "{ HID RFIDs... }"},
{"hitag", CmdLFHitag, 1, "{ Hitag tags and transponders... }"},
{"io", CmdLFIO, 1, "{ ioProx tags... }"},
+ {"presco", CmdLFPresco, 1, "{ Presco RFIDs... }"},
{"pcf7931", CmdLFPCF7931, 1, "{ PCF7931 RFIDs... }"},
+ {"pyramid", CmdLFPyramid, 1, "{ Farpointe/Pyramid RFIDs... }"},
{"t55xx", CmdLFT55XX, 1, "{ T55xx RFIDs... }"},
{"ti", CmdLFTI, 1, "{ TI RFIDs... }"},
{"viking", CmdLFViking, 1, "{ Viking tags... }"},
#include "common.h"
#include "util.h"
#include "hitag2.h"
+#include "hitagS.h"
#include "sleep.h"
#include "cmdmain.h"
}
int CmdLFHitagReader(const char *Cmd) {
-// UsbCommand c = {CMD_READER_HITAG};
-
-// param_get32ex(Cmd,1,0,16);
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)}};
hitag_data* htd = (hitag_data*)c.d.asBytes;
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);
+ } break;
+ case 02: { //RHTSF_KEY
+ c = (UsbCommand){ CMD_READ_HITAG_S };
+ num_to_bytes(param_get64ex(Cmd,1,0,16),6,htd->crypto.key);
+ } break;
case RHT2F_PASSWORD: {
num_to_bytes(param_get32ex(Cmd,1,0,16),4,htd->pwd.password);
} break;
PrintAndLog("Error: unkown reader function %d",htf);
PrintAndLog("Hitag reader functions");
PrintAndLog(" HitagS (0*)");
+ PrintAndLog(" 01 <nr> <ar> (Challenge) read all pages from a Hitag S tag");
+ PrintAndLog(" 02 <key> (set to 0 if no authentication is needed) read all pages from a Hitag S tag");
PrintAndLog(" Hitag1 (1*)");
PrintAndLog(" Hitag2 (2*)");
PrintAndLog(" 21 <password> (password mode)");
return 0;
}
+
+int CmdLFHitagSimS(const char *Cmd) {
+ UsbCommand c = { CMD_SIMULATE_HITAG_S };
+ 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);
+ return 1;
+ }
+ tag_mem_supplied = true;
+ if (fread(c.d.asBytes, 4*64, 1, pf) == 0) {
+ PrintAndLog("Error: File reading error");
+ fclose(pf);
+ return 1;
+ }
+ fclose(pf);
+ } else {
+ tag_mem_supplied = false;
+ }
+
+ // Does the tag comes with memory
+ c.arg[0] = (uint32_t) tag_mem_supplied;
+
+ SendCommand(&c);
+ return 0;
+}
+
+int CmdLFHitagCheckChallenges(const char *Cmd) {
+ UsbCommand c = { CMD_TEST_HITAGS_TRACES };
+ char filename[FILE_PATH_SIZE] = { 0x00 };
+ FILE* pf;
+ bool file_given;
+ 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);
+ return 1;
+ }
+ file_given = true;
+ if (fread(c.d.asBytes,8*60,1,pf) == 0) {
+ 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;
+
+ SendCommand(&c);
+ return 0;
+}
+
+
+int CmdLFHitagWP(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
+ 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: { //WHTSF_KEY
+ 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;
+ 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*)");
+ 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;
+}
+
+
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"},
- {NULL, NULL, 0, NULL}
+ {"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> test all challenges" }, {
+ NULL,NULL, 0, NULL }
};
int CmdLFHitag(const char *Cmd)
--- /dev/null
+//-----------------------------------------------------------------------------
+//
+// This code is licensed to you under the terms of the GNU GPL, version 2 or,
+// at your option, any later version. See the LICENSE.txt file for the text of
+// the license.
+//-----------------------------------------------------------------------------
+// Low frequency Presco tag commands
+//-----------------------------------------------------------------------------
+#include <string.h>
+#include <inttypes.h>
+#include "cmdlfpresco.h"
+#include "proxmark3.h"
+#include "ui.h"
+#include "util.h"
+#include "graph.h"
+#include "cmdparser.h"
+#include "cmddata.h"
+#include "cmdmain.h"
+#include "cmdlf.h"
+#include "protocols.h" // for T55xx config register definitions
+#include "lfdemod.h" // parityTest
+
+static int CmdHelp(const char *Cmd);
+
+int usage_lf_presco_clone(void){
+ PrintAndLog("clone a Presco tag to a T55x7 tag.");
+ PrintAndLog("Usage: lf presco clone d <Card-ID> H <hex-ID> <Q5>");
+ PrintAndLog("Options :");
+ PrintAndLog(" d <Card-ID> : 9 digit presco card ID");
+ PrintAndLog(" H <hex-ID> : 8 digit hex card number");
+ PrintAndLog(" <Q5> : specify write to Q5 (t5555 instead of t55x7)");
+ PrintAndLog("");
+ PrintAndLog("Sample : lf presco clone d 123456789");
+ return 0;
+}
+
+int usage_lf_presco_sim(void) {
+ PrintAndLog("Enables simulation of presco card with specified card number.");
+ PrintAndLog("Simulation runs until the button is pressed or another USB command is issued.");
+ PrintAndLog("Per presco format, the card number is 9 digit number and can contain *# chars. Larger values are truncated.");
+ PrintAndLog("");
+ PrintAndLog("Usage: lf presco sim d <Card-ID> or H <hex-ID>");
+ PrintAndLog("Options :");
+ PrintAndLog(" d <Card-ID> : 9 digit presco card number");
+ PrintAndLog(" H <hex-ID> : 8 digit hex card number");
+ PrintAndLog("");
+ PrintAndLog("Sample : lf presco sim d 123456789");
+ return 0;
+}
+
+// convert base 12 ID to sitecode & usercode & 8 bit other unknown code
+int GetWiegandFromPresco(const char *Cmd, uint32_t *sitecode, uint32_t *usercode, uint32_t *fullcode, bool *Q5) {
+
+ uint8_t val = 0;
+ bool hex = false, errors = false;
+ uint8_t cmdp = 0;
+ char id[11];
+ int stringlen = 0;
+ while(param_getchar(Cmd, cmdp) != 0x00) {
+ switch(param_getchar(Cmd, cmdp)) {
+ case 'h':
+ return -1;
+ case 'H':
+ hex = true;
+ //get hex
+ *fullcode = param_get32ex(Cmd, cmdp+1, 0, 10);
+ cmdp+=2;
+ break;
+ case 'P':
+ case 'p':
+ //param get string int param_getstr(const char *line, int paramnum, char * str)
+ stringlen = param_getstr(Cmd, cmdp+1, id);
+ if (stringlen < 2) return -1;
+ cmdp+=2;
+ break;
+ case 'Q':
+ case 'q':
+ *Q5 = true;
+ cmdp++;
+ break;
+ default:
+ PrintAndLog("Unknown parameter '%c'", param_getchar(Cmd, cmdp));
+ errors = 1;
+ break;
+ }
+ if(errors) break;
+ }
+ // No args
+ if(cmdp == 0) errors = 1;
+
+ //Validations
+ if(errors) return -1;
+
+ if (!hex) {
+ for (int index =0; index < strlen(id); ++index) {
+ // Get value from number string.
+ if ( id[index] == '*' ) val = 10;
+ if ( id[index] == '#') val = 11;
+ if ( id[index] >= 0x30 && id[index] <= 0x39 )
+ val = id[index] - 0x30;
+
+ *fullcode += val;
+
+ // last digit is only added, not multipled.
+ if ( index < strlen(id)-1 )
+ *fullcode *= 12;
+ }
+ }
+
+ *usercode = *fullcode & 0x0000FFFF; //% 65566
+ *sitecode = (*fullcode >> 24) & 0x000000FF; // /= 16777216;
+ return 0;
+}
+
+// calc not certain - intended to get bitstream for programming / sim
+int GetPrescoBits(uint32_t fullcode, uint8_t *prescoBits) {
+ num_to_bytebits(0x10D00000, 32, prescoBits);
+ num_to_bytebits(0x00000000, 32, prescoBits+32);
+ num_to_bytebits(0x00000000, 32, prescoBits+64);
+ num_to_bytebits(fullcode , 32, prescoBits+96);
+ return 1;
+}
+
+//see ASKDemod for what args are accepted
+int CmdPrescoDemod(const char *Cmd) {
+ if (!ASKDemod(Cmd, false, false, 1)) {
+ if (g_debugMode) PrintAndLog("ASKDemod failed");
+ return 0;
+ }
+ size_t size = DemodBufferLen;
+ //call lfdemod.c demod for Viking
+ int ans = PrescoDemod(DemodBuffer, &size);
+ if (ans < 0) {
+ if (g_debugMode) PrintAndLog("Error Presco_Demod %d", ans);
+ return 0;
+ }
+ //got a good demod
+ uint32_t raw1 = bytebits_to_byte(DemodBuffer+ans, 32);
+ uint32_t raw2 = bytebits_to_byte(DemodBuffer+ans+32, 32);
+ uint32_t raw3 = bytebits_to_byte(DemodBuffer+ans+64, 32);
+ uint32_t raw4 = bytebits_to_byte(DemodBuffer+ans+96, 32);
+ uint32_t cardid = raw4;
+ PrintAndLog("Presco Tag Found: Card ID %08X", cardid);
+ PrintAndLog("Raw: %08X%08X%08X%08X", raw1,raw2,raw3,raw4);
+ setDemodBuf(DemodBuffer+ans, 128, 0);
+
+ uint32_t sitecode = 0, usercode = 0, fullcode = 0;
+ bool Q5=false;
+ char cmd[12] = {0};
+ sprintf(cmd, "H %08X", cardid);
+ GetWiegandFromPresco(cmd, &sitecode, &usercode, &fullcode, &Q5);
+ PrintAndLog("SiteCode %u, UserCode %u, FullCode, %08X", sitecode, usercode, fullcode);
+
+ return 1;
+}
+
+//see ASKDemod for what args are accepted
+int CmdPrescoRead(const char *Cmd) {
+ // Presco Number: 123456789 --> Sitecode 30 | usercode 8665
+
+ // read lf silently
+ CmdLFRead("s");
+ // get samples silently
+ getSamples("30000",false);
+ // demod and output Presco ID
+ return CmdPrescoDemod(Cmd);
+}
+
+// takes base 12 ID converts to hex
+// Or takes 8 digit hex ID
+int CmdPrescoClone(const char *Cmd) {
+
+ bool Q5 = false;
+ uint32_t sitecode=0, usercode=0, fullcode=0;
+ uint32_t blocks[5] = {T55x7_MODULATION_MANCHESTER | T55x7_BITRATE_RF_32 | 4<<T55x7_MAXBLOCK_SHIFT | T55x7_ST_TERMINATOR, 0, 0, 0, 5};
+
+ // get wiegand from printed number.
+ if (GetWiegandFromPresco(Cmd, &sitecode, &usercode, &fullcode, &Q5) == -1) return usage_lf_presco_clone();
+
+ if (Q5)
+ blocks[0] = T5555_MODULATION_MANCHESTER | 32<<T5555_BITRATE_SHIFT | 4<<T5555_MAXBLOCK_SHIFT | T5555_ST_TERMINATOR;
+
+ if ((sitecode & 0xFF) != sitecode) {
+ sitecode &= 0xFF;
+ PrintAndLog("Facility-Code Truncated to 8-bits (Presco): %u", sitecode);
+ }
+
+ if ((usercode & 0xFFFF) != usercode) {
+ usercode &= 0xFFFF;
+ PrintAndLog("Card Number Truncated to 16-bits (Presco): %u", usercode);
+ }
+
+ blocks[1] = 0x10D00000; //preamble
+ blocks[2] = 0x00000000;
+ blocks[3] = 0x00000000;
+ blocks[4] = fullcode;
+
+ PrintAndLog("Preparing to clone Presco to T55x7 with SiteCode: %u, UserCode: %u, FullCode: %08x", sitecode, usercode, fullcode);
+ PrintAndLog("Blk | Data ");
+ PrintAndLog("----+------------");
+ PrintAndLog(" 00 | 0x%08x", blocks[0]);
+ PrintAndLog(" 01 | 0x%08x", blocks[1]);
+ PrintAndLog(" 02 | 0x%08x", blocks[2]);
+ PrintAndLog(" 03 | 0x%08x", blocks[3]);
+ PrintAndLog(" 04 | 0x%08x", blocks[4]);
+
+ UsbCommand resp;
+ UsbCommand c = {CMD_T55XX_WRITE_BLOCK, {0,0,0}};
+
+ for (int i=4; i>=0; i--) {
+ c.arg[0] = blocks[i];
+ c.arg[1] = i;
+ clearCommandBuffer();
+ SendCommand(&c);
+ if (!WaitForResponseTimeout(CMD_ACK, &resp, 1000)){
+ PrintAndLog("Error occurred, device did not respond during write operation.");
+ return -1;
+ }
+ }
+ return 0;
+}
+
+// takes base 12 ID converts to hex
+// Or takes 8 digit hex ID
+int CmdPrescoSim(const char *Cmd) {
+ uint32_t sitecode=0, usercode=0, fullcode=0;
+ bool Q5=false;
+ // get wiegand from printed number.
+ if (GetWiegandFromPresco(Cmd, &sitecode, &usercode, &fullcode, &Q5) == -1) return usage_lf_presco_sim();
+
+ uint8_t clk = 32, encoding = 1, separator = 1, invert = 0;
+ uint16_t arg1, arg2;
+ size_t size = 128;
+ arg1 = clk << 8 | encoding;
+ arg2 = invert << 8 | separator;
+
+ PrintAndLog("Simulating Presco - SiteCode: %u, UserCode: %u, FullCode: %08X",sitecode, usercode, fullcode);
+
+ UsbCommand c = {CMD_ASK_SIM_TAG, {arg1, arg2, size}};
+ GetPrescoBits(fullcode, c.d.asBytes);
+ clearCommandBuffer();
+ SendCommand(&c);
+ return 0;
+}
+
+static command_t CommandTable[] = {
+ {"help", CmdHelp, 1, "This help"},
+ {"read", CmdPrescoRead, 0, "Attempt to read and Extract tag data"},
+ {"clone", CmdPrescoClone, 0, "d <9 digit ID> or h <hex> [Q5] clone presco tag"},
+ {"sim", CmdPrescoSim, 0, "d <9 digit ID> or h <hex> simulate presco tag"},
+ {NULL, NULL, 0, NULL}
+};
+
+int CmdLFPresco(const char *Cmd) {
+ clearCommandBuffer();
+ CmdsParse(CommandTable, Cmd);
+ return 0;
+}
+
+int CmdHelp(const char *Cmd) {
+ CmdsHelp(CommandTable);
+ return 0;
+}
--- /dev/null
+//-----------------------------------------------------------------------------
+//
+// This code is licensed to you under the terms of the GNU GPL, version 2 or,
+// at your option, any later version. See the LICENSE.txt file for the text of
+// the license.
+//-----------------------------------------------------------------------------
+// Low frequency T55xx commands
+//-----------------------------------------------------------------------------
+#ifndef CMDLFPRESCO_H__
+#define CMDLFPRESCO_H__
+
+#include <stdint.h> //uint_32+
+#include <stdbool.h> //bool
+
+int CmdLFPresco(const char *Cmd);
+int CmdPrescoClone(const char *Cmd);
+int CmdPrescoSim(const char *Cmd);
+
+int GetWiegandFromPresco(const char *id, uint32_t *sitecode, uint32_t *usercode, uint32_t *fullcode, bool *Q5);
+
+int usage_lf_presco_clone(void);
+int usage_lf_presco_sim(void);
+#endif
+
--- /dev/null
+//-----------------------------------------------------------------------------
+//
+// This code is licensed to you under the terms of the GNU GPL, version 2 or,
+// at your option, any later version. See the LICENSE.txt file for the text of
+// the license.
+//-----------------------------------------------------------------------------
+// Low frequency Farpoint / Pyramid tag commands
+//-----------------------------------------------------------------------------
+#include <string.h>
+#include <inttypes.h>
+#include "cmdlfpyramid.h"
+#include "proxmark3.h"
+#include "ui.h"
+#include "util.h"
+#include "graph.h"
+#include "cmdparser.h"
+#include "cmddata.h"
+#include "cmdmain.h"
+#include "cmdlf.h"
+#include "protocols.h" // for T55xx config register definitions
+#include "lfdemod.h" // parityTest
+#include "crc.h"
+
+static int CmdHelp(const char *Cmd);
+
+int usage_lf_pyramid_clone(void){
+ PrintAndLog("clone a Farpointe/Pyramid tag to a T55x7 tag.");
+ PrintAndLog("The facility-code is 8-bit and the card number is 16-bit. Larger values are truncated. ");
+ PrintAndLog("Currently work only on 26bit");
+ PrintAndLog("");
+ PrintAndLog("Usage: lf pyramid clone <Facility-Code> <Card-Number>");
+ PrintAndLog("Options :");
+ PrintAndLog(" <Facility-Code> : 8-bit value facility code");
+ PrintAndLog(" <Card Number> : 16-bit value card number");
+ PrintAndLog(" Q5 : optional - clone to Q5 (T5555) instead of T55x7 chip");
+ PrintAndLog("");
+ PrintAndLog("Sample : lf pyramid clone 123 11223");
+ return 0;
+}
+
+int usage_lf_pyramid_sim(void) {
+ PrintAndLog("Enables simulation of Farpointe/Pyramid card with specified card number.");
+ PrintAndLog("Simulation runs until the button is pressed or another USB command is issued.");
+ PrintAndLog("The facility-code is 8-bit and the card number is 16-bit. Larger values are truncated.");
+ PrintAndLog("Currently work only on 26bit");
+ PrintAndLog("");
+ PrintAndLog("Usage: lf pyramid sim <Card-Number>");
+ PrintAndLog("Options :");
+ PrintAndLog(" <Facility-Code> : 8-bit value facility code");
+ PrintAndLog(" <Card Number> : 16-bit value card number");
+ PrintAndLog("");
+ PrintAndLog("Sample : lf pyramid sim 123 11223");
+ return 0;
+}
+
+// Works for 26bits.
+int GetPyramidBits(uint32_t fc, uint32_t cn, uint8_t *pyramidBits) {
+
+ uint8_t pre[128];
+ memset(pre, 0x00, sizeof(pre));
+
+ // format start bit
+ pre[79] = 1;
+
+ // Get 26 wiegand from FacilityCode, CardNumber
+ uint8_t wiegand[24];
+ memset(wiegand, 0x00, sizeof(wiegand));
+ num_to_bytebits(fc, 8, wiegand);
+ num_to_bytebits(cn, 16, wiegand+8);
+
+ // add wiegand parity bits (dest, source, len)
+ wiegand_add_parity(pre+80, wiegand, 24);
+
+ // add paritybits (bitsource, dest, sourcelen, paritylen, parityType (odd, even,)
+ addParity(pre+8, pyramidBits+8, 102, 8, 1);
+
+ // add checksum
+ uint8_t csBuff[13];
+ for (uint8_t i = 0; i < 13; i++)
+ csBuff[i] = bytebits_to_byte(pyramidBits + 16 + (i*8), 8);
+
+ uint32_t crc = CRC8Maxim(csBuff, 13);
+ num_to_bytebits(crc, 8, pyramidBits+120);
+ return 1;
+}
+
+int CmdPyramidRead(const char *Cmd) {
+ CmdLFRead("s");
+ getSamples("30000",false);
+ return CmdFSKdemodPyramid("");
+}
+
+int CmdPyramidClone(const char *Cmd) {
+
+ char cmdp = param_getchar(Cmd, 0);
+ if (strlen(Cmd) == 0 || cmdp == 'h' || cmdp == 'H') return usage_lf_pyramid_clone();
+
+ uint32_t facilitycode=0, cardnumber=0, fc = 0, cn = 0;
+ uint32_t blocks[5];
+ uint8_t i;
+ uint8_t bs[128];
+ memset(bs, 0x00, sizeof(bs));
+
+ if (sscanf(Cmd, "%u %u", &fc, &cn ) != 2) return usage_lf_pyramid_clone();
+
+ facilitycode = (fc & 0x000000FF);
+ cardnumber = (cn & 0x0000FFFF);
+
+ if ( !GetPyramidBits(facilitycode, cardnumber, bs)) {
+ PrintAndLog("Error with tag bitstream generation.");
+ return 1;
+ }
+
+ //Pyramid - compat mode, FSK2a, data rate 50, 4 data blocks
+ blocks[0] = T55x7_MODULATION_FSK2a | T55x7_BITRATE_RF_50 | 4<<T55x7_MAXBLOCK_SHIFT;
+
+ if (param_getchar(Cmd, 3) == 'Q' || param_getchar(Cmd, 3) == 'q')
+ blocks[0] = T5555_MODULATION_FSK2 | T5555_INVERT_OUTPUT | 50<<T5555_BITRATE_SHIFT | 4<<T5555_MAXBLOCK_SHIFT;
+
+ blocks[1] = bytebits_to_byte(bs,32);
+ blocks[2] = bytebits_to_byte(bs+32,32);
+ blocks[3] = bytebits_to_byte(bs+64,32);
+ blocks[4] = bytebits_to_byte(bs+96,32);
+
+ PrintAndLog("Preparing to clone Farpointe/Pyramid to T55x7 with Facility Code: %u, Card Number: %u", facilitycode, cardnumber);
+ PrintAndLog("Blk | Data ");
+ PrintAndLog("----+------------");
+ for ( i = 0; i<5; ++i )
+ PrintAndLog(" %02d | %08" PRIx32, i, blocks[i]);
+
+ UsbCommand resp;
+ UsbCommand c = {CMD_T55XX_WRITE_BLOCK, {0,0,0}};
+
+ for ( i = 0; i<5; ++i ) {
+ c.arg[0] = blocks[i];
+ c.arg[1] = i;
+ clearCommandBuffer();
+ SendCommand(&c);
+ if (!WaitForResponseTimeout(CMD_ACK, &resp, 1000)){
+ PrintAndLog("Error occurred, device did not respond during write operation.");
+ return -1;
+ }
+ }
+ return 0;
+}
+
+int CmdPyramidSim(const char *Cmd) {
+
+ char cmdp = param_getchar(Cmd, 0);
+ if (strlen(Cmd) == 0 || cmdp == 'h' || cmdp == 'H') return usage_lf_pyramid_sim();
+
+ uint32_t facilitycode = 0, cardnumber = 0, fc = 0, cn = 0;
+
+ uint8_t bs[128];
+ size_t size = sizeof(bs);
+ memset(bs, 0x00, size);
+
+ // Pyramid uses: fcHigh: 10, fcLow: 8, clk: 50, invert: 0
+ uint64_t arg1, arg2;
+ arg1 = (10 << 8) + 8;
+ arg2 = 50 | 0;
+
+ if (sscanf(Cmd, "%u %u", &fc, &cn ) != 2) return usage_lf_pyramid_sim();
+
+ facilitycode = (fc & 0x000000FF);
+ cardnumber = (cn & 0x0000FFFF);
+
+ if ( !GetPyramidBits(facilitycode, cardnumber, bs)) {
+ PrintAndLog("Error with tag bitstream generation.");
+ return 1;
+ }
+
+ PrintAndLog("Simulating Farpointe/Pyramid - Facility Code: %u, CardNumber: %u", facilitycode, cardnumber );
+
+ UsbCommand c = {CMD_FSK_SIM_TAG, {arg1, arg2, size}};
+ memcpy(c.d.asBytes, bs, size);
+ clearCommandBuffer();
+ SendCommand(&c);
+ return 0;
+}
+
+static command_t CommandTable[] = {
+ {"help", CmdHelp, 1, "This help"},
+ {"read", CmdPyramidRead, 0, "Attempt to read and extract tag data"},
+ {"clone", CmdPyramidClone, 0, "<Facility-Code> <Card Number> clone pyramid tag"},
+ {"sim", CmdPyramidSim, 0, "<Facility-Code> <Card Number> simulate pyramid tag"},
+ {NULL, NULL, 0, NULL}
+};
+
+int CmdLFPyramid(const char *Cmd) {
+ clearCommandBuffer();
+ CmdsParse(CommandTable, Cmd);
+ return 0;
+}
+
+int CmdHelp(const char *Cmd) {
+ CmdsHelp(CommandTable);
+ return 0;
+}
--- /dev/null
+//-----------------------------------------------------------------------------
+//
+// This code is licensed to you under the terms of the GNU GPL, version 2 or,
+// at your option, any later version. See the LICENSE.txt file for the text of
+// the license.
+//-----------------------------------------------------------------------------
+// Low frequency T55xx commands
+//-----------------------------------------------------------------------------
+#ifndef CMDLFPYRAMID_H__
+#define CMDLFPYRAMID_H__
+
+int CmdLFPyramid(const char *Cmd);
+int CmdPyramidClone(const char *Cmd);
+int CmdPyramidSim(const char *Cmd);
+
+int usage_lf_pyramid_clone(void);
+int usage_lf_pyramid_sim(void);
+#endif
+
PrintAndLog(" i [1] Invert data signal, defaults to normal");\r
PrintAndLog(" o [offset] Set offset, where data should start decode in bitstream");\r
PrintAndLog(" Q5 Set as Q5(T5555) chip instead of T55x7");\r
+ PrintAndLog(" ST Set Sequence Terminator on");\r
PrintAndLog("");\r
PrintAndLog("Examples:");\r
PrintAndLog(" lf t55xx config d FSK - FSK demodulation");\r
return 0;\r
}\r
int usage_t55xx_write(){\r
- PrintAndLog("Usage: lf t55xx wr [b <block>] [d <data>] [p <password>] [1]");\r
+ PrintAndLog("Usage: lf t55xx write [b <block>] [d <data>] [p <password>] [1]");\r
PrintAndLog("Options:");\r
PrintAndLog(" b <block> - block number to write. Between 0-7");\r
PrintAndLog(" d <data> - 4 bytes of data to write (8 hex characters)");\r
PrintAndLog(" 1 - OPTIONAL write Page 1 instead of Page 0");\r
PrintAndLog("");\r
PrintAndLog("Examples:");\r
- PrintAndLog(" lf t55xx wr b 3 d 11223344 - write 11223344 to block 3");\r
- PrintAndLog(" lf t55xx wr b 3 d 11223344 p feedbeef - write 11223344 to block 3 password feedbeef");\r
+ PrintAndLog(" lf t55xx write b 3 d 11223344 - write 11223344 to block 3");\r
+ PrintAndLog(" lf t55xx write b 3 d 11223344 p feedbeef - write 11223344 to block 3 password feedbeef");\r
PrintAndLog("");\r
return 0;\r
}\r
config.Q5 = TRUE;\r
cmdp++;\r
break;\r
+ case 'S':\r
+ case 's': \r
+ config.ST = TRUE;\r
+ cmdp++;\r
+ break;\r
default:\r
PrintAndLog("Unknown parameter '%c'", param_getchar(Cmd, cmdp));\r
errors = TRUE;\r
char buf[30] = {0x00};\r
char *cmdStr = buf;\r
int ans = 0;\r
+ bool ST = config.ST;\r
uint8_t bitRate[8] = {8,16,32,40,50,64,100,128};\r
DemodBufferLen = 0x00;\r
\r
break;\r
case DEMOD_ASK:\r
snprintf(cmdStr, sizeof(buf),"%d %d 1", bitRate[config.bitrate], config.inverted );\r
- ans = ASKDemod(cmdStr, FALSE, FALSE, 1);\r
+ ans = ASKDemod_ext(cmdStr, FALSE, FALSE, 1, &ST);\r
break;\r
case DEMOD_PSK1:\r
// skip first 160 samples to allow antenna to settle in (psk gets inverted occasionally otherwise)\r
t55xx_conf_block_t tests[15];\r
int bitRate=0;\r
uint8_t fc1 = 0, fc2 = 0, clk=0;\r
-\r
if (GetFskClock("", FALSE, FALSE)){ \r
fskClocks(&fc1, &fc2, &clk, FALSE);\r
if ( FSKrawDemod("0 0", FALSE) && test(DEMOD_FSK, &tests[hits].offset, &bitRate, clk, &tests[hits].Q5)) {\r
tests[hits].bitrate = bitRate;\r
tests[hits].inverted = FALSE;\r
tests[hits].block0 = PackBits(tests[hits].offset, 32, DemodBuffer);\r
+ tests[hits].ST = FALSE;\r
++hits;\r
}\r
if ( FSKrawDemod("0 1", FALSE) && test(DEMOD_FSK, &tests[hits].offset, &bitRate, clk, &tests[hits].Q5)) {\r
tests[hits].bitrate = bitRate;\r
tests[hits].inverted = TRUE;\r
tests[hits].block0 = PackBits(tests[hits].offset, 32, DemodBuffer);\r
+ tests[hits].ST = FALSE;\r
++hits;\r
}\r
} else {\r
clk = GetAskClock("", FALSE, FALSE);\r
if (clk>0) {\r
- if ( ASKDemod("0 0 1", FALSE, FALSE, 1) && test(DEMOD_ASK, &tests[hits].offset, &bitRate, clk, &tests[hits].Q5)) {\r
+ tests[hits].ST = TRUE;\r
+ if ( ASKDemod_ext("0 0 1", FALSE, FALSE, 1, &tests[hits].ST) && test(DEMOD_ASK, &tests[hits].offset, &bitRate, clk, &tests[hits].Q5)) {\r
tests[hits].modulation = DEMOD_ASK;\r
tests[hits].bitrate = bitRate;\r
tests[hits].inverted = FALSE;\r
tests[hits].block0 = PackBits(tests[hits].offset, 32, DemodBuffer);\r
++hits;\r
}\r
- if ( ASKDemod("0 1 1", FALSE, FALSE, 1) && test(DEMOD_ASK, &tests[hits].offset, &bitRate, clk, &tests[hits].Q5)) {\r
+ tests[hits].ST = TRUE;\r
+ if ( ASKDemod_ext("0 1 1", FALSE, FALSE, 1, &tests[hits].ST) && test(DEMOD_ASK, &tests[hits].offset, &bitRate, clk, &tests[hits].Q5)) {\r
tests[hits].modulation = DEMOD_ASK;\r
tests[hits].bitrate = bitRate;\r
tests[hits].inverted = TRUE;\r
tests[hits].bitrate = bitRate;\r
tests[hits].inverted = FALSE;\r
tests[hits].block0 = PackBits(tests[hits].offset, 32, DemodBuffer);\r
+ tests[hits].ST = FALSE;\r
++hits;\r
}\r
if ( ASKbiphaseDemod("0 0 1 2", FALSE) && test(DEMOD_BIa, &tests[hits].offset, &bitRate, clk, &tests[hits].Q5) ) {\r
tests[hits].bitrate = bitRate;\r
tests[hits].inverted = TRUE;\r
tests[hits].block0 = PackBits(tests[hits].offset, 32, DemodBuffer);\r
+ tests[hits].ST = FALSE;\r
++hits;\r
}\r
}\r
tests[hits].bitrate = bitRate;\r
tests[hits].inverted = FALSE;\r
tests[hits].block0 = PackBits(tests[hits].offset, 32, DemodBuffer);\r
+ tests[hits].ST = FALSE;\r
++hits;\r
}\r
\r
tests[hits].bitrate = bitRate;\r
tests[hits].inverted = TRUE;\r
tests[hits].block0 = PackBits(tests[hits].offset, 32, DemodBuffer);\r
+ tests[hits].ST = FALSE;\r
++hits;\r
}\r
}\r
tests[hits].bitrate = bitRate;\r
tests[hits].inverted = FALSE;\r
tests[hits].block0 = PackBits(tests[hits].offset, 32, DemodBuffer);\r
+ tests[hits].ST = FALSE;\r
++hits;\r
}\r
if ( PSKDemod("0 1 6", FALSE) && test(DEMOD_PSK1, &tests[hits].offset, &bitRate, clk, &tests[hits].Q5)) {\r
tests[hits].bitrate = bitRate;\r
tests[hits].inverted = TRUE;\r
tests[hits].block0 = PackBits(tests[hits].offset, 32, DemodBuffer);\r
+ tests[hits].ST = FALSE;\r
++hits;\r
}\r
// PSK2 - needs a call to psk1TOpsk2.\r
tests[hits].bitrate = bitRate;\r
tests[hits].inverted = FALSE;\r
tests[hits].block0 = PackBits(tests[hits].offset, 32, DemodBuffer);\r
+ tests[hits].ST = FALSE;\r
++hits;\r
}\r
} // inverse waves does not affect this demod\r
tests[hits].bitrate = bitRate;\r
tests[hits].inverted = FALSE;\r
tests[hits].block0 = PackBits(tests[hits].offset, 32, DemodBuffer);\r
+ tests[hits].ST = FALSE;\r
++hits;\r
}\r
} // inverse waves does not affect this demod\r
config.offset = tests[0].offset;\r
config.block0 = tests[0].block0;\r
config.Q5 = tests[0].Q5;\r
+ config.ST = tests[0].ST;\r
printConfiguration( config );\r
return TRUE;\r
}\r
uint8_t extend = PackBits(si, 1, DemodBuffer); si += 1; //bit 15 extended mode\r
uint8_t modread = PackBits(si, 5, DemodBuffer); si += 5+2+1; \r
//uint8_t pskcr = PackBits(si, 2, DemodBuffer); si += 2+1; //could check psk cr\r
- uint8_t nml01 = PackBits(si, 1, DemodBuffer); si += 1+5; //bit 24, 30, 31 could be tested for 0 if not extended mode\r
- uint8_t nml02 = PackBits(si, 2, DemodBuffer); si += 2;\r
+ //uint8_t nml01 = PackBits(si, 1, DemodBuffer); si += 1+5; //bit 24, 30, 31 could be tested for 0 if not extended mode\r
+ //uint8_t nml02 = PackBits(si, 2, DemodBuffer); si += 2;\r
\r
//if extended mode\r
bool extMode =( (safer == 0x6 || safer == 0x9) && extend) ? TRUE : FALSE;\r
\r
if (!extMode){\r
- if (nml01 || nml02 || xtRate) continue;\r
+ if (xtRate) continue; //nml01 || nml02 || caused issues on noralys tags\r
}\r
//test modulation\r
if (!testModulation(mode, modread)) continue;\r
PrintAndLog("Bit Rate : %s", GetBitRateStr(b.bitrate) );\r
PrintAndLog("Inverted : %s", (b.inverted) ? "Yes" : "No" );\r
PrintAndLog("Offset : %d", b.offset);\r
+ PrintAndLog("Seq. Term. : %s", (b.ST) ? "Yes" : "No" );\r
PrintAndLog("Block0 : 0x%08X", b.block0);\r
PrintAndLog("");\r
return 0;\r
RF_128 = 0x07,\r
} bitrate;\r
bool Q5;\r
+ bool ST;\r
} t55xx_conf_block_t;\r
t55xx_conf_block_t Get_t55xx_Config();\r
void Set_t55xx_Config(t55xx_conf_block_t conf);\r
uint64_t getVikingBits(uint32_t id) {
//calc checksum
- uint8_t checksum = (id>>24) ^ ((id>>16) & 0xFF) ^ ((id>>8) & 0xFF) ^ (id & 0xFF) ^ 0xF2 ^ 0xA8;
- return ((uint64_t)0xF2 << 56) | (id << 8) | checksum;
+ uint8_t checksum = ((id>>24) & 0xFF) ^ ((id>>16) & 0xFF) ^ ((id>>8) & 0xFF) ^ (id & 0xFF) ^ 0xF2 ^ 0xA8;
+ return ((uint64_t)0xF2 << 56) | ((uint64_t)id << 8) | checksum;
}
//by marshmellow
//see ASKDemod for what args are accepted
#define MAX(a,b) ((a)>(b)?(a):(b))
// zlib configuration
-#define COMPRESS_LEVEL 9 // use best possible compression
-#define COMPRESS_WINDOW_BITS 15 // default = max = 15 for a window of 2^15 = 32KBytes
-#define COMPRESS_MEM_LEVEL 9 // determines the amount of memory allocated during compression. Default = 8.
+#define COMPRESS_LEVEL 9 // use best possible compression
+#define COMPRESS_WINDOW_BITS 15 // default = max = 15 for a window of 2^15 = 32KBytes
+#define COMPRESS_MEM_LEVEL 9 // determines the amount of memory allocated during compression. Default = 8.
/* COMPRESS_STRATEGY can be
Z_DEFAULT_STRATEGY (the default),
Z_FILTERED (more huffmann, less string matching),
Z_HUFFMAN_ONLY (huffman only, no string matching)
Z_RLE (distances limited to one)
Z_FIXED (prevents the use of dynamic Huffman codes)
-*/
-#define COMPRESS_STRATEGY Z_DEFAULT_STRATEGY
+*/
+
+#define COMPRESS_STRATEGY Z_DEFAULT_STRATEGY
// zlib tuning parameters:
-#define COMPRESS_GOOD_LENGTH 258
-#define COMPRESS_MAX_LAZY 258
-#define COMPRESS_MAX_NICE_LENGTH 258
-#define COMPRESS_MAX_CHAIN 8192
+#define COMPRESS_GOOD_LENGTH 258
+#define COMPRESS_MAX_LAZY 258
+#define COMPRESS_MAX_NICE_LENGTH 258
+#define COMPRESS_MAX_CHAIN 8192
-#define FPGA_INTERLEAVE_SIZE 288 // (the FPGA's internal config frame size is 288 bits. Interleaving with 288 bytes should give best compression)
-#define FPGA_CONFIG_SIZE 42336 // our current fpga_[lh]f.bit files are 42175 bytes. Rounded up to next multiple of FPGA_INTERLEAVE_SIZE
+#define FPGA_INTERLEAVE_SIZE 288 // (the FPGA's internal config frame size is 288 bits. Interleaving with 288 bytes should give best compression)
+#define FPGA_CONFIG_SIZE 42336 // our current fpga_[lh]f.bit files are 42175 bytes. Rounded up to next multiple of FPGA_INTERLEAVE_SIZE
static void usage(void)
{
{
uint8_t *fpga_config;
uint32_t i;
- int ret;
- uint8_t c;
+ int32_t ret;
+ uint8_t c;
z_stream compressed_fpga_stream;
fpga_config = malloc(num_infiles * FPGA_CONFIG_SIZE);
do {
if (i >= num_infiles * FPGA_CONFIG_SIZE) {
- fprintf(stderr, "Input files too big (total > %lu bytes). These are probably not PM3 FPGA config files.\n", num_infiles*FPGA_CONFIG_SIZE);
+ fprintf(stderr, "Input files too big (total > %u bytes). These are probably not PM3 FPGA config files.\n", num_infiles*FPGA_CONFIG_SIZE);
for(uint16_t j = 0; j < num_infiles; j++) {
fclose(infile[j]);
}
COMPRESS_STRATEGY);
// estimate the size of the compressed output
- unsigned int outsize_max = deflateBound(&compressed_fpga_stream, compressed_fpga_stream.avail_in);
+ uint32_t outsize_max = deflateBound(&compressed_fpga_stream, compressed_fpga_stream.avail_in);
uint8_t *outbuf = malloc(outsize_max);
compressed_fpga_stream.next_out = outbuf;
compressed_fpga_stream.avail_out = outsize_max;
-
+
if (ret == Z_OK) {
ret = deflateTune(&compressed_fpga_stream,
COMPRESS_GOOD_LENGTH,
ret = deflate(&compressed_fpga_stream, Z_FINISH);
}
- fprintf(stderr, "compressed %lu input bytes to %lu output bytes\n", i, compressed_fpga_stream.total_out);
+ fprintf(stderr, "compressed %u input bytes to %lu output bytes\n", i, compressed_fpga_stream.total_out);
if (ret != Z_STREAM_END) {
- fprintf(stderr, "Error in deflate(): %d %s\n", ret, compressed_fpga_stream.msg);
+ fprintf(stderr, "Error in deflate(): %i %s\n", ret, compressed_fpga_stream.msg);
free(outbuf);
deflateEnd(&compressed_fpga_stream);
for(uint16_t j = 0; j < num_infiles; j++) {
#define DECOMPRESS_BUF_SIZE 1024
uint8_t outbuf[DECOMPRESS_BUF_SIZE];
uint8_t inbuf[DECOMPRESS_BUF_SIZE];
- int ret;
+ int32_t ret;
z_stream compressed_fpga_stream;
compressed_fpga_stream.next_in = inbuf;
uint16_t i = 0;
do {
- int c = fgetc(infile);
+ int32_t c = fgetc(infile);
if (!feof(infile)) {
inbuf[i++] = c & 0xFF;
compressed_fpga_stream.avail_in++;
fclose(infile);
return(EXIT_SUCCESS);
} else {
- fprintf(stderr, "Error. Inflate() returned error %d, %s", ret, compressed_fpga_stream.msg);
+ fprintf(stderr, "Error. Inflate() returned error %i, %s", ret, compressed_fpga_stream.msg);
fclose(outfile);
fclose(infile);
return(EXIT_FAILURE);
return(EXIT_FAILURE);
}
- if (!strcmp(argv[1], "-d")) { // Decompress
+ if (!strcmp(argv[1], "-d")) { // Decompress
infiles = calloc(1, sizeof(FILE*));
if (argc != 4) {
usage();
}
return zlib_decompress(infiles[0], outfile);
- } else { // Compress
+ } else { // Compress
infiles = calloc(argc-2, sizeof(FILE*));
for (uint16_t i = 0; i < argc-2; i++) {
PrintAndLog("Failed to copy from graphbuffer");
return -1;
}
- int start = DetectASKClock(grph, size, &clock, 20);
+ bool st = DetectST(grph, &size, &clock);
+ int start = 0;
+ if (st == false) {
+ start = DetectASKClock(grph, size, &clock, 20);
+ }
// Only print this message if we're not looping something
- if (printAns){
+ if (printAns) {
PrintAndLog("Auto-detected clock rate: %d, Best Starting Position: %d", clock, start);
}
return clock;
#define CMD_SIMULATE_HITAG 0x0371
#define CMD_READER_HITAG 0x0372
+#define CMD_SIMULATE_HITAG_S 0x0368
+#define CMD_TEST_HITAGS_TRACES 0x0367
+#define CMD_READ_HITAG_S 0x0373
+#define CMD_WR_HITAG_S 0x0375
+#define CMD_EMU_HITAG_S 0x0376
+
#define CMD_SIMULATE_TAG_ISO_14443B 0x0381
#define CMD_SNOOP_ISO_14443B 0x0382
#define CMD_SNOOP_ISO_14443a 0x0383
'776974687573', -- RKF ÖstgötaTrafiken Key B
--[[
- The keys below are taken from from https://code.google.com/p/mifare-key-cracker/downloads/list
+ The keys below are taken from https://code.google.com/p/mifare-key-cracker/downloads/list
--]]
'bd493a3962b6',
'123456789abc',
--[[
- The keys below are taken from from https://github.com/4ZM/mfterm/blob/master/dictionary.txt
+ The keys below are taken from https://github.com/4ZM/mfterm/blob/master/dictionary.txt
--]]
'abcdef123456', -- Key from ladyada.net
table.insert(foobar, value);
end
end
- --print("final list length length ", #foobar)
+ --print("final list length ", #foobar)
return foobar
end
return 1;
}
+
+// 32 bit recover key from 2 nonces
+bool mfkey32(nonces_t data, uint64_t *outputkey) {
+ struct Crypto1State *s,*t;
+ uint64_t outkey = 0;
+ uint64_t key=0; // recovered key
+ uint32_t uid = data.cuid;
+ uint32_t nt = data.nonce; // first tag challenge (nonce)
+ uint32_t nr0_enc = data.nr; // first encrypted reader challenge
+ uint32_t ar0_enc = data.ar; // first encrypted reader response
+ uint32_t nr1_enc = data.nr2; // second encrypted reader challenge
+ uint32_t ar1_enc = data.ar2; // second encrypted reader response
+ clock_t t1 = clock();
+ bool isSuccess = FALSE;
+ uint8_t counter=0;
+
+ s = lfsr_recovery32(ar0_enc ^ prng_successor(nt, 64), 0);
+
+ for(t = s; t->odd | t->even; ++t) {
+ lfsr_rollback_word(t, 0, 0);
+ lfsr_rollback_word(t, nr0_enc, 1);
+ lfsr_rollback_word(t, uid ^ nt, 0);
+ crypto1_get_lfsr(t, &key);
+ crypto1_word(t, uid ^ nt, 0);
+ crypto1_word(t, nr1_enc, 1);
+ if (ar1_enc == (crypto1_word(t, 0, 0) ^ prng_successor(nt, 64))) {
+ //PrintAndLog("Found Key: [%012"llx"]",key);
+ outkey = key;
+ counter++;
+ if (counter==20) break;
+ }
+ }
+ isSuccess = (counter == 1);
+ t1 = clock() - t1;
+ //if ( t1 > 0 ) PrintAndLog("Time in mfkey32: %.0f ticks \nFound %d possible keys", (float)t1, counter);
+ *outputkey = ( isSuccess ) ? outkey : 0;
+ crypto1_destroy(s);
+ /* //un-comment to save all keys to a stats.txt file
+ FILE *fout;
+ if ((fout = fopen("stats.txt","ab")) == NULL) {
+ PrintAndLog("Could not create file name stats.txt");
+ return 1;
+ }
+ fprintf(fout, "mfkey32,%d,%08x,%d,%s,%04x%08x,%.0Lf\r\n", counter, data.cuid, data.sector, (data.keytype) ? "B" : "A", (uint32_t)(outkey>>32) & 0xFFFF,(uint32_t)(outkey&0xFFFFFFFF),(long double)t1);
+ fclose(fout);
+ */
+ return isSuccess;
+}
+
+bool tryMfk32_moebius(nonces_t data, uint64_t *outputkey) {
+ struct Crypto1State *s, *t;
+ uint64_t outkey = 0;
+ uint64_t key = 0; // recovered key
+ uint32_t uid = data.cuid;
+ uint32_t nt0 = data.nonce; // first tag challenge (nonce)
+ uint32_t nr0_enc = data.nr; // first encrypted reader challenge
+ uint32_t ar0_enc = data.ar; // first encrypted reader response
+ uint32_t nt1 = data.nonce2; // second tag challenge (nonce)
+ uint32_t nr1_enc = data.nr2; // second encrypted reader challenge
+ uint32_t ar1_enc = data.ar2; // second encrypted reader response
+ bool isSuccess = FALSE;
+ int counter = 0;
+
+ //PrintAndLog("Enter mfkey32_moebius");
+ clock_t t1 = clock();
+
+ s = lfsr_recovery32(ar0_enc ^ prng_successor(nt0, 64), 0);
+
+ for(t = s; t->odd | t->even; ++t) {
+ lfsr_rollback_word(t, 0, 0);
+ lfsr_rollback_word(t, nr0_enc, 1);
+ lfsr_rollback_word(t, uid ^ nt0, 0);
+ crypto1_get_lfsr(t, &key);
+
+ crypto1_word(t, uid ^ nt1, 0);
+ crypto1_word(t, nr1_enc, 1);
+ if (ar1_enc == (crypto1_word(t, 0, 0) ^ prng_successor(nt1, 64))) {
+ //PrintAndLog("Found Key: [%012"llx"]",key);
+ outkey=key;
+ ++counter;
+ if (counter==20)
+ break;
+ }
+ }
+ isSuccess = (counter == 1);
+ t1 = clock() - t1;
+ //if ( t1 > 0 ) PrintAndLog("Time in mfkey32_moebius: %.0f ticks \nFound %d possible keys", (float)t1,counter);
+ *outputkey = ( isSuccess ) ? outkey : 0;
+ crypto1_destroy(s);
+ /* // un-comment to output all keys to stats.txt
+ FILE *fout;
+ if ((fout = fopen("stats.txt","ab")) == NULL) {
+ PrintAndLog("Could not create file name stats.txt");
+ return 1;
+ }
+ fprintf(fout, "moebius,%d,%08x,%d,%s,%04x%08x,%0.Lf\r\n", counter, data.cuid, data.sector, (data.keytype) ? "B" : "A", (uint32_t) (outkey>>32),(uint32_t)(outkey&0xFFFFFFFF),(long double)t1);
+ fclose(fout);
+ */
+ return isSuccess;
+}
+
+int tryMfk64_ex(uint8_t *data, uint64_t *outputkey){
+ uint32_t uid = le32toh(data);
+ uint32_t nt = le32toh(data+4); // tag challenge
+ uint32_t nr_enc = le32toh(data+8); // encrypted reader challenge
+ uint32_t ar_enc = le32toh(data+12); // encrypted reader response
+ uint32_t at_enc = le32toh(data+16); // encrypted tag response
+ return tryMfk64(uid, nt, nr_enc, ar_enc, at_enc, outputkey);
+}
+
+int tryMfk64(uint32_t uid, uint32_t nt, uint32_t nr_enc, uint32_t ar_enc, uint32_t at_enc, uint64_t *outputkey){
+ uint64_t key = 0; // recovered key
+ uint32_t ks2; // keystream used to encrypt reader response
+ uint32_t ks3; // keystream used to encrypt tag response
+ struct Crypto1State *revstate;
+
+ PrintAndLog("Enter mfkey64");
+ clock_t t1 = clock();
+
+ // Extract the keystream from the messages
+ ks2 = ar_enc ^ prng_successor(nt, 64);
+ ks3 = at_enc ^ prng_successor(nt, 96);
+ revstate = lfsr_recovery64(ks2, ks3);
+ lfsr_rollback_word(revstate, 0, 0);
+ lfsr_rollback_word(revstate, 0, 0);
+ lfsr_rollback_word(revstate, nr_enc, 1);
+ lfsr_rollback_word(revstate, uid ^ nt, 0);
+ crypto1_get_lfsr(revstate, &key);
+ PrintAndLog("Found Key: [%012"llx"]", key);
+ crypto1_destroy(revstate);
+ *outputkey = key;
+
+ t1 = clock() - t1;
+ if ( t1 > 0 ) PrintAndLog("Time in mfkey64: %.0f ticks \n", (float)t1);
+ return 0;
+}
+
#include <stdlib.h>
#include "crapto1.h"
#include "common.h"
+//#include <stdbool.h> //for bool
+
+typedef struct {
+ uint32_t cuid;
+ uint8_t sector;
+ uint8_t keytype;
+ uint32_t nonce;
+ uint32_t ar;
+ uint32_t nr;
+ uint32_t nonce2;
+ uint32_t ar2;
+ uint32_t nr2;
+ } nonces_t;
int nonce2key(uint32_t uid, uint32_t nt, uint32_t nr, uint64_t par_info, uint64_t ks_info, uint64_t * key);
+bool mfkey32(nonces_t data, uint64_t *outputkey);
+bool tryMfk32_moebius(nonces_t data, uint64_t *outputkey);
+int tryMfk64_ex(uint8_t *data, uint64_t *outputkey);
+int tryMfk64(uint32_t uid, uint32_t nt, uint32_t nr_enc, uint32_t ar_enc, uint32_t at_enc, uint64_t *outputkey);
+
+//uint64_t mfkey32(uint32_t uid, uint32_t nt, uint32_t nr0_enc, uint32_t ar0_enc, uint32_t nr1_enc, uint32_t ar1_enc);
#endif
void InitGraphics(int argc, char **argv);
void ExitGraphics(void);
-#define MAX_GRAPH_TRACE_LEN (1024*128)
+#define MAX_GRAPH_TRACE_LEN (40000*8)
extern int GraphBuffer[MAX_GRAPH_TRACE_LEN];
extern int GraphTraceLen;
extern double CursorScaleFactor;
memset(fileName, 0x00, 200);
for (int j = 0; j < byteCount; j++, fnameptr += 2)
- sprintf(fnameptr, "%02x", uid[j]);
+ sprintf(fnameptr, "%02x", (unsigned int) uid[j]);
sprintf(fnameptr, "%s", ext);
}
size_t i;
for (i=0; i < maxLen; ++i, tmp += 3)
- sprintf(tmp, "%02x ", data[i]);
+ sprintf(tmp, "%02x ", (unsigned int) data[i]);
return buf;
}
for (size_t out_index=0; out_index < max_len; out_index++) {
// set character - (should be binary but verify it isn't more than 1 digit)
if (data[in_index]<10)
- sprintf(tmp++, "%u", data[in_index]);
+ sprintf(tmp++, "%u", (unsigned int) data[in_index]);
// check if a line break is needed and we have room to print it in our array
if ( (breaks > 0) && !((in_index+1) % breaks) && (out_index+1 != max_len) ) {
// increment and print line break
{
byte = b[i] & (1<<j);
byte >>= j;
- sprintf(tmp, "%u", byte);
+ sprintf(tmp, "%u", (unsigned int)byte);
tmp++;
}
}
{
for(i= x= 0 ; i < 4 ; ++i)
x += ( source[i] << (3 - i));
- sprintf(target,"%X", x);
+ sprintf(target,"%X", (unsigned int)x);
++target;
source += 4;
j -= 4;
int32_t le24toh (uint8_t data[3]) {
return (data[2] << 16) | (data[1] << 8) | data[0];
}
+uint32_t le32toh (uint8_t *data) {
+ return (uint32_t)( (data[3]<<24) | (data[2]<<16) | (data[1]<<8) | data[0]);
+}
// RotateLeft - Ultralight, Desfire, works on byte level
// 00-01-02 >> 01-02-00
//-----------------------------------------------------------------------------
#include <stdio.h>
-#include <stdint.h>
-#include <stdio.h>
+#include <stdint.h> //included in data.h
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <time.h>
-#include "data.h"
+#include "data.h" //for FILE_PATH_SIZE
#ifndef ROTR
# define ROTR(x,n) (((uintmax_t)(x) >> (n)) | ((uintmax_t)(x) << ((sizeof(x) * 8) - (n))))
void xor(unsigned char *dst, unsigned char *src, size_t len);
int32_t le24toh(uint8_t data[3]);
+uint32_t le32toh (uint8_t *data);
void rol(uint8_t *data, const size_t len);
/* This is the default version.c file that Makefile.common falls back to if perl is not available */
const struct version_information __attribute__((section(".version_information"))) version_information = {
VERSION_INFORMATION_MAGIC,
- 1, /* version version 1 */
+ 1, /* version 1 */
0, /* version information not present */
2, /* cleanliness couldn't be determined */
/* Remaining fields: zero */
//-----------------------------------------------------------------------------
#include <stdlib.h>
-#include <string.h>
#include "lfdemod.h"
-#include "common.h"
+#include <string.h>
-//un_comment to allow debug print calls when used not on device
+//to allow debug print calls when used not on device
void dummy(char *fmt, ...){}
#ifndef ON_DEVICE
// by marshmellow
// takes a array of binary values, start position, length of bits per parity (includes parity bit),
-// Parity Type (1 for odd; 0 for even; 2 Always 1's), and binary Length (length to run)
+// Parity Type (1 for odd; 0 for even; 2 for Always 1's; 3 for Always 0's), and binary Length (length to run)
size_t removeParity(uint8_t *BitStream, size_t startIdx, uint8_t pLen, uint8_t pType, size_t bLen)
{
uint32_t parityWd = 0;
}
j--; // overwrite parity with next data
// if parity fails then return 0
- if (pType == 2) { // then marker bit which should be a 1
- if (!BitStream[j]) return 0;
- } else {
- if (parityTest(parityWd, pLen, pType) == 0) return 0;
+ switch (pType) {
+ case 3: if (BitStream[j]==1) {return 0;} break; //should be 0 spacer bit
+ case 2: if (BitStream[j]==0) {return 0;} break; //should be 1 spacer bit
+ default: if (parityTest(parityWd, pLen, pType) == 0) {return 0;} break; //test parity
}
bitCnt+=(pLen-1);
parityWd = 0;
// by marshmellow
// takes a array of binary values, length of bits per parity (includes parity bit),
-// Parity Type (1 for odd; 0 for even; 2 Always 1's), and binary Length (length to run)
+// Parity Type (1 for odd; 0 for even; 2 Always 1's; 3 Always 0's), and binary Length (length to run)
+// Make sure *dest is long enough to store original sourceLen + #_of_parities_to_be_added
size_t addParity(uint8_t *BitSource, uint8_t *dest, uint8_t sourceLen, uint8_t pLen, uint8_t pType)
{
uint32_t parityWd = 0;
dest[j++] = (BitSource[word+bit]);
}
// if parity fails then return 0
- if (pType == 2) { // then marker bit which should be a 1
- dest[j++]=1;
- } else {
- dest[j++] = parityTest(parityWd, pLen-1, pType) ^ 1;
+ switch (pType) {
+ case 3: dest[j++]=0; break; // marker bit which should be a 0
+ case 2: dest[j++]=1; break; // marker bit which should be a 1
+ default:
+ dest[j++] = parityTest(parityWd, pLen-1, pType) ^ 1;
+ break;
}
bitCnt += pLen;
parityWd = 0;
if (smplCnt > clk-(clk/4)-1) { //full clock
if (smplCnt > clk + (clk/4)+1) { //too many samples
errCnt++;
+ if (g_debugMode==2) prnt("DEBUG ASK: Modulation Error at: %u", i);
BinStream[bitCnt++]=7;
} else if (waveHigh) {
BinStream[bitCnt++] = invert;
//by marshmellow
void askAmp(uint8_t *BitStream, size_t size)
{
+ uint8_t Last = 128;
for(size_t i = 1; i<size; i++){
if (BitStream[i]-BitStream[i-1]>=30) //large jump up
- BitStream[i]=127;
- else if(BitStream[i]-BitStream[i-1]<=-20) //large jump down
- BitStream[i]=-127;
+ Last = 255;
+ else if(BitStream[i-1]-BitStream[i]>=20) //large jump down
+ Last = 0;
+
+ BitStream[i-1] = Last;
}
return;
}
if (*clk==0 || start < 0) return -3;
if (*invert != 1) *invert = 0;
if (amp==1) askAmp(BinStream, *size);
- if (g_debugMode==2) prnt("DEBUG: clk %d, beststart %d", *clk, start);
+ if (g_debugMode==2) prnt("DEBUG ASK: clk %d, beststart %d", *clk, start);
uint8_t initLoopMax = 255;
if (initLoopMax > *size) initLoopMax = *size;
size_t errCnt = 0;
// if clean clipped waves detected run alternate demod
if (DetectCleanAskWave(BinStream, *size, high, low)) {
- if (g_debugMode==2) prnt("DEBUG: Clean Wave Detected");
+ if (g_debugMode==2) prnt("DEBUG ASK: Clean Wave Detected - using clean wave demod");
errCnt = cleanAskRawDemod(BinStream, size, *clk, *invert, high, low);
if (askType) //askman
return manrawdecode(BinStream, size, 0);
else //askraw
return errCnt;
}
+ if (g_debugMode==2) prnt("DEBUG ASK: Weak Wave Detected - using weak wave demod");
- int lastBit; //set first clock check - can go negative
+ int lastBit; //set first clock check - can go negative
size_t i, bitnum = 0; //output counter
uint8_t midBit = 0;
uint8_t tol = 0; //clock tolerance adjust - waves will be accepted as within the clock if they fall + or - this value + clock from last valid wave
- if (*clk <= 32) tol = 1; //clock tolerance may not be needed anymore currently set to + or - 1 but could be increased for poor waves or removed entirely
- size_t MaxBits = 3072;
+ if (*clk <= 32) tol = 1; //clock tolerance may not be needed anymore currently set to + or - 1 but could be increased for poor waves or removed entirely
+ size_t MaxBits = 3072; //max bits to collect
lastBit = start - *clk;
for (i = start; i < *size; ++i) {
BinStream[bitnum++] = *invert ^ 1;
} else if (i-lastBit >= *clk+tol) {
if (bitnum > 0) {
+ if (g_debugMode==2) prnt("DEBUG ASK: Modulation Error at: %u", i);
BinStream[bitnum++]=7;
errCnt++;
}
//return start position
return (int) startIdx;
}
- return -5;
+ return -5; //spacer bits not found - not a valid gproxII
}
-//translate wave to 11111100000 (1 for each short wave 0 for each long wave)
+//translate wave to 11111100000 (1 for each short wave [higher freq] 0 for each long wave [lower freq])
size_t fsk_wave_demod(uint8_t * dest, size_t size, uint8_t fchigh, uint8_t fclow)
{
size_t last_transition = 0;
size_t numBits = 0;
// count cycles between consecutive lo-hi transitions, there should be either 8 (fc/8)
- // or 10 (fc/10) cycles but in practice due to noise etc we may end up with with anywhere
+ // or 10 (fc/10) cycles but in practice due to noise etc we may end up with anywhere
// between 7 to 11 cycles so fuzz it by treat anything <9 as 8 and anything else as 10
+ // (could also be fc/5 && fc/7 for fsk1 = 4-9)
for(idx = 161; idx < size-20; idx++) {
// threshold current value
else dest[idx] = 1;
// Check for 0->1 transition
- if (dest[idx-1] < dest[idx]) { // 0 -> 1 transition
+ if (dest[idx-1] < dest[idx]) {
preLastSample = LastSample;
LastSample = currSample;
currSample = idx-last_transition;
- if (currSample < (fclow-2)){ //0-5 = garbage noise (or 0-3)
+ if (currSample < (fclow-2)) { //0-5 = garbage noise (or 0-3)
//do nothing with extra garbage
- } else if (currSample < (fchigh-1)) { //6-8 = 8 sample waves or 3-6 = 5
+ } else if (currSample < (fchigh-1)) { //6-8 = 8 sample waves (or 3-6 = 5)
+ //correct previous 9 wave surrounded by 8 waves (or 6 surrounded by 5)
if (LastSample > (fchigh-2) && (preLastSample < (fchigh-1) || preLastSample == 0 )){
- dest[numBits-1]=1; //correct previous 9 wave surrounded by 8 waves
+ dest[numBits-1]=1;
}
dest[numBits++]=1;
- } else if (currSample > (fchigh) && !numBits) { //12 + and first bit = garbage
+ } else if (currSample > (fchigh) && !numBits) { //12 + and first bit = unusable garbage
//do nothing with beginning garbage
- } else if (currSample == (fclow+1) && LastSample == (fclow-1)) { // had a 7 then a 9 should be two 8's
+ } else if (currSample == (fclow+1) && LastSample == (fclow-1)) { // had a 7 then a 9 should be two 8's (or 4 then a 6 should be two 5's)
dest[numBits++]=1;
- } else { //9+ = 10 sample waves
+ } else { //9+ = 10 sample waves (or 6+ = 7)
dest[numBits++]=0;
}
last_transition = idx;
}
//translate 11111100000 to 10
+//rfLen = clock, fchigh = larger field clock, fclow = smaller field clock
size_t aggregate_bits(uint8_t *dest, size_t size, uint8_t rfLen,
uint8_t invert, uint8_t fchigh, uint8_t fclow)
{
uint32_t n=1;
for( idx=1; idx < size; idx++) {
n++;
- if (dest[idx]==lastval) continue;
+ if (dest[idx]==lastval) continue; //skip until we hit a transition
+ //find out how many bits (n) we collected
//if lastval was 1, we have a 1->0 crossing
if (dest[idx-1]==1) {
n = (n * fclow + rfLen/2) / rfLen;
}
if (n == 0) n = 1;
+ //add to our destination the bits we collected
memset(dest+numBits, dest[idx-1]^invert , n);
numBits += n;
n=0;
return (int) startIdx;
}
+// find presco preamble 0x10D in already demoded data
+int PrescoDemod(uint8_t *dest, size_t *size) {
+ //make sure buffer has data
+ if (*size < 64*2) return -2;
+
+ size_t startIdx = 0;
+ uint8_t preamble[] = {1,0,0,0,0,1,1,0,1,0,0,0,0,0,0,0,0,0,0,0};
+ uint8_t errChk = preambleSearch(dest, preamble, sizeof(preamble), size, &startIdx);
+ if (errChk == 0) return -4; //preamble not found
+ //return start position
+ return (int) startIdx;
+}
+
// Ask/Biphase Demod then try to locate an ISO 11784/85 ID
// BitStream must contain previously askrawdemod and biphasedemoded data
int FDXBdemodBI(uint8_t *dest, size_t *size)
return (int) startidx;
}
-// by marshmellow - demodulate NRZ wave
+// by marshmellow - demodulate NRZ wave - requires a read with strong signal
// peaks invert bit (high=1 low=0) each clock cycle = 1 bit determined by last peak
int nrzRawDemod(uint8_t *dest, size_t *size, int *clk, int *invert){
if (justNoise(dest, *size)) return -1;
numBits += (firstFullWave / *clock);
//set start of wave as clock align
lastClkBit = firstFullWave;
- //PrintAndLog("DEBUG: firstFullWave: %d, waveLen: %d",firstFullWave,fullWaveLen);
- //PrintAndLog("DEBUG: clk: %d, lastClkBit: %d", *clock, lastClkBit);
+ if (g_debugMode==2) prnt("DEBUG PSK: firstFullWave: %u, waveLen: %u",firstFullWave,fullWaveLen);
+ if (g_debugMode==2) prnt("DEBUG: clk: %d, lastClkBit: %u, fc: %u", *clock, lastClkBit,(unsigned int) fc);
waveStart = 0;
dest[numBits++] = curPhase; //set first read bit
for (i = firstFullWave + fullWaveLen - 1; i < *size-3; i++){
*size = numBits;
return errCnt;
}
+
+//by marshmellow
+//attempt to identify a Sequence Terminator in ASK modulated raw wave
+bool DetectST(uint8_t buffer[], size_t *size, int *foundclock) {
+ size_t bufsize = *size;
+ //need to loop through all samples and identify our clock, look for the ST pattern
+ uint8_t fndClk[] = {8,16,32,40,50,64,128};
+ int clk = 0;
+ int tol = 0;
+ int i, j, skip, start, end, low, high, minClk, waveStart;
+ bool complete = false;
+ int tmpbuff[bufsize / 64];
+ int waveLen[bufsize / 64];
+ size_t testsize = (bufsize < 512) ? bufsize : 512;
+ int phaseoff = 0;
+ high = low = 128;
+ memset(tmpbuff, 0, sizeof(tmpbuff));
+
+ if ( getHiLo(buffer, testsize, &high, &low, 80, 80) == -1 ) {
+ if (g_debugMode==2) prnt("DEBUG STT: just noise detected - quitting");
+ return false; //just noise
+ }
+ i = 0;
+ j = 0;
+ minClk = 255;
+ // get to first full low to prime loop and skip incomplete first pulse
+ while ((buffer[i] < high) && (i < bufsize))
+ ++i;
+ while ((buffer[i] > low) && (i < bufsize))
+ ++i;
+ skip = i;
+
+ // populate tmpbuff buffer with pulse lengths
+ while (i < bufsize) {
+ // measure from low to low
+ while ((buffer[i] > low) && (i < bufsize))
+ ++i;
+ start= i;
+ while ((buffer[i] < high) && (i < bufsize))
+ ++i;
+ //first high point for this wave
+ waveStart = i;
+ while ((buffer[i] > low) && (i < bufsize))
+ ++i;
+ if (j >= (bufsize/64)) {
+ break;
+ }
+ waveLen[j] = i - waveStart; //first high to first low
+ tmpbuff[j++] = i - start;
+ if (i-start < minClk && i < bufsize) {
+ minClk = i - start;
+ }
+ }
+ // set clock - might be able to get this externally and remove this work...
+ if (!clk) {
+ for (uint8_t clkCnt = 0; clkCnt<7; clkCnt++) {
+ tol = fndClk[clkCnt]/8;
+ if (minClk >= fndClk[clkCnt]-tol && minClk <= fndClk[clkCnt]+1) {
+ clk=fndClk[clkCnt];
+ break;
+ }
+ }
+ // clock not found - ERROR
+ if (!clk) {
+ if (g_debugMode==2) prnt("DEBUG STT: clock not found - quitting");
+ return false;
+ }
+ } else tol = clk/8;
+
+ *foundclock = clk;
+
+ // look for Sequence Terminator - should be pulses of clk*(1 or 1.5), clk*2, clk*(1.5 or 2)
+ start = -1;
+ for (i = 0; i < j - 4; ++i) {
+ skip += tmpbuff[i];
+ if (tmpbuff[i] >= clk*1-tol && tmpbuff[i] <= (clk*2)+tol && waveLen[i] < clk+tol) { //1 to 2 clocks depending on 2 bits prior
+ if (tmpbuff[i+1] >= clk*2-tol && tmpbuff[i+1] <= clk*2+tol && waveLen[i+1] > clk*3/2-tol) { //2 clocks and wave size is 1 1/2
+ if (tmpbuff[i+2] >= (clk*3)/2-tol && tmpbuff[i+2] <= clk*2+tol && waveLen[i+2] > clk-tol) { //1 1/2 to 2 clocks and at least one full clock wave
+ if (tmpbuff[i+3] >= clk*1-tol && tmpbuff[i+3] <= clk*2+tol) { //1 to 2 clocks for end of ST + first bit
+ start = i + 3;
+ break;
+ }
+ }
+ }
+ }
+ }
+ // first ST not found - ERROR
+ if (start < 0) {
+ if (g_debugMode==2) prnt("DEBUG STT: first STT not found - quitting");
+ return false;
+ }
+ if (waveLen[i+2] > clk*1+tol)
+ phaseoff = 0;
+ else
+ phaseoff = clk/2;
+
+ // skip over the remainder of ST
+ skip += clk*7/2; //3.5 clocks from tmpbuff[i] = end of st - also aligns for ending point
+
+ // now do it again to find the end
+ end = skip;
+ for (i += 3; i < j - 4; ++i) {
+ end += tmpbuff[i];
+ if (tmpbuff[i] >= clk*1-tol && tmpbuff[i] <= (clk*2)+tol) { //1 to 2 clocks depending on 2 bits prior
+ if (tmpbuff[i+1] >= clk*2-tol && tmpbuff[i+1] <= clk*2+tol && waveLen[i+1] > clk*3/2-tol) { //2 clocks and wave size is 1 1/2
+ if (tmpbuff[i+2] >= (clk*3)/2-tol && tmpbuff[i+2] <= clk*2+tol && waveLen[i+2] > clk-tol) { //1 1/2 to 2 clocks and at least one full clock wave
+ if (tmpbuff[i+3] >= clk*1-tol && tmpbuff[i+3] <= clk*2+tol) { //1 to 2 clocks for end of ST + first bit
+ complete = true;
+ break;
+ }
+ }
+ }
+ }
+ }
+ end -= phaseoff;
+ //didn't find second ST - ERROR
+ if (!complete) {
+ if (g_debugMode==2) prnt("DEBUG STT: second STT not found - quitting");
+ return false;
+ }
+ if (g_debugMode==2) prnt("DEBUG STT: start of data: %d end of data: %d, datalen: %d, clk: %d, bits: %d, phaseoff: %d", skip, end, end-skip, clk, (end-skip)/clk, phaseoff);
+ //now begin to trim out ST so we can use normal demod cmds
+ start = skip;
+ size_t datalen = end - start;
+ // check validity of datalen (should be even clock increments) - use a tolerance of up to 1/8th a clock
+ if (datalen % clk > clk/8) {
+ if (g_debugMode==2) prnt("DEBUG STT: datalen not divisible by clk: %u %% %d = %d - quitting", datalen, clk, datalen % clk);
+ return false;
+ } else {
+ // padd the amount off - could be problematic... but shouldn't happen often
+ datalen += datalen % clk;
+ }
+ // if datalen is less than one t55xx block - ERROR
+ if (datalen/clk < 8*4) {
+ if (g_debugMode==2) prnt("DEBUG STT: datalen is less than 1 full t55xx block - quitting");
+ return false;
+ }
+ size_t dataloc = start;
+ size_t newloc = 0;
+ i=0;
+ // warning - overwriting buffer given with raw wave data with ST removed...
+ while ( dataloc < bufsize-(clk/2) ) {
+ //compensate for long high at end of ST not being high due to signal loss... (and we cut out the start of wave high part)
+ if (buffer[dataloc]<high && buffer[dataloc]>low && buffer[dataloc+3]<high && buffer[dataloc+3]>low) {
+ for(i=0; i < clk/2-tol; ++i) {
+ buffer[dataloc+i] = high+5;
+ }
+ }
+ for (i=0; i<datalen; ++i) {
+ if (i+newloc < bufsize) {
+ if (i+newloc < dataloc)
+ buffer[i+newloc] = buffer[dataloc];
+
+ dataloc++;
+ }
+ }
+ newloc += i;
+ //skip next ST - we just assume it will be there from now on...
+ dataloc += clk*4;
+ }
+ *size = newloc;
+ return true;
+}
#ifndef LFDEMOD_H__
#define LFDEMOD_H__
-#include <stdint.h>
+#include <stdint.h> // for uint_32+
+#include <stdbool.h> // for bool
//generic
size_t addParity(uint8_t *BitSource, uint8_t *dest, uint8_t sourceLen, uint8_t pLen, uint8_t pType);
int DetectNRZClock(uint8_t dest[], size_t size, int clock);
int DetectPSKClock(uint8_t dest[], size_t size, int clock);
int DetectStrongAskClock(uint8_t dest[], size_t size, uint8_t high, uint8_t low);
+bool DetectST(uint8_t buffer[], size_t *size, int *foundclock);
int fskdemod(uint8_t *dest, size_t size, uint8_t rfLen, uint8_t invert, uint8_t fchigh, uint8_t fclow);
int getHiLo(uint8_t *BitStream, size_t size, int *high, int *low, uint8_t fuzzHi, uint8_t fuzzLo);
uint32_t manchesterEncode2Bytes(uint16_t datain);
int ParadoxdemodFSK(uint8_t *dest, size_t *size, uint32_t *hi2, uint32_t *hi, uint32_t *lo);
int PyramiddemodFSK(uint8_t *dest, size_t *size);
int VikingDemod_AM(uint8_t *dest, size_t *size);
-
+int PrescoDemod(uint8_t *dest, size_t *size);
#endif
#define ISO14443A_CMD_WUPA 0x52
#define ISO14443A_CMD_ANTICOLL_OR_SELECT 0x93
#define ISO14443A_CMD_ANTICOLL_OR_SELECT_2 0x95
+#define ISO14443A_CMD_ANTICOLL_OR_SELECT_3 0x97
#define ISO14443A_CMD_WRITEBLOCK 0xA0 // or 0xA2 ?
#define ISO14443A_CMD_HALT 0x50
#define ISO14443A_CMD_RATS 0xE0
-#define MIFARE_AUTH_KEYA 0x60
-#define MIFARE_AUTH_KEYB 0x61
-#define MIFARE_MAGICWUPC1 0x40
-#define MIFARE_MAGICWUPC2 0x43
-#define MIFARE_MAGICWIPEC 0x41
+#define MIFARE_AUTH_KEYA 0x60
+#define MIFARE_AUTH_KEYB 0x61
+#define MIFARE_MAGICWUPC1 0x40
+#define MIFARE_MAGICWUPC2 0x43
+#define MIFARE_MAGICWIPEC 0x41
#define MIFARE_CMD_INC 0xC0
#define MIFARE_CMD_DEC 0xC1
#define MIFARE_CMD_RESTORE 0xC2
#define MIFARE_CMD_TRANSFER 0xB0
+#define MIFARE_EV1_PERSONAL_UID 0x40
+#define MIFARE_EV1_SETMODE 0x43
+
+
#define MIFARE_ULC_WRITE 0xA2
//#define MIFARE_ULC__COMP_WRITE 0xA0
#define MIFARE_ULC_AUTH_1 0x1A
#ifndef MAX
# define MAX(a, b) (((a) > (b)) ? (a) : (b))
#endif
+#ifndef ABS
+# define ABS(a) ( ((a)<0) ? -(a) : (a) )
+#endif
+
#define RAMFUNC __attribute((long_call, section(".ramfunc")))
//-----------------------------------------------------------------------------
// Hitag2 type prototyping
//-----------------------------------------------------------------------------
+// HitagS added
+//-----------------------------------------------------------------------------
#ifndef _HITAG2_H_
#define _HITAG2_H_
typedef enum {
+ RHTSF_CHALLENGE = 01,
+ RHTSF_KEY = 02,
+ WHTSF_CHALLENGE = 03,
+ WHTSF_KEY = 04,
RHT2F_PASSWORD = 21,
RHT2F_AUTHENTICATE = 22,
RHT2F_CRYPTO = 23,
typedef struct {
byte_t NrAr[8];
+ byte_t data[4];
} PACKED rht2d_authenticate;
typedef struct {
- byte_t key[4];
+ byte_t key[6];
+ byte_t data[4];
} PACKED rht2d_crypto;
typedef union {
--- /dev/null
+//-----------------------------------------------------------------------------
+// This code is licensed to you under the terms of the GNU GPL, version 2 or,
+// at your option, any later version. See the LICENSE.txt file for the text of
+// the license.
+//-----------------------------------------------------------------------------
+// HitagS emulation (preliminary test version)
+//
+// (c) 2016 Oguzhan Cicek, Hendrik Schwartke, Ralf Spenneberg
+// <info@os-s.de>
+//-----------------------------------------------------------------------------
+
+
+#include <stdlib.h>
+#include <string.h>
+#include <hitag2.h>
+
+#ifndef _HITAGS_H_
+#define _HITAGS_H_
+
+typedef enum PROTO_STATE {READY=0,INIT,AUTHENTICATE,SELECTED,QUIET,TTF,FAIL} PSTATE; //protocol-state
+typedef enum TAG_STATE {NO_OP=0,READING_PAGE,WRITING_PAGE_ACK,WRITING_PAGE_DATA,WRITING_BLOCK_DATA} TSATE; //tag-state
+typedef enum SOF_TYPE {STANDARD=0,ADVANCED,FAST_ADVANCED,ONE,NO_BITS} stype; //number of start-of-frame bits
+
+struct hitagS_tag {
+ PSTATE pstate; //protocol-state
+ TSATE tstate; //tag-state
+ uint32_t uid;
+ uint32_t pages[16][4];
+ uint64_t key;
+ byte_t pwdl0,pwdl1,pwdh0;
+ //con0
+ int max_page;
+ stype mode;
+ //con1
+ bool auth; //0=Plain 1=Auth
+ bool TTFC; //Transponder Talks first coding. 0=Manchester 1=Biphase
+ int TTFDR; //data rate in TTF Mode
+ int TTFM; //the number of pages that are sent to the RWD
+ bool LCON; //0=con1/2 read write 1=con1 read only and con2 OTP
+ bool LKP; //0=page2/3 read write 1=page2/3 read only in Plain mode and no access in authenticate mode
+ //con2
+ //0=read write 1=read only
+ bool LCK7; //page4/5
+ bool LCK6; //page6/7
+ bool LCK5; //page8-11
+ bool LCK4; //page12-15
+ bool LCK3; //page16-23
+ bool LCK2; //page24-31
+ bool LCK1; //page32-47
+ bool LCK0; //page48-63
+} ;
+
+#endif
#define CMD_SIMULATE_HITAG 0x0371
#define CMD_READER_HITAG 0x0372
+#define CMD_SIMULATE_HITAG_S 0x0368
+#define CMD_TEST_HITAGS_TRACES 0x0367
+#define CMD_READ_HITAG_S 0x0373
+#define CMD_WR_HITAG_S 0x0375
+#define CMD_EMU_HITAG_S 0x0376
+
+
#define CMD_SIMULATE_TAG_ISO_14443B 0x0381
#define CMD_SNOOP_ISO_14443B 0x0382
#define CMD_SNOOP_ISO_14443a 0x0383
//Mifare simulation flags
-#define FLAG_INTERACTIVE 0x01
-#define FLAG_4B_UID_IN_DATA 0x02
-#define FLAG_7B_UID_IN_DATA 0x04
-#define FLAG_NR_AR_ATTACK 0x08
+#define FLAG_INTERACTIVE 0x01
+#define FLAG_4B_UID_IN_DATA 0x02
+#define FLAG_7B_UID_IN_DATA 0x04
+#define FLAG_10B_UID_IN_DATA 0x08
+#define FLAG_NR_AR_ATTACK 0x10
//Iclass reader flags
#define FLAG_ICLASS_READER_CEDITKEY 0x40
+//hw tune args
+#define FLAG_TUNE_LF 1
+#define FLAG_TUNE_HF 2
+#define FLAG_TUNE_ALL 3
+
// CMD_DEVICE_INFO response packet has flags in arg[0], flag definitions:
/* Whether a bootloader that understands the common_area is present */
generic: $(ALL)
linux:
- $(MAKE) $(ALL) SYSCFLAGS="-DLUA_USE_LINUX" SYSLIBS="-Wl,-E -ldl -lreadline"
+ $(MAKE) $(ALL) SYSCFLAGS="-DLUA_USE_LINUX" SYSLIBS="-Wl,-E -ldl -lreadline -ltermcap -lncurses"
macosx:
$(MAKE) $(ALL) SYSCFLAGS="-DLUA_USE_MACOSX" SYSLIBS="-lreadline"
./mfkey64 9c599b32 82a4166c a1e458ce 6eea41e0 5cadf439
+
+
+### Communication decryption
+
+
+RDR 26
+TAG 04 00
+RDR 93 20
+TAG 14 57 9f 69 b5
+RDR 93 70 14 57 9f 69 b5 2e 51
+TAG 08 b6 dd
+RDR 60 14 50 2d
+TAG ce 84 42 61
+RDR f8 04 9c cb 05 25 c8 4f
+TAG 94 31 cc 40
+RDR 70 93 df 99
+TAG 99 72 42 8c e2 e8 52 3f 45 6b 99 c8 31 e7 69 dc ed 09
+RDR 8c a6 82 7b
+TAG ab 79 7f d3 69 e8 b9 3a 86 77 6b 40 da e3 ef 68 6e fd
+RDR c3 c3 81 ba
+TAG 49 e2 c9 de f4 86 8d 17 77 67 0e 58 4c 27 23 02 86 f4
+RDR fb dc d7 c1
+TAG 4a bd 96 4b 07 d3 56 3a a0 66 ed 0a 2e ac 7f 63 12 bf
+RDR 9f 91 49 ea
+
+
+./mfkey64 14579f69 ce844261 f8049ccb 0525c84f 9431cc40 7093df99 9972428ce2e8523f456b99c831e769dced09 8ca6827b ab797fd369e8b93a86776b40dae3ef686efd c3c381ba 49e2c9def4868d1777670e584c27230286f4 fbdcd7c1 4abd964b07d3563aa066ed0a2eac7f6312bf 9f9149ea
+
+Recovering key for:
+ uid: 14579f69
+ nt: ce844261
+ {nr}: f8049ccb
+ {ar}: 0525c84f
+ {at}: 9431cc40
+{enc0}: 7093df99
+{enc1}: 9972428ce2e8523f456b99c831e769dced09
+{enc2}: 8ca6827b
+{enc3}: ab797fd369e8b93a86776b40dae3ef686efd
+{enc4}: c3c381ba
+{enc5}: 49e2c9def4868d1777670e584c27230286f4
+{enc6}: fbdcd7c1
+{enc7}: 4abd964b07d3563aa066ed0a2eac7f6312bf
+{enc8}: 9f9149ea
+
+LFSR succesors of the tag challenge:
+ nt': 76d4468d
+ nt'': d5f3c476
+
+Keystream used to generate {ar} and {at}:
+ ks2: 73f18ec2
+ ks3: 41c20836
+
+Decrypted communication:
+{dec0}: 3014a7fe
+{dec1}: c26935cfdb95c4b4a27a84b8217ae9e48217
+{dec2}: 30152eef
+{dec3}: 493167c536c30f8e220b09675687067d4b31
+{dec4}: 3016b5dd
+{dec5}: 493167c536c30f8e220b09675687067d4b31
+{dec6}: 30173ccc
+{dec7}: 0000000000007e178869000000000000c4f2
+{dec8}: 61148834
+
+Found Key: [091e639cb715]
\ No newline at end of file
// Test-file: test2.c
#include "crapto1.h"
#include <stdio.h>
+#include <string.h>
int main (int argc, char *argv[]) {
struct Crypto1State *revstate;
printf("MIFARE Classic key recovery - based 64 bits of keystream\n");
printf("Recover key from only one complete authentication!\n\n");
- if (argc < 6) {
- printf(" syntax: %s <uid> <nt> <{nr}> <{ar}> <{at}>\n\n",argv[0]);
+ if (argc < 6 ) {
+ printf(" syntax: %s <uid> <nt> <{nr}> <{ar}> <{at}> [enc] [enc...]\n\n", argv[0]);
return 1;
}
- sscanf(argv[1],"%x",&uid);
- sscanf(argv[2],"%x",&nt);
- sscanf(argv[3],"%x",&nr_enc);
- sscanf(argv[4],"%x",&ar_enc);
- sscanf(argv[5],"%x",&at_enc);
+ int encc = argc - 6;
+ int enclen[encc];
+ uint8_t enc[encc][120];
+ sscanf(argv[1], "%x", &uid);
+ sscanf(argv[2], "%x", &nt);
+ sscanf(argv[3], "%x", &nr_enc);
+ sscanf(argv[4], "%x", &ar_enc);
+ sscanf(argv[5], "%x", &at_enc);
+ for (int i = 0; i < encc; i++) {
+ enclen[i] = strlen(argv[i + 6]) / 2;
+ for (int i2 = 0; i2 < enclen[i]; i2++) {
+ sscanf(argv[i+6] + i2*2,"%2x", (uint8_t*)&enc[i][i2]);
+ }
+ }
printf("Recovering key for:\n");
- printf(" uid: %08x\n",uid);
- printf(" nt: %08x\n",nt);
- printf(" {nr}: %08x\n",nr_enc);
- printf(" {ar}: %08x\n",ar_enc);
- printf(" {at}: %08x\n",at_enc);
-/*
+ printf(" uid: %08x\n", uid);
+ printf(" nt: %08x\n", nt);
+ printf(" {nr}: %08x\n", nr_enc);
+ printf(" {ar}: %08x\n", ar_enc);
+ printf(" {at}: %08x\n", at_enc);
+ for (int i = 0; i < encc; i++) {
+ printf("{enc%d}: ", i);
+ for (int i2 = 0; i2 < enclen[i]; i2++) {
+ printf("%02x", enc[i][i2]);
+ }
+ printf("\n");
+ }
+
+
+ /*
uint32_t uid = 0x9c599b32;
uint32_t tag_challenge = 0x82a4166c;
uint32_t nr_enc = 0xa1e458ce;
uint32_t reader_response = 0x6eea41e0;
uint32_t tag_response = 0x5cadf439;
*/
- // Generate lfsr succesors of the tag challenge
+ // Generate lfsr succesors of the tag challenge
printf("\nLFSR succesors of the tag challenge:\n");
printf(" nt': %08x\n",prng_successor(nt, 64));
printf(" nt'': %08x\n",prng_successor(nt, 96));
printf(" ks3: %08x\n",ks3);
revstate = lfsr_recovery64(ks2, ks3);
+
+ // Decrypting communication using keystream if presented
+ if (argc > 6 ) {
+ printf("\nDecrypted communication:\n");
+ uint8_t ks4;
+ int rollb = 0;
+ for (int i = 0; i < encc; i++) {
+ printf("{dec%d}: ", i);
+ for (int i2 = 0; i2 < enclen[i]; i2++) {
+ ks4 = crypto1_byte(revstate, 0, 0);
+ printf("%02x", ks4 ^ enc[i][i2]);
+ rollb += 1;
+ }
+ printf("\n");
+ }
+ for (int i = 0; i < rollb; i++) {
+ lfsr_rollback_byte(revstate, 0, 0);
+ }
+ }
+
lfsr_rollback_word(revstate, 0, 0);
lfsr_rollback_word(revstate, 0, 0);
lfsr_rollback_word(revstate, nr_enc, 1);