From 0472d76de484018f2d11425417f3078a08a2e3d3 Mon Sep 17 00:00:00 2001 From: etmatrix Date: Fri, 23 Oct 2015 15:29:12 +0200 Subject: [PATCH 1/1] The great work of Enio hf snoop is now ported into latest version in git you can find original work here https://github.com/EnioArda/proxmark3 --- armsrc/Makefile | 5 +-- armsrc/appmain.c | 7 +++- armsrc/apps.h | 1 + armsrc/fpgaloader.h | 1 + armsrc/hfsnoop.c | 74 ++++++++++++++++++++++++++++++++++++++++++ client/cmdhf.c | 11 ++++++- fpga/Makefile | 2 +- fpga/fpga_hf.bit | Bin 42175 -> 42175 bytes fpga/fpga_hf.v | 34 ++++++++++++------- fpga/fpga_lf.bit | Bin 42175 -> 42175 bytes fpga/hi_sniffer.v | 77 ++++++++++++++++++++++++++++++++++++++++++++ include/usb_cmd.h | 2 ++ 12 files changed, 198 insertions(+), 16 deletions(-) create mode 100644 armsrc/hfsnoop.c create mode 100644 fpga/hi_sniffer.v diff --git a/armsrc/Makefile b/armsrc/Makefile index a59fa073..3c6c14c6 100644 --- a/armsrc/Makefile +++ b/armsrc/Makefile @@ -10,7 +10,7 @@ APP_INCLUDES = apps.h #remove one of the following defines and comment out the relevant line #in the next section to remove that particular feature from compilation -APP_CFLAGS = -DWITH_ISO14443a_StandAlone -DWITH_LF -DWITH_ISO15693 -DWITH_ISO14443a -DWITH_ISO14443b -DWITH_ICLASS -DWITH_LEGICRF -DWITH_HITAG -DWITH_CRC -DON_DEVICE \ +APP_CFLAGS = -DWITH_ISO14443a_StandAlone -DWITH_LF -DWITH_ISO15693 -DWITH_ISO14443a -DWITH_ISO14443b -DWITH_ICLASS -DWITH_LEGICRF -DWITH_HITAG -DWITH_CRC -DON_DEVICE -DWITH_HFSNOOP \ -fno-strict-aliasing -ffunction-sections -fdata-sections #-DWITH_LCD @@ -60,7 +60,8 @@ ARMSRC = fpgaloader.c \ legic_prng.c \ iclass.c \ BigBuf.c \ - optimized_cipher.c + optimized_cipher.c \ + hfsnoop.c # Do not move this inclusion before the definition of {THUMB,ASM,ARM}SRC include ../common/Makefile.common diff --git a/armsrc/appmain.c b/armsrc/appmain.c index 48c9caef..8c2aefbb 100644 --- a/armsrc/appmain.c +++ b/armsrc/appmain.c @@ -1202,6 +1202,11 @@ void UsbPacketReceived(uint8_t *packet, int len) iClass_Clone(c->arg[0], c->arg[1], c->d.asBytes); break; #endif +#ifdef WITH_HFSNOOP + case CMD_HF_SNIFFER: + HfSnoop(c->arg[0], c->arg[1]); + break; +#endif case CMD_BUFF_CLEAR: BigBuf_Clear(); @@ -1338,7 +1343,7 @@ void __attribute__((noreturn)) AppMain(void) AT91C_BASE_PMC->PMC_SCER = AT91C_PMC_PCK0; // PCK0 is PLL clock / 4 = 96Mhz / 4 = 24Mhz AT91C_BASE_PMC->PMC_PCKR[0] = AT91C_PMC_CSS_PLL_CLK | - AT91C_PMC_PRES_CLK_4; + AT91C_PMC_PRES_CLK_4; // 4 for 24Mhz pck0, 2 for 48 MHZ pck0 AT91C_BASE_PIOA->PIO_OER = GPIO_PCK0; // Reset SPI diff --git a/armsrc/apps.h b/armsrc/apps.h index 79c9da86..2cfd31d7 100644 --- a/armsrc/apps.h +++ b/armsrc/apps.h @@ -189,5 +189,6 @@ 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); /// util.h +void HfSnoop(int , int); #endif diff --git a/armsrc/fpgaloader.h b/armsrc/fpgaloader.h index 52d6c677..38724cdb 100644 --- a/armsrc/fpgaloader.h +++ b/armsrc/fpgaloader.h @@ -43,6 +43,7 @@ void SetAdcMuxFor(uint32_t whichGpio); #define FPGA_MAJOR_MODE_HF_READER_RX_XCORR (1<<5) #define FPGA_MAJOR_MODE_HF_SIMULATOR (2<<5) #define FPGA_MAJOR_MODE_HF_ISO14443A (3<<5) +#define FPGA_MAJOR_MODE_HF_SNOOP (4<<5) // BOTH #define FPGA_MAJOR_MODE_OFF (7<<5) // Options for LF_ADC diff --git a/armsrc/hfsnoop.c b/armsrc/hfsnoop.c new file mode 100644 index 00000000..5338bd0d --- /dev/null +++ b/armsrc/hfsnoop.c @@ -0,0 +1,74 @@ +#include "proxmark3.h" +#include "apps.h" +#include "BigBuf.h" +#include "util.h" + +static void RAMFUNC optimizedSnoop(void); + +static void RAMFUNC optimizedSnoop(void) +{ + BigBuf_free(); + int n = BigBuf_max_traceLen() / sizeof(uint16_t); // take all memory + + uint16_t *dest = (uint16_t *)BigBuf_get_addr(); + uint16_t *destend = dest + n; + + AT91C_BASE_SSC->SSC_RFMR = SSC_FRAME_MODE_BITS_IN_WORD(16); // Setting Frame mode, 16 bits per word + // Reading data loop + while(dest <= destend) + { + if(AT91C_BASE_SSC->SSC_SR & AT91C_SSC_RXRDY) + { + *dest = (uint16_t)(AT91C_BASE_SSC->SSC_RHR); + dest = dest + 1; + } + } + //Resetting Frame mode (First set in fpgaloader.c) + AT91C_BASE_SSC->SSC_RFMR = SSC_FRAME_MODE_BITS_IN_WORD(8) | AT91C_SSC_MSBF | SSC_FRAME_MODE_WORDS_PER_TRANSFER(0); +} + +void HfSnoop(int samplesToSkip, int triggersToSkip) +{ + Dbprintf("Skipping first %d sample pairs, Skipping %d triggers.\n", samplesToSkip, triggersToSkip); + bool trigger_cnt; + LED_D_OFF(); + // Select correct configs + FpgaDownloadAndGo(FPGA_BITSTREAM_HF); + // Set up the synchronous serial port + FpgaSetupSsc(); + // connect Demodulated Signal to ADC: + SetAdcMuxFor(GPIO_MUXSEL_HIPKD); + FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_SNOOP); + SpinDelay(100); + + AT91C_BASE_SSC->SSC_RFMR = SSC_FRAME_MODE_BITS_IN_WORD(16); // Setting Frame Mode For better performance on high speed data transfer. + + trigger_cnt = 0; + uint16_t r; + for(;;) { + if(AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_RXRDY)) { + r = (uint16_t)AT91C_BASE_SSC->SSC_RHR; + if (!(trigger_cnt == triggersToSkip) && ( (r >> 8) >= 240)) + { + Dbprintf("Trigger kicked! Value: %d.", r >> 8); + trigger_cnt++; + break; + } + } + } + Dbprintf("Trigger kicked! Value: %d, Dumping Samples Hispeed now.", r >> 8); + int waitcount = samplesToSkip; // lets wait 40000 ticks of pck0 + while(waitcount != 0) { + if(AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_RXRDY)) { + waitcount--; + } + } + + // Snooooop!!! + optimizedSnoop(); + + DbpString("Done."); + FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); + LED_D_OFF(); +} + diff --git a/client/cmdhf.c b/client/cmdhf.c index 8406fe76..34bdc24f 100644 --- a/client/cmdhf.c +++ b/client/cmdhf.c @@ -576,6 +576,14 @@ int CmdHFSearch(const char *Cmd){ return 0; } +int CmdHFSnoop(const char *Cmd) +{ + char * pEnd; + UsbCommand c = {CMD_HF_SNIFFER, {strtol(Cmd, &pEnd,0),strtol(pEnd, &pEnd,0),0}}; + SendCommand(&c); + return 0; +} + static command_t CommandTable[] = { {"help", CmdHelp, 1, "This help"}, @@ -590,7 +598,8 @@ static command_t CommandTable[] = {"tune", CmdHFTune, 0, "Continuously measure HF antenna tuning"}, {"list", CmdHFList, 1, "List protocol data in trace buffer"}, {"search", CmdHFSearch, 1, "Search for known HF tags [preliminary]"}, - {NULL, NULL, 0, NULL} + {"snoop", CmdHFSnoop, 0, " Generic LF/HF Snoop in Testing stage"}, + {NULL, NULL, 0, NULL} }; int CmdHF(const char *Cmd) diff --git a/fpga/Makefile b/fpga/Makefile index fad2ff04..e58d6fc4 100644 --- a/fpga/Makefile +++ b/fpga/Makefile @@ -9,7 +9,7 @@ fpga_hf.ngc: fpga_hf.v fpga.ucf xst_hf.scr util.v hi_simulate.v hi_read_tx.v hi_ $(DELETE) $@ $(XILINX_TOOLS_PREFIX)xst -ifn xst_hf.scr -fpga_lf.ngc: fpga_lf.v fpga.ucf xst_lf.scr util.v clk_divider.v lo_edge_detect.v lo_read.v lo_passthru.v lp20khz_1MSa_iir_filter.v min_max_tracker.v lf_edge_detect.v +fpga_lf.ngc: fpga_lf.v fpga.ucf xst_lf.scr util.v clk_divider.v lo_edge_detect.v lo_read.v lo_passthru.v lp20khz_1MSa_iir_filter.v min_max_tracker.v lf_edge_detect.v hi_sniffer.v $(DELETE) $@ $(XILINX_TOOLS_PREFIX)xst -ifn xst_lf.scr diff --git a/fpga/fpga_hf.bit b/fpga/fpga_hf.bit index 50c7eef97c8b98461b7d8be9e4e643dd85910241..eea2083b4127d5f893347496679abde7642d497d 100644 GIT binary patch literal 42175 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
aF>5%M+C8_(G-6 z$7*^8`U~}M`4oNHU6jE^6)p5b_$*0xLB^E9yhy@5F$uQM z7c2-C|Nm?JK2K#)%8>(;c%)jP#;q zk*bVY8d*9{*HfLU2*dc>J<`i9sxq&hVBS?B z8-wA9GTe$__SsJ?7N zW6d1lHg2KnyhusMhA$HFh1>#Dt#RyLv(o3On~mRAFJ?c|SjWP6c3EQ_!odC9QhC=? zH`m-b@VV?~8*84fxl?V(ex`BJ-B)-m&( zkN=#8yK9>6;s-8z+PqU)+23qj%-sC3c# zB?J9}Fi9=23A)AaR1;Yy*Y_`MFrQ+fkA<3L)GHU-X7HTmnoUQ3H}jbtiypX4P}O%i zgiITe!tn(PI>g}_2;AcTSnKXs(5P;1S}@GQ(9MzG9$uGap=m+Thi>XyaGQBkWP#Me zry;EAvu`s$9a$uU=iqODqjt#Ae+0ZQx5yK2%|{lJbm%}=DC$l zW(bZoKr=3TLeNJ^+CiVC=Enx=3+qM}TrT*JvD`Rm)0K&=zf6#}*UJsy_)O zeN4ugn`wc%T=4qX5h=2?i%SLB!BvhSfN?>T*uo+=z)_MFPQq}dl~pqpsH0O$ukcRK)jtg>IfQojORmYDnPsxe#J7`gj0LHQHA zDQj+tTtmO97L+d&DrW=xbqOv90A0~9iT#>`%K<<$F8g!GIrIvE7KqCPs?5uvKDQxL z!{~OYApPe6VXC;S;dnvN;&tJ3cnK~8l`1WjcSYpoY8ABj@48gKz8F?CzYo@MWn@0B zRefb&umizg!#;xM%Q#nA9l1Q^dmBih!1}%DdK@*&~gao8t=x zwNP6T(4zb`j7ZXOTrnqNj^Mp3((A!-1($0pLKT$k|f(DJtTBrdo2Q8KT3i)E; zJbpjq(y$eTWHd`iAJ`H>ZMmkY8ouU=wm7KVTT6x_?^JxI9N# zQ|ah-q;w3;(<;9*5^ob6M-83SX+LsGKpE>iIYx2EU;Z46}St<)vd5%q2WN^5@ zLW^Ap6I#H^Yhlbg(beam20Y_0ct!A^L&0P?ILNDr6{`sTc<>+p7rbBoQU-$GsbXL$ z&Q*clPav3%-||2FPiN=9(WO;Xs!w z!ezSrOKhh9uBt8vN?jGId+O_QpwuD3?-b~A^&eHG_jUP~nS%ds^}V_~ze>vBFG2A! z$xzR4{i;6ix4*vv@2|l7EAajbyuSkPufY2&@E>^vw7&$03I3A&kGu}=&;9)scz*@n zUxD{m;QbYNe+B+yt^mUM$TWQZiy2b*FCnTg=lwb>;rFk};47fq-+RuHYFf&F$o~V| Ce|JUz diff --git a/fpga/fpga_hf.v b/fpga/fpga_hf.v index 8a465e75..264e1b0c 100644 --- a/fpga/fpga_hf.v +++ b/fpga/fpga_hf.v @@ -17,6 +17,7 @@ `include "hi_read_rx_xcorr.v" `include "hi_simulate.v" `include "hi_iso14443a.v" +`include "hi_sniffer.v" `include "util.v" module fpga_hf( @@ -122,25 +123,36 @@ hi_iso14443a hisn( hi_simulate_mod_type ); +hi_sniffer he( + pck0, ck_1356meg, ck_1356megb, + he_pwr_lo, he_pwr_hi, he_pwr_oe1, he_pwr_oe2, he_pwr_oe3, he_pwr_oe4, + adc_d, he_adc_clk, + he_ssp_frame, he_ssp_din, ssp_dout, he_ssp_clk, + cross_hi, cross_lo, + he_dbg, + hi_read_rx_xcorr_848, hi_read_rx_xcorr_snoop, hi_read_rx_xcorr_quarter +); + // Major modes: // 000 -- HF reader, transmitting to tag; modulation depth selectable // 001 -- HF reader, receiving from tag, correlating as it goes; frequency selectable // 010 -- HF simulated tag // 011 -- HF ISO14443-A +// 100 -- HF Snoop // 111 -- everything off -mux8 mux_ssp_clk (major_mode, ssp_clk, ht_ssp_clk, hrxc_ssp_clk, hs_ssp_clk, hisn_ssp_clk, 1'b0, 1'b0, 1'b0, 1'b0); -mux8 mux_ssp_din (major_mode, ssp_din, ht_ssp_din, hrxc_ssp_din, hs_ssp_din, hisn_ssp_din, 1'b0, 1'b0, 1'b0, 1'b0); -mux8 mux_ssp_frame (major_mode, ssp_frame, ht_ssp_frame, hrxc_ssp_frame, hs_ssp_frame, hisn_ssp_frame, 1'b0, 1'b0, 1'b0, 1'b0); -mux8 mux_pwr_oe1 (major_mode, pwr_oe1, ht_pwr_oe1, hrxc_pwr_oe1, hs_pwr_oe1, hisn_pwr_oe1, 1'b0, 1'b0, 1'b0, 1'b0); -mux8 mux_pwr_oe2 (major_mode, pwr_oe2, ht_pwr_oe2, hrxc_pwr_oe2, hs_pwr_oe2, hisn_pwr_oe2, 1'b0, 1'b0, 1'b0, 1'b0); -mux8 mux_pwr_oe3 (major_mode, pwr_oe3, ht_pwr_oe3, hrxc_pwr_oe3, hs_pwr_oe3, hisn_pwr_oe3, 1'b0, 1'b0, 1'b0, 1'b0); -mux8 mux_pwr_oe4 (major_mode, pwr_oe4, ht_pwr_oe4, hrxc_pwr_oe4, hs_pwr_oe4, hisn_pwr_oe4, 1'b0, 1'b0, 1'b0, 1'b0); -mux8 mux_pwr_lo (major_mode, pwr_lo, ht_pwr_lo, hrxc_pwr_lo, hs_pwr_lo, hisn_pwr_lo, 1'b0, 1'b0, 1'b0, 1'b0); -mux8 mux_pwr_hi (major_mode, pwr_hi, ht_pwr_hi, hrxc_pwr_hi, hs_pwr_hi, hisn_pwr_hi, 1'b0, 1'b0, 1'b0, 1'b0); -mux8 mux_adc_clk (major_mode, adc_clk, ht_adc_clk, hrxc_adc_clk, hs_adc_clk, hisn_adc_clk, 1'b0, 1'b0, 1'b0, 1'b0); -mux8 mux_dbg (major_mode, dbg, ht_dbg, hrxc_dbg, hs_dbg, hisn_dbg, 1'b0, 1'b0, 1'b0, 1'b0); +mux8 mux_ssp_clk (major_mode, ssp_clk, ht_ssp_clk, hrxc_ssp_clk, hs_ssp_clk, hisn_ssp_clk, he_ssp_clk, 1'b0, 1'b0, 1'b0); +mux8 mux_ssp_din (major_mode, ssp_din, ht_ssp_din, hrxc_ssp_din, hs_ssp_din, hisn_ssp_din, he_ssp_din, 1'b0, 1'b0, 1'b0); +mux8 mux_ssp_frame (major_mode, ssp_frame, ht_ssp_frame, hrxc_ssp_frame, hs_ssp_frame, hisn_ssp_frame, he_ssp_frame, 1'b0, 1'b0, 1'b0); +mux8 mux_pwr_oe1 (major_mode, pwr_oe1, ht_pwr_oe1, hrxc_pwr_oe1, hs_pwr_oe1, hisn_pwr_oe1, he_pwr_oe1, 1'b0, 1'b0, 1'b0); +mux8 mux_pwr_oe2 (major_mode, pwr_oe2, ht_pwr_oe2, hrxc_pwr_oe2, hs_pwr_oe2, hisn_pwr_oe2, he_pwr_oe2, 1'b0, 1'b0, 1'b0); +mux8 mux_pwr_oe3 (major_mode, pwr_oe3, ht_pwr_oe3, hrxc_pwr_oe3, hs_pwr_oe3, hisn_pwr_oe3, he_pwr_oe3, 1'b0, 1'b0, 1'b0); +mux8 mux_pwr_oe4 (major_mode, pwr_oe4, ht_pwr_oe4, hrxc_pwr_oe4, hs_pwr_oe4, hisn_pwr_oe4, he_pwr_oe4, 1'b0, 1'b0, 1'b0); +mux8 mux_pwr_lo (major_mode, pwr_lo, ht_pwr_lo, hrxc_pwr_lo, hs_pwr_lo, hisn_pwr_lo, he_pwr_lo, 1'b0, 1'b0, 1'b0); +mux8 mux_pwr_hi (major_mode, pwr_hi, ht_pwr_hi, hrxc_pwr_hi, hs_pwr_hi, hisn_pwr_hi, he_pwr_hi, 1'b0, 1'b0, 1'b0); +mux8 mux_adc_clk (major_mode, adc_clk, ht_adc_clk, hrxc_adc_clk, hs_adc_clk, hisn_adc_clk, he_adc_clk, 1'b0, 1'b0, 1'b0); +mux8 mux_dbg (major_mode, dbg, ht_dbg, hrxc_dbg, hs_dbg, hisn_dbg, he_dbg, 1'b0, 1'b0, 1'b0); // In all modes, let the ADC's outputs be enabled. assign adc_noe = 1'b0; diff --git a/fpga/fpga_lf.bit b/fpga/fpga_lf.bit index bd4d821bbd7db5d6ff01190fc2204e259e467c50..6a16e7bf3758bc838f1ecb1633335028d1345d78 100644 GIT binary patch delta 30 mcmdmgl4<`*rU@2;h6egZ#tbP8oQ9@WMkZE<78^awmH+^i@(B$9 delta 30 mcmdmgl4<`*rU@2;2FCgZW(+9|oCfAr#uiovCL2A=mH+^jK?xB6 diff --git a/fpga/hi_sniffer.v b/fpga/hi_sniffer.v new file mode 100644 index 00000000..f9d8ba93 --- /dev/null +++ b/fpga/hi_sniffer.v @@ -0,0 +1,77 @@ + +module hi_sniffer( + pck0, ck_1356meg, ck_1356megb, + pwr_lo, pwr_hi, pwr_oe1, pwr_oe2, pwr_oe3, pwr_oe4, + adc_d, adc_clk, + ssp_frame, ssp_din, ssp_dout, ssp_clk, + cross_hi, cross_lo, + dbg, + xcorr_is_848, snoop, xcorr_quarter_freq // not used. +); + input pck0, ck_1356meg, ck_1356megb; + output pwr_lo, pwr_hi, pwr_oe1, pwr_oe2, pwr_oe3, pwr_oe4; + input [7:0] adc_d; + output adc_clk; + input ssp_dout; + output ssp_frame, ssp_din, ssp_clk; + input cross_hi, cross_lo; + output dbg; + input xcorr_is_848, snoop, xcorr_quarter_freq; // not used. + +// We are only snooping, all off. +assign pwr_hi = 1'b0;// ck_1356megb & (~snoop); +assign pwr_oe1 = 1'b0; +assign pwr_oe2 = 1'b0; +assign pwr_oe3 = 1'b0; +assign pwr_oe4 = 1'b0; + +reg ssp_clk = 1'b0; +reg ssp_frame; +reg adc_clk; +reg [7:0] adc_d_out = 8'd0; +reg [7:0] ssp_cnt = 8'd0; +reg [7:0] pck_divider = 8'd0; +reg ant_lo = 1'b0; +reg bit_to_send = 1'b0; + +always @(ck_1356meg, pck0) // should synthetisize to a mux.. + begin + adc_clk = ck_1356meg; + ssp_clk = ~ck_1356meg; + end + +reg [7:0] cnt_test = 8'd0; // test + +always @(posedge pck0) +begin + ant_lo <= 1'b0; +end + +always @(posedge ssp_clk) // ~1356 (hf) +begin + if(ssp_cnt[7:0] == 8'd255) // SSP counter for divides. + ssp_cnt[7:0] <= 8'd0; + else + ssp_cnt <= ssp_cnt + 1; + + if((ssp_cnt[2:0] == 3'b000) && !ant_lo) // To set frame length + begin + adc_d_out[7:0] = adc_d; // disable for test + bit_to_send = adc_d_out[0]; + ssp_frame <= 1'b1; + end + else + begin + adc_d_out[6:0] = adc_d_out[7:1]; + adc_d_out[7] = 1'b0; // according to old lf_read.v comment prevents gliches if not set. + bit_to_send = adc_d_out[0]; + ssp_frame <= 1'b0; + end +end + +assign ssp_din = bit_to_send && !ant_lo;//bit_to_send && !ant_lo; // && .. not needed i guess? + +assign pwr_lo = ant_lo; + + +endmodule diff --git a/include/usb_cmd.h b/include/usb_cmd.h index 0f649a69..88e2afe3 100644 --- a/include/usb_cmd.h +++ b/include/usb_cmd.h @@ -197,6 +197,8 @@ typedef struct{ #define CMD_MIFARE_DESFIRE_INFO 0x072d #define CMD_MIFARE_DESFIRE 0x072e +#define CMD_HF_SNIFFER 0x0800 + #define CMD_UNKNOWN 0xFFFF -- 2.39.2