Skip to content

Commit

Permalink
MAJOR update, added hitag2 reader, emulation and eavesdropping, lots …
Browse files Browse the repository at this point in the history
…of new code, including FPGA tweaks
  • Loading branch information
roel@libnfc.org committed Sep 18, 2012
1 parent e5ad43c commit db09cb3
Show file tree
Hide file tree
Showing 11 changed files with 277 additions and 28 deletions.
1 change: 1 addition & 0 deletions client/Makefile
Expand Up @@ -64,6 +64,7 @@ CMDSRCS = \
cmdlf.c \
cmdlfem4x.c \
cmdlfhid.c \
cmdlfhitag.c \
cmdlfti.c \
cmdparser.c \
cmdmain.c
Expand Down
2 changes: 1 addition & 1 deletion client/cmdhf14a.c
Expand Up @@ -28,7 +28,7 @@ static int CmdHelp(const char *Cmd);
int CmdHF14AList(const char *Cmd)
{
uint8_t got[1920];
GetFromBigBuf(got, sizeof(got));
GetFromBigBuf(got,sizeof(got),0);

PrintAndLog("recorded activity:");
PrintAndLog(" ETU :rssi: who bytes");
Expand Down
2 changes: 1 addition & 1 deletion client/cmdhf14b.c
Expand Up @@ -144,7 +144,7 @@ int CmdHF14BDemod(const char *Cmd)
int CmdHF14BList(const char *Cmd)
{
uint8_t got[960];
GetFromBigBuf(got, sizeof(got));
GetFromBigBuf(got,sizeof(got),0);

PrintAndLog("recorded activity:");
PrintAndLog(" time :rssi: who bytes");
Expand Down
2 changes: 1 addition & 1 deletion client/cmdhficlass.c
Expand Up @@ -26,7 +26,7 @@ static int CmdHelp(const char *Cmd);
int CmdHFiClassList(const char *Cmd)
{
uint8_t got[1920];
GetFromBigBuf(got, sizeof(got));
GetFromBigBuf(got,sizeof(got),0);

PrintAndLog("recorded activity:");
PrintAndLog(" ETU :rssi: who bytes");
Expand Down
2 changes: 2 additions & 0 deletions client/cmdlf.c
Expand Up @@ -23,6 +23,7 @@
#include "cmdlfhid.h"
#include "cmdlfti.h"
#include "cmdlfem4x.h"
#include "cmdlfhitag.h"

static int CmdHelp(const char *Cmd);

Expand Down Expand Up @@ -535,6 +536,7 @@ static command_t CommandTable[] =
{"simbidir", CmdLFSimBidir, 0, "Simulate LF tag (with bidirectional data transmission between reader and tag)"},
{"simman", CmdLFSimManchester, 0, "<Clock> <Bitstream> [GAP] Simulate arbitrary Manchester LF tag"},
{"ti", CmdLFTI, 1, "{ TI RFIDs... }"},
{"hitag", CmdLFHitag, 1, "{ Hitag tags and transponders... }"},
{"vchdemod", CmdVchDemod, 1, "['clone'] -- Demodulate samples for VeriChip"},
{NULL, NULL, 0, NULL}
};
Expand Down
203 changes: 203 additions & 0 deletions client/cmdlfhitag.c
@@ -0,0 +1,203 @@
//-----------------------------------------------------------------------------
// Copyright (C) 2012 Roel Verdult
//
// 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 Hitag support
//-----------------------------------------------------------------------------

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "data.h"
#include "proxusb.h"
#include "ui.h"
#include "cmdparser.h"
#include "common.h"
#include "util.h"
#include "hitag2.h"

static int CmdHelp(const char *Cmd);

int CmdLFHitagList(const char *Cmd)
{
uint8_t got[3000];
GetFromBigBuf(got,sizeof(got),0);

PrintAndLog("recorded activity:");
PrintAndLog(" ETU :rssi: who bytes");
PrintAndLog("---------+----+----+-----------");

int i = 0;
int prev = -1;

for (;;) {
if(i >= 1900) {
break;
}

bool isResponse;
int timestamp = *((uint32_t *)(got+i));
if (timestamp & 0x80000000) {
timestamp &= 0x7fffffff;
isResponse = 1;
} else {
isResponse = 0;
}

int metric = 0;
int parityBits = *((uint32_t *)(got+i+4));
// 4 bytes of additional information...
// maximum of 32 additional parity bit information
//
// TODO:
// at each quarter bit period we can send power level (16 levels)
// or each half bit period in 256 levels.

int len = got[i+8];

if (len > 100) {
break;
}
if (i + len >= 1900) {
break;
}

uint8_t *frame = (got+i+9);

// Break and stick with current result if buffer was not completely full
if (frame[0] == 0x44 && frame[1] == 0x44 && frame[3] == 0x44) { break; }

char line[1000] = "";
int j;
for (j = 0; j < len; j++) {
int oddparity = 0x01;
int k;

for (k=0;k<8;k++) {
oddparity ^= (((frame[j] & 0xFF) >> k) & 0x01);
}

//if((parityBits >> (len - j - 1)) & 0x01) {
if (isResponse && (oddparity != ((parityBits >> (len - j - 1)) & 0x01))) {
sprintf(line+(j*4), "%02x! ", frame[j]);
}
else {
sprintf(line+(j*4), "%02x ", frame[j]);
}
}

char metricString[100];
if (isResponse) {
sprintf(metricString, "%3d", metric);
} else {
strcpy(metricString, " ");
}

PrintAndLog(" +%7d: %s: %s %s",
(prev < 0 ? 0 : (timestamp - prev)),
metricString,
(isResponse ? "TAG" : " "),
line);

prev = timestamp;
i += (len + 9);
}
return 0;
}

int CmdLFHitagSnoop(const char *Cmd) {
UsbCommand c = {CMD_SNOOP_HITAG};
SendCommand(&c);
return 0;
}

int CmdLFHitagSim(const char *Cmd) {
UsbCommand c = {CMD_SIMULATE_HITAG};
char filename[256];
FILE* pf;
bool tag_mem_supplied;

param_getstr(Cmd,0,filename);

if (strlen(filename) > 0) {
if ((pf = fopen(filename,"rb+")) == NULL) {
PrintAndLog("Error: Could not open file [%s]",filename);
return 1;
}
tag_mem_supplied = true;
fread(c.d.asBytes,48,1,pf);
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 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 RHT2F_PASSWORD: {
num_to_bytes(param_get32ex(Cmd,1,0,16),4,htd->pwd.password);
} break;
case RHT2F_AUTHENTICATE: {
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 RHT2F_TEST_AUTH_ATTEMPTS: {
// No additional parameters needed
} break;
default: {
PrintAndLog("Error: unkown reader function %d",htf);
PrintAndLog("Hitag reader functions",htf);
PrintAndLog(" HitagS (0*)",htf);
PrintAndLog(" Hitag1 (1*)",htf);
PrintAndLog(" Hitag2 (2*)",htf);
PrintAndLog(" 21 <password> (password mode)",htf);
PrintAndLog(" 22 <nr> <ar> (authentication)",htf);
PrintAndLog(" 25 (test recorded authentications)",htf);
return 1;
} break;
}

// Copy the hitag2 function into the first argument
c.arg[0] = htf;

SendCommand(&c);
return 0;
}

static command_t CommandTableHitag[] =
{
{"help", CmdHelp, 1, "This help"},
{"list", CmdLFHitagList, 1, "List Hitag trace history"},
{"reader", CmdLFHitagReader, 1, "Act like a Hitag Reader"},
{"sim", CmdLFHitagSim, 1, "Simulate Hitag transponder"},
{"snoop", CmdLFHitagSnoop, 1, "Eavesdrop Hitag communication"},
{NULL, NULL, 0, NULL}
};

int CmdLFHitag(const char *Cmd)
{
CmdsParse(CommandTableHitag, Cmd);
return 0;
}

int CmdHelp(const char *Cmd)
{
CmdsHelp(CommandTableHitag);
return 0;
}
21 changes: 21 additions & 0 deletions client/cmdlfhitag.h
@@ -0,0 +1,21 @@
//-----------------------------------------------------------------------------
// Copyright (C) 2012 Roel Verdult
//
// 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 Hitag support
//-----------------------------------------------------------------------------

#ifndef CMDLFHITAG_H__
#define CMDLFHITAG_H__

int CmdLFHitag(const char *Cmd);

int CmdLFHitagList(const char *Cmd);
int CmdLFHitagSnoop(const char *Cmd);
int CmdLFHitagSim(const char *Cmd);
int CmdLFHitagReader(const char *Cmd);

#endif
38 changes: 30 additions & 8 deletions client/cmdmain.c
Expand Up @@ -98,6 +98,7 @@ void UsbCommandReceived(UsbCommand *UC)
// printf("%s(%x) current cmd = %x\n", __FUNCTION__, c->cmd, current_command);
/* If we recognize a response, return to avoid further processing */
switch(UC->cmd) {
// First check if we are handling a debug message
case CMD_DEBUG_PRINT_STRING: {
char s[100];
if(UC->arg[0] > 70 || UC->arg[0] < 0) {
Expand All @@ -107,11 +108,12 @@ void UsbCommandReceived(UsbCommand *UC)
s[UC->arg[0]] = '\0';
PrintAndLog("#db# %s ", s);
return;
}
} break;

case CMD_DEBUG_PRINT_INTEGERS:
case CMD_DEBUG_PRINT_INTEGERS: {
PrintAndLog("#db# %08x, %08x, %08x \r\n", UC->arg[0], UC->arg[1], UC->arg[2]);
return;
} break;

case CMD_MEASURED_ANTENNA_TUNING: {
int peakv, peakf;
Expand All @@ -122,7 +124,6 @@ void UsbCommandReceived(UsbCommand *UC)
peakf = UC->arg[2] & 0xffff;
peakv = UC->arg[2] >> 16;
PrintAndLog("");
PrintAndLog("");
PrintAndLog("# LF antenna: %5.2f V @ 125.00 kHz", vLf125/1000.0);
PrintAndLog("# LF antenna: %5.2f V @ 134.00 kHz", vLf134/1000.0);
PrintAndLog("# LF optimal: %5.2f V @%9.2f kHz", peakv/1000.0, 12000.0/(peakf+1));
Expand All @@ -135,12 +136,32 @@ void UsbCommandReceived(UsbCommand *UC)
PrintAndLog("# Your HF antenna is unusable.");
else if (vHf<5000)
PrintAndLog("# Your HF antenna is marginal.");
return;
}
default:
break;
} break;

default: {
// Maybe it's a response
switch(current_command) {
case CMD_DOWNLOAD_RAW_ADC_SAMPLES_125K: {
if (UC->cmd != CMD_DOWNLOADED_RAW_ADC_SAMPLES_125K) {
PrintAndLog("unrecognized command %08x\n", UC->cmd);
break;
}
int i;
for(i=0; i<48; i++) sample_buf[i] = UC->d.asBytes[i];
received_command = UC->cmd;
} break;

default: {
} break;
}
// Store the last received command
received_command = UC->cmd;
memcpy(&current_response, UC, sizeof(UsbCommand));
} break;
}
/* Maybe it's a response: */
received_command = UC->cmd;
/*
// Maybe it's a response:
switch(current_command) {
case CMD_DOWNLOAD_RAW_ADC_SAMPLES_125K:
if (UC->cmd != CMD_DOWNLOADED_RAW_ADC_SAMPLES_125K) goto unexpected_response;
Expand All @@ -163,4 +184,5 @@ void UsbCommandReceived(UsbCommand *UC)
memcpy(&current_response, UC, sizeof(UsbCommand));
received_command = UC->cmd;
}
*/
}
29 changes: 15 additions & 14 deletions client/data.c
Expand Up @@ -17,19 +17,20 @@

uint8_t sample_buf[SAMPLE_BUFFER_SIZE];

void GetFromBigBuf(uint8_t *dest, int bytes)
void GetFromBigBuf(uint8_t *dest, int bytes, int start_index)
{
int n = bytes/4;

if (n % 48 != 0) {
PrintAndLog("bad len in GetFromBigBuf");
return;
}

for (int i = 0; i < n; i += 12) {
UsbCommand c = {CMD_DOWNLOAD_RAW_ADC_SAMPLES_125K, {i, 0, 0}};
SendCommand(&c);
WaitForResponse(CMD_DOWNLOADED_RAW_ADC_SAMPLES_125K);
memcpy(dest+(i*4), sample_buf, 48);
}
start_index = ((start_index/12)*12);
int n = (((bytes/4)/48)*48) + start_index;
/*
if (n % 48 != 0) {
PrintAndLog("bad len in GetFromBigBuf");
return;
}
*/
for (int i = start_index; i < n; i += 12) {
UsbCommand c = {CMD_DOWNLOAD_RAW_ADC_SAMPLES_125K, {i, 0, 0}};
SendCommand(&c);
WaitForResponse(CMD_DOWNLOADED_RAW_ADC_SAMPLES_125K);
memcpy(dest+(i*4), sample_buf, 48);
}
}
2 changes: 1 addition & 1 deletion client/data.h
Expand Up @@ -18,6 +18,6 @@
extern uint8_t sample_buf[SAMPLE_BUFFER_SIZE];
#define arraylen(x) (sizeof(x)/sizeof((x)[0]))

void GetFromBigBuf(uint8_t *dest, int bytes);
void GetFromBigBuf(uint8_t *dest, int bytes, int start_index);

#endif

0 comments on commit db09cb3

Please sign in to comment.