Add raw HF signal plotting (#786)

* Add raw HF signal plotting
* new fpga module hi_get_trace.v - store A/D converter output to circular buffer on FPGA
* new command 'hf plot' - pull data from FPGA and display it in Graph Window
This commit is contained in:
pwpiwi 2019-02-20 19:18:12 +01:00 committed by GitHub
parent 7527c2bdd8
commit fc52fbd42f
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
30 changed files with 441 additions and 62 deletions

View file

@ -13,7 +13,7 @@ This project uses the changelog in accordance with [keepchangelog](http://keepac
### Fixed
- AC-Mode decoding for HitagS
- Wrong UID at HitagS simulation
- 'hf 15 sim' now works as expected (piwi)
- `hf 15 sim` now works as expected (piwi)
### Added
- Support Standard Communication Mode in HITAG S
@ -25,8 +25,9 @@ This project uses the changelog in accordance with [keepchangelog](http://keepac
- Added `hf fido` `assert` and `make` commands from fido2 protocol (authenticatorMakeCredential and authenticatorGetAssertion) (Merlok)
- Added `lf paradox clone` to clone a Paradox card
- Added `emv` commmands working for both contactless and smart cards (Merlok)
- Added 'hf 15 snoop' (piwi)
- Added `hf 15 snoop` (piwi)
- Added support for standard USB Smartcard Readers (piwi)
- Added `hf plot` (piwi)
## [v3.1.0][2018-10-10]

View file

@ -30,6 +30,8 @@
#include "mifareutil.h"
#include "pcf7931.h"
#include "i2c.h"
#include "hfsnoop.h"
#include "fpgaloader.h"
#ifdef WITH_LCD
#include "LCD.h"
#endif
@ -1323,11 +1325,16 @@ 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;
case CMD_HF_PLOT:
HfPlot();
break;
#endif
#ifdef WITH_SMARTCARD
case CMD_SMART_ATR: {
SmartCardAtr();
@ -1377,7 +1384,6 @@ void UsbPacketReceived(uint8_t *packet, int len)
break;
case CMD_DOWNLOAD_RAW_ADC_SAMPLES_125K:
LED_B_ON();
uint8_t *BigBuf = BigBuf_get_addr();
for(size_t i=0; i<c->arg[1]; i += USB_CMD_DATA_SIZE) {

View file

@ -21,7 +21,6 @@
#include "mifare.h"
#include "../common/crc32.h"
#include "BigBuf.h"
#include "fpgaloader.h"
extern const uint8_t OddByteParity[256];
extern int rsamples; // = 0;
@ -174,13 +173,8 @@ void SimulateHitagSTag(bool tag_mem_supplied, byte_t* data);
void WritePageHitagS(hitag_function htf, hitag_data* htd,int page);
void check_challenges_cmd(bool file_given, byte_t* data, uint64_t tagMode);
// 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);
/// util.h
void HfSnoop(int , int);
#endif

View file

@ -166,7 +166,7 @@ bool FpgaSetupSscDma(uint8_t *buf, uint16_t sample_count)
AT91C_BASE_PDC_SSC->PDC_RPR = (uint32_t) buf; // transfer to this memory address
AT91C_BASE_PDC_SSC->PDC_RCR = sample_count; // transfer this many samples
AT91C_BASE_PDC_SSC->PDC_RNPR = (uint32_t) buf; // next transfer to same memory address
AT91C_BASE_PDC_SSC->PDC_RNCR = sample_count; // ... with same number of samples AT91C_BASE_PDC_SSC->PDC_PTCR = AT91C_PDC_RXTEN; // go!
AT91C_BASE_PDC_SSC->PDC_RNCR = sample_count; // ... with same number of samples
AT91C_BASE_PDC_SSC->PDC_PTCR = AT91C_PDC_RXTEN; // go!
return true;
}
@ -417,8 +417,10 @@ void FpgaDownloadAndGo(int bitstream_version)
uint8_t output_buffer[OUTPUT_BUFFER_LEN] = {0x00};
// check whether or not the bitstream is already loaded
if (downloaded_bitstream == bitstream_version)
if (downloaded_bitstream == bitstream_version) {
FpgaEnableTracing();
return;
}
// make sure that we have enough memory to decompress
BigBuf_free(); BigBuf_Clear_ext(false);
@ -454,16 +456,30 @@ void FpgaSendCommand(uint16_t cmd, uint16_t v)
while ((AT91C_BASE_SPI->SPI_SR & AT91C_SPI_TXEMPTY) == 0); // wait for the transfer to complete
AT91C_BASE_SPI->SPI_TDR = AT91C_SPI_LASTXFER | cmd | v; // send the data
}
//-----------------------------------------------------------------------------
// Write the FPGA setup word (that determines what mode the logic is in, read
// vs. clone vs. etc.). This is now a special case of FpgaSendCommand() to
// avoid changing this function's occurence everywhere in the source code.
//-----------------------------------------------------------------------------
void FpgaWriteConfWord(uint8_t v)
void FpgaWriteConfWord(uint16_t v)
{
FpgaSendCommand(FPGA_CMD_SET_CONFREG, v);
}
//-----------------------------------------------------------------------------
// enable/disable FPGA internal tracing
//-----------------------------------------------------------------------------
void FpgaEnableTracing(void)
{
FpgaSendCommand(FPGA_CMD_TRACE_ENABLE, 1);
}
void FpgaDisableTracing(void)
{
FpgaSendCommand(FPGA_CMD_TRACE_ENABLE, 0);
}
//-----------------------------------------------------------------------------
// Set up the CMOS switches that mux the ADC: four switches, independently
// closable, but should only close one at a time. Not an FPGA thing, but

View file

@ -17,13 +17,15 @@
#include <stdbool.h>
void FpgaSendCommand(uint16_t cmd, uint16_t v);
void FpgaWriteConfWord(uint8_t v);
void FpgaWriteConfWord(uint16_t v);
void FpgaDownloadAndGo(int bitstream_version);
void FpgaSetupSsc(uint8_t mode);
void SetupSpi(int mode);
bool FpgaSetupSscDma(uint8_t *buf, uint16_t sample_count);
void Fpga_print_status();
int FpgaGetCurrent();
void FpgaEnableTracing(void);
void FpgaDisableTracing(void);
#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);
@ -33,9 +35,14 @@ void SetAdcMuxFor(uint32_t whichGpio);
#define FPGA_BITSTREAM_HF 2
// Definitions for the FPGA commands.
// BOTH
#define FPGA_CMD_SET_CONFREG (1<<12)
// LF
#define FPGA_CMD_SET_DIVISOR (2<<12)
#define FPGA_CMD_SET_USER_BYTE1 (3<<12)
// HF
#define FPGA_CMD_TRACE_ENABLE (2<<12)
// Definitions for the FPGA configuration word.
// LF
#define FPGA_MAJOR_MODE_LF_ADC (0<<5)
@ -47,21 +54,27 @@ void SetAdcMuxFor(uint32_t whichGpio);
#define FPGA_MAJOR_MODE_HF_SIMULATOR (2<<5)
#define FPGA_MAJOR_MODE_HF_ISO14443A (3<<5)
#define FPGA_MAJOR_MODE_HF_SNOOP (4<<5)
#define FPGA_MAJOR_MODE_HF_GET_TRACE (5<<5)
// BOTH
#define FPGA_MAJOR_MODE_OFF (7<<5)
// Options for LF_ADC
#define FPGA_LF_ADC_READER_FIELD (1<<0)
// Options for LF_EDGE_DETECT
#define FPGA_CMD_SET_EDGE_DETECT_THRESHOLD FPGA_CMD_SET_USER_BYTE1
#define FPGA_LF_EDGE_DETECT_READER_FIELD (1<<0)
#define FPGA_LF_EDGE_DETECT_TOGGLE_MODE (1<<1)
// Options for the HF reader, tx to tag
#define FPGA_HF_READER_TX_SHALLOW_MOD (1<<0)
// Options for the HF reader, correlating against rx from tag
#define FPGA_HF_READER_RX_XCORR_848_KHZ (1<<0)
#define FPGA_HF_READER_RX_XCORR_SNOOP (1<<1)
#define FPGA_HF_READER_RX_XCORR_QUARTER_FREQ (1<<2)
#define FPGA_HF_READER_RX_XCORR_AMPLITUDE (1<<3)
// Options for the HF simulated tag, how to modulate
#define FPGA_HF_SIMULATOR_NO_MODULATION (0<<0)
#define FPGA_HF_SIMULATOR_MODULATE_BPSK (1<<0)

View file

@ -1,10 +1,22 @@
//-----------------------------------------------------------------------------
// piwi, 2019
//
// 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.
//-----------------------------------------------------------------------------
// Routines to get sample data from FPGA.
//-----------------------------------------------------------------------------
#include "hfsnoop.h"
#include "proxmark3.h"
#include "apps.h"
#include "BigBuf.h"
#include "util.h"
#include "apps.h"
#include "usb_cdc.h" // for usb_poll_validate_length
static void RAMFUNC optimizedSnoop(void);
#include "fpga.h"
#include "fpgaloader.h"
static void RAMFUNC optimizedSnoop(void)
{
@ -74,3 +86,33 @@ void HfSnoop(int samplesToSkip, int triggersToSkip)
LED_D_OFF();
}
void HfPlot(void)
{
uint8_t *buf = ToSend;
uint8_t *this_buf = buf;
FpgaDownloadAndGo(FPGA_BITSTREAM_HF);
FpgaSetupSsc(FPGA_MAJOR_MODE_HF_GET_TRACE);
AT91C_BASE_PDC_SSC->PDC_PTCR = AT91C_PDC_RXTDIS; // Disable DMA Transfer
AT91C_BASE_PDC_SSC->PDC_RPR = (uint32_t) this_buf; // start transfer to this memory address
AT91C_BASE_PDC_SSC->PDC_RCR = USB_CMD_DATA_SIZE; // transfer this many samples
buf[0] = (uint8_t)AT91C_BASE_SSC->SSC_RHR; // clear receive register
AT91C_BASE_PDC_SSC->PDC_PTCR = AT91C_PDC_RXTEN; // Start DMA transfer
FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_GET_TRACE); // let FPGA transfer its internal Block-RAM
LED_B_ON();
for(size_t i = 0; i < FPGA_TRACE_SIZE; i += USB_CMD_DATA_SIZE) {
// prepare next DMA transfer:
uint8_t *next_buf = buf + ((i + USB_CMD_DATA_SIZE) % (2 * USB_CMD_DATA_SIZE));
AT91C_BASE_PDC_SSC->PDC_RNPR = (uint32_t)next_buf;
AT91C_BASE_PDC_SSC->PDC_RNCR = USB_CMD_DATA_SIZE;
size_t len = MIN(FPGA_TRACE_SIZE - i, USB_CMD_DATA_SIZE);
while (!(AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_ENDRX))) ; // wait for DMA transfer to complete
cmd_send(CMD_DOWNLOADED_RAW_ADC_SAMPLES_125K, i, len, FPGA_TRACE_SIZE, this_buf, len);
this_buf = next_buf;
}
// Trigger a finish downloading signal with an ACK frame
cmd_send(CMD_ACK, 1, 0, FPGA_TRACE_SIZE, 0, 0);
LED_B_OFF();
FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
}

17
armsrc/hfsnoop.h Normal file
View file

@ -0,0 +1,17 @@
//-----------------------------------------------------------------------------
// piwi, 2019
//
// 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.
//-----------------------------------------------------------------------------
// Routines to get sample data from FPGA.
//-----------------------------------------------------------------------------
#ifndef HFSNOOP_H__
#define HFSNOOP_H__
void HfSnoop(int samplesToSkip, int triggersToSkip);
void HfPlot(void);
#endif

View file

@ -22,6 +22,7 @@
#include "hitag2.h"
#include "string.h"
#include "BigBuf.h"
#include "fpgaloader.h"
static bool bQuiet;

View file

@ -20,6 +20,7 @@
#include "hitag2.h"
#include "string.h"
#include "BigBuf.h"
#include "fpgaloader.h"
#define CRC_PRESET 0xFF
#define CRC_POLYNOM 0x1D

View file

@ -51,6 +51,7 @@
#include "protocols.h"
#include "optimized_cipher.h"
#include "usb_cdc.h" // for usb_poll_validate_length
#include "fpgaloader.h"
static int timeout = 4096;

View file

@ -25,6 +25,7 @@
#include "BigBuf.h"
#include "protocols.h"
#include "parity.h"
#include "fpgaloader.h"
typedef struct {
enum {
@ -1771,7 +1772,9 @@ int iso14443a_select_card(byte_t *uid_ptr, iso14a_card_select_t *p_hi14a_card, u
if (anticollision) {
// SELECT_ALL
ReaderTransmit(sel_all, sizeof(sel_all), NULL);
if (!ReaderReceive(resp, resp_par)) return 0;
if (!ReaderReceive(resp, resp_par)) {
return 0;
}
if (Demod.collisionPos) { // we had a collision and need to construct the UID bit by bit
memset(uid_resp, 0, 4);
@ -1793,7 +1796,9 @@ int iso14443a_select_card(byte_t *uid_ptr, iso14a_card_select_t *p_hi14a_card, u
}
collision_answer_offset = uid_resp_bits%8;
ReaderTransmitBits(sel_uid, 16 + uid_resp_bits, NULL);
if (!ReaderReceiveOffset(resp, collision_answer_offset, resp_par)) return 0;
if (!ReaderReceiveOffset(resp, collision_answer_offset, resp_par)) {
return 0;
}
}
// finally, add the last bits and BCC of the UID
for (uint16_t i = collision_answer_offset; i < (Demod.len-1)*8; i++, uid_resp_bits++) {
@ -1827,7 +1832,9 @@ int iso14443a_select_card(byte_t *uid_ptr, iso14a_card_select_t *p_hi14a_card, u
ReaderTransmit(sel_uid, sizeof(sel_uid), NULL);
// Receive the SAK
if (!ReaderReceive(resp, resp_par)) return 0;
if (!ReaderReceive(resp, resp_par)) {
return 0;
}
sak = resp[0];
// Test if more parts of the uid are coming
@ -1862,7 +1869,9 @@ int iso14443a_select_card(byte_t *uid_ptr, iso14a_card_select_t *p_hi14a_card, u
AppendCrc14443a(rats, 2);
ReaderTransmit(rats, sizeof(rats), NULL);
if (!(len = ReaderReceive(resp, resp_par))) return 0;
if (!(len = ReaderReceive(resp, resp_par))) {
return 0;
}
if(p_hi14a_card) {
memcpy(p_hi14a_card->ats, resp, len);
@ -2044,7 +2053,7 @@ void ReaderIso14443a(UsbCommand *c)
// 1 - all is OK with ATS, 2 - without ATS
cantSELECT = true;
}
FpgaDisableTracing();
LED_B_ON();
cmd_send(CMD_ACK,arg0,card->uidlen,0,buf,sizeof(iso14a_card_select_t));
LED_B_OFF();
@ -2058,6 +2067,7 @@ void ReaderIso14443a(UsbCommand *c)
if(param & ISO14A_APDU && !cantSELECT) {
uint8_t res;
arg0 = iso14_apdu(cmd, len, buf, &res);
FpgaDisableTracing();
LED_B_ON();
cmd_send(CMD_ACK, arg0, res, 0, buf, sizeof(buf));
LED_B_OFF();
@ -2099,6 +2109,7 @@ void ReaderIso14443a(UsbCommand *c)
}
}
arg0 = ReaderReceive(buf, par);
FpgaDisableTracing();
LED_B_ON();
cmd_send(CMD_ACK,arg0,0,0,buf,sizeof(buf));
@ -2415,6 +2426,8 @@ void ReaderMifare(bool first_try)
}
}
FpgaDisableTracing();
uint8_t buf[32];
memcpy(buf + 0, uid, 4);
num_to_bytes(nt, 4, buf + 4);
@ -2587,6 +2600,7 @@ void RAMFUNC SniffMifare(uint8_t param) {
DbpString("COMMAND FINISHED.");
FpgaDisableSscDma();
FpgaDisableTracing();
MfSniffEnd();
Dbprintf("maxDataLen=%x, Uart.state=%x, Uart.len=%x", maxDataLen, Uart.state, Uart.len);

View file

@ -10,12 +10,14 @@
// the `fake tag' modes.
//-----------------------------------------------------------------------------
#include "iso14443b.h"
#include "proxmark3.h"
#include "apps.h"
#include "util.h"
#include "string.h"
#include "iso14443crc.h"
#include "fpgaloader.h"
#define RECEIVE_SAMPLES_TIMEOUT 1000 // TR0 max is 256/fs = 256/(848kHz) = 302us or 64 samples from FPGA. 1000 seems to be much too high?
#define ISO14443B_DMA_BUFFER_SIZE 128

View file

@ -60,6 +60,7 @@
#include "protocols.h"
#include "cmd.h"
#include "BigBuf.h"
#include "fpgaloader.h"
#define arraylen(x) (sizeof(x)/sizeof((x)[0]))

View file

@ -10,15 +10,16 @@
// LEGIC RF simulation code
//-----------------------------------------------------------------------------
#include "legicrf.h"
#include "proxmark3.h"
#include "apps.h"
#include "util.h"
#include "string.h"
#include "legicrf.h"
#include "legic_prng.h"
#include "legic.h"
#include "crc.h"
#include "fpgaloader.h"
static legic_card_select_t card;/* metadata of currently selected card */
static crc_t legic_crc;

View file

@ -10,16 +10,17 @@
// LEGIC RF simulation code
//-----------------------------------------------------------------------------
#include "legicrfsim.h"
#include "proxmark3.h"
#include "apps.h"
#include "util.h"
#include "string.h"
#include "legicrfsim.h"
#include "legic_prng.h"
#include "legic.h"
#include "crc.h"
#include "usb_cdc.h" // for usb_poll_validate_length
#include "fpgaloader.h"
static uint8_t* legic_mem; /* card memory, used for sim */
static legic_card_select_t card;/* metadata of currently selected card */

View file

@ -18,6 +18,7 @@
#include "lfsampling.h"
#include "protocols.h"
#include "usb_cdc.h" // for usb_poll_validate_length
#include "fpgaloader.h"
/**
* Function to do a modulation and then get samples.

View file

@ -12,7 +12,7 @@
#include "string.h"
#include "lfsampling.h"
#include "usb_cdc.h" // for usb_poll_validate_length
//#include "ticks.h" // for StartTicks
#include "fpgaloader.h"
sample_config config = { 1, 8, 1, 95, 0 } ;

View file

@ -15,10 +15,10 @@
#include "mifarecmd.h"
#include "apps.h"
#include "util.h"
#include "parity.h"
#include "crc.h"
#include "fpgaloader.h"
#define HARDNESTED_AUTHENTICATION_TIMEOUT 848 // card times out 1ms after wrong authentication (according to NXP documentation)
#define HARDNESTED_PRE_AUTHENTICATION_LEADTIME 400 // some (non standard) cards need a pause after select before they are ready for first authentication

View file

@ -9,7 +9,7 @@
//-----------------------------------------------------------------------------
#include "mifaresniff.h"
#include "apps.h"
#include "proxmark3.h"
#include "util.h"
#include "string.h"
@ -18,6 +18,9 @@
#include "crapto1/crapto1.h"
#include "mifareutil.h"
#include "common.h"
#include "cmd.h"
#include "BigBuf.h"
#include "fpgaloader.h"
static int sniffState = SNF_INIT;

View file

@ -4,6 +4,7 @@
#include "pcf7931.h"
#include "util.h"
#include "string.h"
#include "fpgaloader.h"
#define T0_PCF 8 //period for the pcf7931 in us
#define ALLOC 16

View file

@ -11,10 +11,12 @@
#include "cmdhf.h"
#include <math.h>
#include "usb_cmd.h"
#include "comms.h"
#include "ui.h"
#include "cmdparser.h"
#include "cliparser/cliparser.h"
#include "cmdhf14a.h"
#include "cmdhf14b.h"
#include "cmdhf15.h"
@ -27,6 +29,9 @@
#include "cmdhftopaz.h"
#include "cmdhflist.h"
#include "cmdhffido.h"
#include "cmddata.h"
#include "graph.h"
#include "fpga.h"
static int CmdHelp(const char *Cmd);
@ -73,31 +78,83 @@ int CmdHFSnoop(const char *Cmd)
return 0;
}
static command_t CommandTable[] =
// static void InterpolateShannon(int *source, size_t source_len, int *dest, size_t dest_len)
// {
// int *buf = (int*)malloc(source_len * sizeof(int));
// memcpy(buf, source, source_len * sizeof(int));
// for (int i = 0; i < source_len; i++) {
// buf[i] += 128;
// }
// for (int i = 0; i < dest_len; i++) {
// float value = 0.0;
// for (int j = 0; j < source_len; j++) {
// if (i * source_len == j * dest_len) { // sin(0) / 0 = 1
// value += (float)buf[j];
// } else {
// value += (float)buf[j] * sin(((float)i*source_len/dest_len-j)*3.1415) / (((float)i*source_len/dest_len-j)*3.1415);
// }
// }
// dest[i] = value - 128;
// }
// free(buf);
// }
static int CmdHFPlot(const char *Cmd)
{
{"help", CmdHelp, 1, "This help"},
{"14a", CmdHF14A, 1, "{ ISO14443A RFIDs... }"},
{"14b", CmdHF14B, 1, "{ ISO14443B RFIDs... }"},
{"15", CmdHF15, 1, "{ ISO15693 RFIDs... }"},
{"epa", CmdHFEPA, 1, "{ German Identification Card... }"},
{"legic", CmdHFLegic, 0, "{ LEGIC RFIDs... }"},
{"iclass", CmdHFiClass, 1, "{ ICLASS RFIDs... }"},
{"mf", CmdHFMF, 1, "{ MIFARE RFIDs... }"},
{"mfu", CmdHFMFUltra, 1, "{ MIFARE Ultralight RFIDs... }"},
{"mfp", CmdHFMFP, 1, "{ MIFARE Plus RFIDs... }"},
{"topaz", CmdHFTopaz, 1, "{ TOPAZ (NFC Type 1) RFIDs... }"},
{"fido", CmdHFFido, 1, "{ FIDO and FIDO2 authenticators... }"},
{"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]"},
CLIParserInit("hf plot",
"Plots HF signal after RF signal path and A/D conversion.",
"This can be used after any hf command and will show the last few milliseconds of the HF signal.\n"
"Note: If the last hf command terminated because of a timeout you will most probably see nothing.\n");
void* argtable[] = {
arg_param_begin,
arg_param_end
};
CLIExecWithReturn(Cmd, argtable, true);
uint8_t buf[FPGA_TRACE_SIZE];
if (GetFromFpgaRAM(buf, FPGA_TRACE_SIZE)) {
for (size_t i = 0; i < FPGA_TRACE_SIZE; i++) {
GraphBuffer[i] = (int)buf[i] - 128;
}
GraphTraceLen = FPGA_TRACE_SIZE;
// InterpolateShannon(GraphBuffer, FPGA_TRACE_SIZE, GraphBuffer, FPGA_TRACE_SIZE*8/7);
// GraphTraceLen = FPGA_TRACE_SIZE*8/7;
ShowGraphWindow();
RepaintGraphWindow();
}
return 0;
}
static command_t CommandTable[] =
{
{"help", CmdHelp, 1, "This help"},
{"14a", CmdHF14A, 0, "{ ISO14443A RFIDs... }"},
{"14b", CmdHF14B, 0, "{ ISO14443B RFIDs... }"},
{"15", CmdHF15, 1, "{ ISO15693 RFIDs... }"},
{"epa", CmdHFEPA, 0, "{ German Identification Card... }"},
{"legic", CmdHFLegic, 0, "{ LEGIC RFIDs... }"},
{"iclass", CmdHFiClass, 1, "{ ICLASS RFIDs... }"},
{"mf", CmdHFMF, 1, "{ MIFARE RFIDs... }"},
{"mfu", CmdHFMFUltra, 1, "{ MIFARE Ultralight RFIDs... }"},
{"mfp", CmdHFMFP, 0, "{ MIFARE Plus RFIDs... }"},
{"topaz", CmdHFTopaz, 0, "{ TOPAZ (NFC Type 1) RFIDs... }"},
{"fido", CmdHFFido, 0, "{ FIDO and FIDO2 authenticators... }"},
{"tune", CmdHFTune, 0, "Continuously measure HF antenna tuning"},
{"list", CmdHFList, 1, "List protocol data in trace buffer"},
{"plot", CmdHFPlot, 0, "Plot signal"},
{"search", CmdHFSearch, 0, "Search for known HF tags [preliminary]"},
{"snoop", CmdHFSnoop, 0, "<samples to skip (10000)> <triggers to skip (1)> Generic HF Snoop"},
{NULL, NULL, 0, NULL}
{NULL, NULL, 0, NULL}
};
int CmdHF(const char *Cmd)
{
CmdsParse(CommandTable, Cmd);
return 0;
return 0;
}
int CmdHelp(const char *Cmd)

View file

@ -9,7 +9,7 @@
//-----------------------------------------------------------------------------
#ifndef CMDPARSER_H__
#define CMDPARSER_H__
#define CMDPARSER_H__
typedef struct command_s
{

View file

@ -301,6 +301,39 @@ bool GetFromBigBuf(uint8_t *dest, int bytes, int start_index, UsbCommand *respon
}
bool GetFromFpgaRAM(uint8_t *dest, int bytes)
{
UsbCommand c = {CMD_HF_PLOT, {0, 0, 0}};
SendCommand(&c);
uint64_t start_time = msclock();
UsbCommand response;
int bytes_completed = 0;
bool show_warning = true;
while(true) {
if (getCommand(&response)) {
if (response.cmd == CMD_DOWNLOADED_RAW_ADC_SAMPLES_125K) {
int copy_bytes = MIN(bytes - bytes_completed, response.arg[1]);
memcpy(dest + response.arg[0], response.d.asBytes, copy_bytes);
bytes_completed += copy_bytes;
} else if (response.cmd == CMD_ACK) {
return true;
}
}
if (msclock() - start_time > 2000 && show_warning) {
PrintAndLog("Waiting for a response from the proxmark...");
PrintAndLog("You can cancel this operation by pressing the pm3 button");
show_warning = false;
}
}
return false;
}
bool OpenProxmark(void *port, bool wait_for_port, int timeout, bool flash_mode) {
char *portname = (char *)port;
if (!wait_for_port) {

View file

@ -35,5 +35,6 @@ bool WaitForResponseTimeoutW(uint32_t cmd, UsbCommand* response, size_t ms_timeo
bool WaitForResponseTimeout(uint32_t cmd, UsbCommand* response, size_t ms_timeout);
bool WaitForResponse(uint32_t cmd, UsbCommand* response);
bool GetFromBigBuf(uint8_t *dest, int bytes, int start_index, UsbCommand *response, size_t ms_timeout, bool show_warning);
bool GetFromFpgaRAM(uint8_t *dest, int bytes);
#endif // COMMS_H_

View file

@ -10,6 +10,7 @@
#define FPGA_BITSTREAM_FIXED_HEADER_SIZE sizeof(bitparse_fixed_header)
#define FPGA_INTERLEAVE_SIZE 288
#define FPGA_CONFIG_SIZE 42336L // our current fpga_[lh]f.bit files are 42175 bytes. Rounded up to next multiple of FPGA_INTERLEAVE_SIZE
#define FPGA_TRACE_SIZE 3072
static const uint8_t bitparse_fixed_header[] = {0x00, 0x09, 0x0f, 0xf0, 0x0f, 0xf0, 0x0f, 0xf0, 0x0f, 0xf0, 0x00, 0x00, 0x01};
extern const int fpga_bitstream_num;

View file

@ -5,7 +5,7 @@ clean:
$(DELETE) *.bgn *.drc *.ncd *.ngd *_par.xrpt *-placed.* *-placed_pad.* *_usage.xml xst_hf.srp xst_lf.srp
$(DELETE) *.map *.ngc *.xrpt *.pcf *.rbt *_auto_* *.bld *.mrp *.ngm *.unroutes *_summary.xml netlist.lst xst
fpga_hf.ngc: fpga_hf.v fpga.ucf xst_hf.scr util.v hi_simulate.v hi_read_tx.v hi_read_rx_xcorr.v hi_iso14443a.v hi_sniffer.v
fpga_hf.ngc: fpga_hf.v fpga.ucf xst_hf.scr util.v hi_simulate.v hi_read_tx.v hi_read_rx_xcorr.v hi_iso14443a.v hi_sniffer.v hi_get_trace.v
$(DELETE) $@
$(XILINX_TOOLS_PREFIX)xst -ifn xst_hf.scr

Binary file not shown.

View file

@ -18,6 +18,7 @@
`include "hi_simulate.v"
`include "hi_iso14443a.v"
`include "hi_sniffer.v"
`include "hi_get_trace.v"
`include "util.v"
module fpga_hf(
@ -40,6 +41,7 @@ module fpga_hf(
reg [15:0] shift_reg;
reg [7:0] conf_word;
reg trace_enable;
// We switch modes between transmitting to the 13.56 MHz tag and receiving
// from it, which means that we must make sure that we can do so without
@ -48,6 +50,7 @@ always @(posedge ncs)
begin
case(shift_reg[15:12])
4'b0001: conf_word <= shift_reg[7:0]; // FPGA_CMD_SET_CONFREG
4'b0010: trace_enable <= shift_reg[0]; // FPGA_CMD_TRACE_ENABLE
endcase
end
@ -129,7 +132,7 @@ hi_iso14443a hisn(
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,
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,
@ -137,6 +140,12 @@ hi_sniffer he(
hi_read_rx_xcorr_848, hi_read_rx_xcorr_snoop, hi_read_rx_xcorr_quarter
);
hi_get_trace gt(
ck_1356megb,
adc_d, trace_enable, major_mode,
gt_ssp_frame, gt_ssp_din, gt_ssp_clk
);
// Major modes:
// 000 -- HF reader, transmitting to tag; modulation depth selectable
@ -144,19 +153,20 @@ hi_sniffer he(
// 010 -- HF simulated tag
// 011 -- HF ISO14443-A
// 100 -- HF Snoop
// 101 -- HF get trace
// 111 -- everything off
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);
mux8 mux_ssp_clk (major_mode, ssp_clk, ht_ssp_clk, hrxc_ssp_clk, hs_ssp_clk, hisn_ssp_clk, he_ssp_clk, gt_ssp_clk, 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, gt_ssp_din, 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, gt_ssp_frame, 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;

160
fpga/hi_get_trace.v Normal file
View file

@ -0,0 +1,160 @@
//-----------------------------------------------------------------------------
//
// piwi, Feb 2019
//-----------------------------------------------------------------------------
module hi_get_trace(
ck_1356megb,
adc_d, trace_enable, major_mode,
ssp_frame, ssp_din, ssp_clk
);
input ck_1356megb;
input [7:0] adc_d;
input trace_enable;
input [2:0] major_mode;
output ssp_frame, ssp_din, ssp_clk;
// constants for some major_modes:
`define OFF 3'b111
`define GET_TRACE 3'b101
// clock divider
reg [6:0] clock_cnt;
always @(negedge ck_1356megb)
begin
clock_cnt <= clock_cnt + 1;
end
// sample at 13,56MHz / 8. The highest signal frequency (subcarrier) is 848,5kHz, i.e. in this case we oversample by a factor of 2
reg [2:0] sample_clock;
always @(negedge ck_1356megb)
begin
if (sample_clock == 3'd3)
sample_clock <= 3'd0;
else
sample_clock <= sample_clock + 1;
end
reg [11:0] addr;
reg [11:0] start_addr;
reg [2:0] previous_major_mode;
reg write_enable1;
reg write_enable2;
always @(negedge ck_1356megb)
begin
previous_major_mode <= major_mode;
if (major_mode == `GET_TRACE)
begin
write_enable1 <= 1'b0;
write_enable2 <= 1'b0;
if (previous_major_mode != `GET_TRACE) // just switched into GET_TRACE mode
addr <= start_addr;
if (clock_cnt == 7'd0)
begin
if (addr == 12'd3071)
addr <= 12'd0;
else
addr <= addr + 1;
end
end
else if (major_mode != `OFF)
begin
if (trace_enable)
begin
if (addr[11] == 1'b0)
begin
write_enable1 <= 1'b1;
write_enable2 <= 1'b0;
end
else
begin
write_enable1 <= 1'b0;
write_enable2 <= 1'b1;
end
if (sample_clock == 3'b000)
begin
if (addr == 12'd3071)
begin
addr <= 12'd0;
write_enable1 <= 1'b1;
write_enable2 <= 1'b0;
end
else
addr <= addr + 1;
end
end
else
begin
write_enable1 <= 1'b0;
write_enable2 <= 1'b0;
start_addr <= addr;
end
end
else // major_mode == `OFF
begin
write_enable1 <= 1'b0;
write_enable2 <= 1'b0;
if (previous_major_mode != `OFF && previous_major_mode != `GET_TRACE) // just switched off
start_addr <= addr;
end
end
// (2+1)k RAM
reg [7:0] D_out1, D_out2;
reg [7:0] ram1 [2047:0];
reg [7:0] ram2 [1023:0];
always @(negedge ck_1356megb)
begin
if (write_enable1)
begin
ram1[addr[10:0]] <= adc_d;
D_out1 <= adc_d;
end
else
D_out1 <= ram1[addr[10:0]];
if (write_enable2)
begin
ram2[addr[9:0]] <= adc_d;
D_out2 <= adc_d;
end
else
D_out2 <= ram2[addr[9:0]];
end
// SSC communication to ARM
reg ssp_clk;
reg ssp_frame;
reg [7:0] shift_out;
always @(negedge ck_1356megb)
begin
if(clock_cnt[3:0] == 4'd0) // update shift register every 16 clock cycles
begin
if(clock_cnt[6:4] == 3'd0) // either load new value
begin
if (addr[11] == 1'b0)
shift_out <= D_out1;
else
shift_out <= D_out2;
end
else // or shift left
shift_out[7:1] <= shift_out[6:0];
end
ssp_clk <= ~clock_cnt[3]; // ssp_clk frequency = 13,56MHz / 16 = 847,5 kHz
if(clock_cnt[6:4] == 3'b000) // set ssp_frame for 0...31
ssp_frame <= 1'b1;
else
ssp_frame <= 1'b0;
end
assign ssp_din = shift_out[7];
endmodule

View file

@ -220,6 +220,7 @@ typedef struct{
#define CMD_MIFARE_DESFIRE 0x072e
#define CMD_HF_SNIFFER 0x0800
#define CMD_HF_PLOT 0x0801
#define CMD_UNKNOWN 0xFFFF