TEST of creating branch simular to PM3master.

This commit is contained in:
iceman1001 2015-01-05 16:31:19 +01:00
commit 052bbe08d0
133 changed files with 4428 additions and 14173 deletions

View file

@ -1,68 +1,87 @@
The iceman fork.
NOTICE: NOTICE:
(2014-03-26)
This is now the official Proxmark repository!
The official Proxmark repository is found here: https://github.com/Proxmark/proxmark3 INTRODUCTION:
The proxmark3 is a powerful general purpose RFID tool, the size of a deck
of cards, designed to snoop, listen and emulate everything from
Low Frequency (125kHz) to High Frequency (13.56MHz) tags.
NEWS: This repository contains enough software, logic (for the FPGA), and design
documentation for the hardware that you could, at least in theory,
do something useful with a proxmark3.
Whats in this fork? I have scraped the web for different enhancements to the PM3 source code and not all of them ever found their way to the master branch. RESOURCES:
Among the stuff is
* Jonor's hf 14a raw timing patch * This repository!
* Piwi's updates. (usually gets into the master) https://github.com/Proxmark/proxmark3
* Holiman's iclass, (usually gets into the master)
* Marshmellow's LF fixes
* Midnitesnake's Ultralight, Ultralight-c enhancements
* Izsh's lf peak modification / iir-filtering
* Aspers's tips and tricks from inside the PM3-gui-tool, settings.xml and other stuff.
* My own desfire, Ultralight extras, LF T55xx enhancements, bugs fixes (filelength, hf mf commands ), TNP3xxx lua scripts, Awid26, skidata scripts (will come)
* other obscure patches like for the sammy-mode, (offline you know), tagidentifications, defaultkeys.
Give me a hint, and I'll see if I can't merge in the stuff you have. * The Wiki
https://github.com/Proxmark/proxmark3/wiki
I don't actually know how to make small pull-request to github :( and that is the number one reason for me not pushing a lot of things back to the PM3 master. * The GitHub page
http://proxmark.github.io/proxmark3/
PM3 GUI: * The Forum
http://www.proxmark.org/forum
I do tend to rename and move stuff around, the official PM3-GUI from Gaucho will not work so well. *sorry*
* The IRC chanel
irc.freenode.org #proxmark3
-or-
http://webchat.freenode.net/?channels=#proxmark3
DEVELOPMENT: DEVELOPMENT:
This fork is adjusted to compile on windows/mingw environment with Qt5.3.1 & GCC 4.8 The tools required to build or run the project will vary depending on
For people with linux you will need to patch some source code and some small change to one makefile. If you are lazy, you google the forum and find asper's or holimans makefile or you find your solution below. your operating system. Please refer to the Wiki for details.
Common errors linux/macOS finds * https://github.com/Proxmark/proxmark3/wiki
Error:
* loclass/fileutils.c:15:2: warning: implicit declaration of function _stat [-Wimplicit-function-declaration]
Solution:
* Remove the "unscore" sign. In linux you use without underscore, in windows you need a underscore.
Error: OBTAINING HARDWARE:
* \client\makefile the parameter -lgdi32
Solution:
* Remove parameter.
Error: The Proxmark 3 is available for purcahse (assembled and tested) from the
* Using older Qt4.6 gives compilation errors. following locations:
Solution
* Upgrade to Qt5.3.1
OR
* Change these two line in \client\makefile
CXXFLAGS = -I$(QTDIR)/include -I$(QTDIR)/include/QtCore -I$(QTDIR)/include/QtGui -I$(QTDIR)/include/QtWidgets -I/mingw/include
QTLDLIBS = -L$(QTDIR)/lib -lQt5Core -lQt5Gui -lQt5Widgets
TO * http://proxmark3.com/
* http://www.xfpga.com/
CXXFLAGS = -I$(QTDIR)/include -I$(QTDIR)/include/QtCore -I$(QTDIR)/include/QtGui Most of the ultra-low-volume contract assemblers could put
QTLDLIBS = -L$(QTDIR)/lib -lQtCore4 -lQtGui4 something like this together with a reasonable yield. A run of around
a dozen units is probably cost-effective. The BOM includes (possibly-
outdated) component pricing, and everything is available from Digikey
and the usual distributors.
If you've never assembled a modern circuit board by hand, then this is
not a good place to start. Some of the components (e.g. the crystals)
must not be assembled with a soldering iron, and require hot air.
The schematics are included; the component values given are not
necessarily correct for all situations, but it should be possible to do
nearly anything you would want with appropriate population options.
The printed circuit board artwork is also available, as Gerbers and an
Excellon drill file.
An old Qt4 version makefile is found here: http://www.icesql.se/proxmark3/code/linuxmakefile.txt but this one doesn't have all new files in it. So I don't recommend it. LICENSING:
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
Jonathan Westhues
user jwesthues, at host cq.cx
January 2015, Sweden May 2007, Cambridge MA
iceman at host iuse.se

View file

@ -6,7 +6,7 @@
// LCD code // LCD code
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
#include "../include/proxmark3.h" #include "proxmark3.h"
#include "apps.h" #include "apps.h"
#include "LCD.h" #include "LCD.h"
#include "fonts.h" #include "fonts.h"

View file

@ -10,7 +10,7 @@ APP_INCLUDES = apps.h
#remove one of the following defines and comment out the relevant line #remove one of the following defines and comment out the relevant line
#in the next section to remove that particular feature from compilation #in the next section to remove that particular feature from compilation
APP_CFLAGS = -DWITH_LF -DWITH_ISO15693 -DWITH_ISO14443a -DWITH_ISO14443b -DWITH_ICLASS -DWITH_LEGICRF -DWITH_HITAG -DWITH_CRC -fno-strict-aliasing APP_CFLAGS = -DWITH_LF -DWITH_ISO15693 -DWITH_ISO14443a -DWITH_ISO14443b -DWITH_ICLASS -DWITH_LEGICRF -DWITH_HITAG
#-DWITH_LCD #-DWITH_LCD
#SRC_LCD = fonts.c LCD.c #SRC_LCD = fonts.c LCD.c
@ -18,8 +18,7 @@ SRC_LF = lfops.c hitag2.c
SRC_ISO15693 = iso15693.c iso15693tools.c SRC_ISO15693 = iso15693.c iso15693tools.c
SRC_ISO14443a = epa.c iso14443a.c mifareutil.c mifarecmd.c mifaresniff.c SRC_ISO14443a = epa.c iso14443a.c mifareutil.c mifarecmd.c mifaresniff.c
SRC_ISO14443b = iso14443.c SRC_ISO14443b = iso14443.c
SRC_CRAPTO1 = crapto1.c crypto1.c des.c aes.c desfire_key.c desfire_crypto.c mifaredesfire.c SRC_CRAPTO1 = crapto1.c crypto1.c
SRC_CRC = iso14443crc.c crc.c crc16.c crc32.c
THUMBSRC = start.c \ THUMBSRC = start.c \
$(SRC_LCD) \ $(SRC_LCD) \
@ -35,14 +34,15 @@ THUMBSRC = start.c \
# These are to be compiled in ARM mode # These are to be compiled in ARM mode
ARMSRC = fpgaloader.c \ ARMSRC = fpgaloader.c \
legicrf.c \ legicrf.c \
iso14443crc.c \
crc16.c \
lfdemod.c \ lfdemod.c \
$(SRC_ISO14443a) \ $(SRC_ISO14443a) \
$(SRC_ISO14443b) \ $(SRC_ISO14443b) \
$(SRC_CRAPTO1) \ $(SRC_CRAPTO1) \
$(SRC_CRC) \
legic_prng.c \ legic_prng.c \
iclass.c iclass.c \
crc.c
# stdint.h provided locally until GCC 4.5 becomes C99 compliant # stdint.h provided locally until GCC 4.5 becomes C99 compliant
APP_CFLAGS += -I. APP_CFLAGS += -I.

File diff suppressed because it is too large Load diff

View file

@ -1,30 +0,0 @@
/*
* AES Cryptographic Algorithm Header File. Include this header file in
* your source which uses these given APIs. (This source is kept under
* public domain)
*/
// AES context structure
typedef struct {
unsigned int Ek[60];
unsigned int Dk[60];
unsigned int Iv[4];
unsigned char Nr;
unsigned char Mode;
} AesCtx;
// key length in bytes
#define KEY128 16
#define KEY192 24
#define KEY256 32
// block size in bytes
#define BLOCKSZ 16
// mode
#define EBC 0
#define CBC 1
// AES API function prototype
int AesCtxIni(AesCtx *pCtx, unsigned char *pIV, unsigned char *pKey, unsigned int KeyLen, unsigned char Mode);
int AesEncrypt(AesCtx *pCtx, unsigned char *pData, unsigned char *pCipher, unsigned int DataLen);
int AesDecrypt(AesCtx *pCtx, unsigned char *pCipher, unsigned char *pData, unsigned int CipherLen);

View file

@ -10,20 +10,19 @@
// executes. // executes.
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
#include "../common/usb_cdc.h" #include "usb_cdc.h"
#include "../common/cmd.h" #include "cmd.h"
#include "../include/proxmark3.h" #include "proxmark3.h"
#include "apps.h" #include "apps.h"
#include "util.h" #include "util.h"
#include "printf.h" #include "printf.h"
#include "string.h" #include "string.h"
#include <stdarg.h> #include <stdarg.h>
#include "legicrf.h" #include "legicrf.h"
#include "../include/hitag2.h" #include <hitag2.h>
#ifdef WITH_LCD #ifdef WITH_LCD
#include "LCD.h" #include "LCD.h"
@ -37,7 +36,7 @@
// is the order in which they go out on the wire. // is the order in which they go out on the wire.
//============================================================================= //=============================================================================
#define TOSEND_BUFFER_SIZE (9*MAX_FRAME_SIZE + 1 + 1 + 2) // 8 data bits and 1 parity bit per payload byte, 1 correction bit, 1 SOC bit, 2 EOC bits #define TOSEND_BUFFER_SIZE (9*MAX_FRAME_SIZE + 1 + 1 + 2) // 8 data bits and 1 parity bit per payload byte, 1 correction bit, 1 SOC bit, 2 EOC bits
uint8_t ToSend[TOSEND_BUFFER_SIZE]; uint8_t ToSend[TOSEND_BUFFER_SIZE];
int ToSendMax; int ToSendMax;
static int ToSendBit; static int ToSendBit;
@ -69,7 +68,7 @@ void ToSendStuffBit(int b)
ToSendBit++; ToSendBit++;
if(ToSendMax >= sizeof(ToSend)) { if(ToSendMax >= sizeof(ToSend)) {
ToSendBit = 0; ToSendBit = 0;
DbpString("ToSendStuffBit overflowed!"); DbpString("ToSendStuffBit overflowed!");
} }
@ -173,7 +172,7 @@ void MeasureAntennaTuning(void)
int i, adcval = 0, peak = 0, peakv = 0, peakf = 0; //ptr = 0 int i, adcval = 0, peak = 0, peakv = 0, peakf = 0; //ptr = 0
int vLf125 = 0, vLf134 = 0, vHf = 0; // in mV int vLf125 = 0, vLf134 = 0, vHf = 0; // in mV
LED_B_ON(); LED_B_ON();
/* /*
* Sweeps the useful LF range of the proxmark from * Sweeps the useful LF range of the proxmark from
@ -207,7 +206,7 @@ void MeasureAntennaTuning(void)
for (i=18; i >= 0; i--) LF_Results[i] = 0; for (i=18; i >= 0; i--) LF_Results[i] = 0;
LED_A_ON(); LED_A_ON();
// Let the FPGA drive the high-frequency antenna around 13.56 MHz. // Let the FPGA drive the high-frequency antenna around 13.56 MHz.
FpgaDownloadAndGo(FPGA_BITSTREAM_HF); FpgaDownloadAndGo(FPGA_BITSTREAM_HF);
FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_READER_RX_XCORR); FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_READER_RX_XCORR);
@ -218,9 +217,9 @@ void MeasureAntennaTuning(void)
cmd_send(CMD_MEASURED_ANTENNA_TUNING,vLf125|(vLf134<<16),vHf,peakf|(peakv<<16),LF_Results,256); cmd_send(CMD_MEASURED_ANTENNA_TUNING,vLf125|(vLf134<<16),vHf,peakf|(peakv<<16),LF_Results,256);
FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
LED_A_OFF(); LED_A_OFF();
LED_B_OFF(); LED_B_OFF();
return; return;
} }
void MeasureAntennaTuningHf(void) void MeasureAntennaTuningHf(void)
@ -362,7 +361,7 @@ void SamyRun()
for (;;) for (;;)
{ {
usb_poll(); usb_poll();
WDT_HIT(); WDT_HIT();
// Was our button held down or pressed? // Was our button held down or pressed?
int button_pressed = BUTTON_HELD(1000); int button_pressed = BUTTON_HELD(1000);
@ -626,7 +625,7 @@ void UsbPacketReceived(uint8_t *packet, int len)
{ {
UsbCommand *c = (UsbCommand *)packet; UsbCommand *c = (UsbCommand *)packet;
//Dbprintf("received %d bytes, with command: 0x%04x and args: %d %d %d",len,c->cmd,c->arg[0],c->arg[1],c->arg[2]); // Dbprintf("received %d bytes, with command: 0x%04x and args: %d %d %d",len,c->cmd,c->arg[0],c->arg[1],c->arg[2]);
switch(c->cmd) { switch(c->cmd) {
#ifdef WITH_LF #ifdef WITH_LF
@ -669,8 +668,9 @@ void UsbPacketReceived(uint8_t *packet, int len)
WriteTItag(c->arg[0],c->arg[1],c->arg[2]); WriteTItag(c->arg[0],c->arg[1],c->arg[2]);
break; break;
case CMD_SIMULATE_TAG_125K: case CMD_SIMULATE_TAG_125K:
SimulateTagLowFrequency(c->arg[0], c->arg[1], 0); LED_A_ON();
//SimulateTagLowFrequencyA(c->arg[0], c->arg[1]); SimulateTagLowFrequency(c->arg[0], c->arg[1], 1);
LED_A_OFF();
break; break;
case CMD_LF_SIMULATE_BIDIR: case CMD_LF_SIMULATE_BIDIR:
SimulateTagLowFrequencyBidir(c->arg[0], c->arg[1]); SimulateTagLowFrequencyBidir(c->arg[0], c->arg[1]);
@ -792,10 +792,6 @@ void UsbPacketReceived(uint8_t *packet, int len)
EPA_PACE_Collect_Nonce(c); EPA_PACE_Collect_Nonce(c);
break; break;
// case CMD_EPA_:
// EpaFoo(c);
// break;
case CMD_READER_MIFARE: case CMD_READER_MIFARE:
ReaderMifare(c->arg[0]); ReaderMifare(c->arg[0]);
break; break;
@ -805,17 +801,8 @@ void UsbPacketReceived(uint8_t *packet, int len)
case CMD_MIFAREU_READBL: case CMD_MIFAREU_READBL:
MifareUReadBlock(c->arg[0],c->d.asBytes); MifareUReadBlock(c->arg[0],c->d.asBytes);
break; break;
case CMD_MIFAREUC_AUTH1:
MifareUC_Auth1(c->arg[0],c->d.asBytes);
break;
case CMD_MIFAREUC_AUTH2:
MifareUC_Auth2(c->arg[0],c->d.asBytes);
break;
case CMD_MIFAREU_READCARD: case CMD_MIFAREU_READCARD:
MifareUReadCard(c->arg[0],c->arg[1],c->d.asBytes); MifareUReadCard(c->arg[0],c->d.asBytes);
break;
case CMD_MIFAREUC_READCARD:
MifareUReadCard(c->arg[0],c->arg[1],c->d.asBytes);
break; break;
case CMD_MIFARE_READSC: case CMD_MIFARE_READSC:
MifareReadSector(c->arg[0], c->arg[1], c->arg[2], c->d.asBytes); MifareReadSector(c->arg[0], c->arg[1], c->arg[2], c->d.asBytes);
@ -871,28 +858,6 @@ void UsbPacketReceived(uint8_t *packet, int len)
case CMD_MIFARE_SNIFFER: case CMD_MIFARE_SNIFFER:
SniffMifare(c->arg[0]); SniffMifare(c->arg[0]);
break; break;
// mifare desfire
case CMD_MIFARE_DESFIRE_READBL:
break;
case CMD_MIFARE_DESFIRE_WRITEBL:
break;
case CMD_MIFARE_DESFIRE_AUTH1:
MifareDES_Auth1(c->arg[0], c->arg[1], c->arg[2], c->d.asBytes);
break;
case CMD_MIFARE_DESFIRE_AUTH2:
//MifareDES_Auth2(c->arg[0],c->d.asBytes);
break;
// case CMD_MIFARE_DES_READER:
// ReaderMifareDES(c->arg[0], c->arg[1], c->d.asBytes);
//break;
case CMD_MIFARE_DESFIRE_INFO:
MifareDesfireGetInformation();
break;
case CMD_MIFARE_DESFIRE:
MifareSendCommand(c->arg[0], c->arg[1], c->d.asBytes);
break;
#endif #endif
#ifdef WITH_ICLASS #ifdef WITH_ICLASS
@ -907,7 +872,7 @@ void UsbPacketReceived(uint8_t *packet, int len)
ReaderIClass(c->arg[0]); ReaderIClass(c->arg[0]);
break; break;
case CMD_READER_ICLASS_REPLAY: case CMD_READER_ICLASS_REPLAY:
ReaderIClass_Replay(c->arg[0], c->d.asBytes); ReaderIClass_Replay(c->arg[0], c->d.asBytes);
break; break;
#endif #endif
@ -1036,7 +1001,7 @@ void __attribute__((noreturn)) AppMain(void)
LED_A_OFF(); LED_A_OFF();
// Init USB device // Init USB device
usb_enable(); usb_enable();
// The FPGA gets its clock from us from PCK0 output, so set that up. // The FPGA gets its clock from us from PCK0 output, so set that up.
AT91C_BASE_PIOA->PIO_BSR = GPIO_PCK0; AT91C_BASE_PIOA->PIO_BSR = GPIO_PCK0;
@ -1066,12 +1031,12 @@ void __attribute__((noreturn)) AppMain(void)
size_t rx_len; size_t rx_len;
for(;;) { for(;;) {
if (usb_poll()) { if (usb_poll()) {
rx_len = usb_read(rx,sizeof(UsbCommand)); rx_len = usb_read(rx,sizeof(UsbCommand));
if (rx_len) { if (rx_len) {
UsbPacketReceived(rx,rx_len); UsbPacketReceived(rx,rx_len);
} }
} }
WDT_HIT(); WDT_HIT();
#ifdef WITH_LF #ifdef WITH_LF

View file

@ -14,40 +14,28 @@
#include <stdint.h> #include <stdint.h>
#include <stddef.h> #include <stddef.h>
#include <stdlib.h> #include "common.h"
#include <sys/types.h> #include "hitag2.h"
#include <string.h> #include "mifare.h"
#include <strings.h>
#include "../include/common.h"
#include "../include/hitag2.h"
#include "../include/mifare.h"
//#include <openssl/des.h>
//#include <openssl/aes.h>
//#include "des.h"
//#include "aes.h"
#include "../common/desfire.h"
#include "../common/crc32.h"
// The large multi-purpose buffer, typically used to hold A/D samples, // The large multi-purpose buffer, typically used to hold A/D samples,
// maybe processed in some way. // maybe processed in some way.
#define BIGBUF_SIZE 40000 #define BIGBUF_SIZE 40000
uint32_t BigBuf[BIGBUF_SIZE / sizeof(uint32_t)]; uint32_t BigBuf[BIGBUF_SIZE / sizeof(uint32_t)];
#define TRACE_OFFSET 0 #define TRACE_OFFSET 0
#define TRACE_SIZE 3000 #define TRACE_SIZE 3000
#define RECV_CMD_OFFSET (TRACE_OFFSET + TRACE_SIZE) #define RECV_CMD_OFFSET (TRACE_OFFSET + TRACE_SIZE)
#define MAX_FRAME_SIZE 256 #define MAX_FRAME_SIZE 256
#define MAX_PARITY_SIZE ((MAX_FRAME_SIZE + 1)/ 8) #define MAX_PARITY_SIZE ((MAX_FRAME_SIZE + 1)/ 8)
#define RECV_CMD_PAR_OFFSET (RECV_CMD_OFFSET + MAX_FRAME_SIZE) #define RECV_CMD_PAR_OFFSET (RECV_CMD_OFFSET + MAX_FRAME_SIZE)
#define RECV_RESP_OFFSET (RECV_CMD_PAR_OFFSET + MAX_PARITY_SIZE) #define RECV_RESP_OFFSET (RECV_CMD_PAR_OFFSET + MAX_PARITY_SIZE)
#define RECV_RESP_PAR_OFFSET (RECV_RESP_OFFSET + MAX_FRAME_SIZE) #define RECV_RESP_PAR_OFFSET (RECV_RESP_OFFSET + MAX_FRAME_SIZE)
#define CARD_MEMORY_OFFSET (RECV_RESP_PAR_OFFSET + MAX_PARITY_SIZE) #define CARD_MEMORY_OFFSET (RECV_RESP_PAR_OFFSET + MAX_PARITY_SIZE)
#define CARD_MEMORY_SIZE 4096 #define CARD_MEMORY_SIZE 4096
#define DMA_BUFFER_OFFSET CARD_MEMORY_OFFSET #define DMA_BUFFER_OFFSET CARD_MEMORY_OFFSET
#define DMA_BUFFER_SIZE CARD_MEMORY_SIZE #define DMA_BUFFER_SIZE CARD_MEMORY_SIZE
#define FREE_BUFFER_OFFSET (CARD_MEMORY_OFFSET + CARD_MEMORY_SIZE) #define FREE_BUFFER_OFFSET (CARD_MEMORY_OFFSET + CARD_MEMORY_SIZE)
#define FREE_BUFFER_SIZE (BIGBUF_SIZE - FREE_BUFFER_OFFSET - 1) #define FREE_BUFFER_SIZE (BIGBUF_SIZE - FREE_BUFFER_OFFSET - 1)
extern const uint8_t OddByteParity[256]; extern const uint8_t OddByteParity[256];
extern uint8_t *trace; // = (uint8_t *) BigBuf; extern uint8_t *trace; // = (uint8_t *) BigBuf;
@ -76,10 +64,7 @@ void ToSendReset(void);
void ListenReaderField(int limit); void ListenReaderField(int limit);
void AcquireRawAdcSamples125k(int at134khz); void AcquireRawAdcSamples125k(int at134khz);
void SnoopLFRawAdcSamples(int divisor, int trigger_threshold); void SnoopLFRawAdcSamples(int divisor, int trigger_threshold);
void DoAcquisition125k_internal(int trigger_threshold, bool silent); void DoAcquisition125k(int trigger_threshold);
void DoAcquisition125k_threshold(int trigger_threshold);
void DoAcquisition125k();
extern int ToSendMax; extern int ToSendMax;
extern uint8_t ToSend[]; extern uint8_t ToSend[];
extern uint32_t BigBuf[]; extern uint32_t BigBuf[];
@ -144,10 +129,8 @@ void ReadTItag(void);
void WriteTItag(uint32_t idhi, uint32_t idlo, uint16_t crc); void WriteTItag(uint32_t idhi, uint32_t idlo, uint16_t crc);
void AcquireTiType(void); void AcquireTiType(void);
void AcquireRawBitsTI(void); void AcquireRawBitsTI(void);
void SimulateTagLowFrequency( uint16_t period, uint32_t gap, uint8_t ledcontrol); void SimulateTagLowFrequency(int period, int gap, int ledcontrol);
void SimulateTagLowFrequencyA(int period, int gap); void CmdHIDsimTAG(int hi, int lo, int ledcontrol);
void CmdHIDsimTAG(int hi, int lo, uint8_t ledcontrol);
void CmdHIDdemodFSK(int findone, int *high, int *low, int ledcontrol); void CmdHIDdemodFSK(int findone, int *high, int *low, int ledcontrol);
void CmdEM410xdemod(int findone, int *high, int *low, int ledcontrol); void CmdEM410xdemod(int findone, int *high, int *low, int ledcontrol);
void CmdIOdemodFSK(int findone, int *high, int *low, int ledcontrol); void CmdIOdemodFSK(int findone, int *high, int *low, int ledcontrol);
@ -160,7 +143,6 @@ void CopyIndala224toT55x7(int uid1, int uid2, int uid3, int uid4, int uid5, int
void T55xxWriteBlock(uint32_t Data, uint32_t Block, uint32_t Pwd, uint8_t PwdMode); void T55xxWriteBlock(uint32_t Data, uint32_t Block, uint32_t Pwd, uint8_t PwdMode);
void T55xxReadBlock(uint32_t Block, uint32_t Pwd, uint8_t PwdMode ); void T55xxReadBlock(uint32_t Block, uint32_t Pwd, uint8_t PwdMode );
void T55xxReadTrace(void); void T55xxReadTrace(void);
void TurnReadLFOn();
int DemodPCF7931(uint8_t **outBlocks); int DemodPCF7931(uint8_t **outBlocks);
int IsBlock0PCF7931(uint8_t *Block); int IsBlock0PCF7931(uint8_t *Block);
int IsBlock1PCF7931(uint8_t *Block); int IsBlock1PCF7931(uint8_t *Block);
@ -181,7 +163,7 @@ void SimulateIso14443aTag(int tagType, int uid_1st, int uid_2nd, byte_t* data);
void ReaderIso14443a(UsbCommand * c); void ReaderIso14443a(UsbCommand * c);
// Also used in iclass.c // Also used in iclass.c
bool RAMFUNC LogTrace(const uint8_t *btBytes, uint16_t len, uint32_t timestamp_start, uint32_t timestamp_end, uint8_t *parity, bool readerToTag); bool RAMFUNC LogTrace(const uint8_t *btBytes, uint16_t len, uint32_t timestamp_start, uint32_t timestamp_end, uint8_t *parity, bool readerToTag);
void GetParity(const uint8_t * pbtCmd, uint16_t len, uint8_t *parity); void GetParity(const uint8_t *pbtCmd, uint16_t len, uint8_t *parity);
void iso14a_set_trigger(bool enable); void iso14a_set_trigger(bool enable);
void iso14a_clear_trace(); void iso14a_clear_trace();
void iso14a_set_tracing(bool enable); void iso14a_set_tracing(bool enable);
@ -195,9 +177,7 @@ void ReaderMifare(bool first_try);
int32_t dist_nt(uint32_t nt1, uint32_t nt2); int32_t dist_nt(uint32_t nt1, uint32_t nt2);
void MifareReadBlock(uint8_t arg0, uint8_t arg1, uint8_t arg2, uint8_t *data); void MifareReadBlock(uint8_t arg0, uint8_t arg1, uint8_t arg2, uint8_t *data);
void MifareUReadBlock(uint8_t arg0,uint8_t *datain); void MifareUReadBlock(uint8_t arg0,uint8_t *datain);
void MifareUC_Auth1(uint8_t arg0, uint8_t *datain); void MifareUReadCard(uint8_t arg0,uint8_t *datain);
void MifareUC_Auth2(uint32_t arg0, uint8_t *datain);
void MifareUReadCard(uint8_t arg0, int Pages, uint8_t *datain);
void MifareReadSector(uint8_t arg0, uint8_t arg1, uint8_t arg2, uint8_t *datain); void MifareReadSector(uint8_t arg0, uint8_t arg1, uint8_t arg2, uint8_t *datain);
void MifareWriteBlock(uint8_t arg0, uint8_t arg1, uint8_t arg2, uint8_t *datain); void MifareWriteBlock(uint8_t arg0, uint8_t arg1, uint8_t arg2, uint8_t *datain);
void MifareUWriteBlock(uint8_t arg0,uint8_t *datain); void MifareUWriteBlock(uint8_t arg0,uint8_t *datain);
@ -214,36 +194,6 @@ void MifareCSetBlock(uint32_t arg0, uint32_t arg1, uint32_t arg2, uint8_t *datai
void MifareCGetBlock(uint32_t arg0, uint32_t arg1, uint32_t arg2, uint8_t *datain); void MifareCGetBlock(uint32_t arg0, uint32_t arg1, uint32_t arg2, uint8_t *datain);
void MifareCIdent(); // is "magic chinese" card? void MifareCIdent(); // is "magic chinese" card?
//desfire
void Mifare_DES_Auth1(uint8_t arg0,uint8_t *datain);
void Mifare_DES_Auth2(uint32_t arg0, uint8_t *datain);
// mifaredesfire.h
bool InitDesfireCard();
void MifareSendCommand(uint8_t arg0,uint8_t arg1, uint8_t *datain);
void MifareDesfireGetInformation();
void MifareDES_Auth1(uint8_t arg0,uint8_t arg1,uint8_t arg2, uint8_t *datain);
void ReaderMifareDES(uint32_t param, uint32_t param2, uint8_t * datain);
int DesfireAPDU(uint8_t *cmd, size_t cmd_len, uint8_t *dataout);
size_t CreateAPDU( uint8_t *datain, size_t len, uint8_t *dataout);
void OnSuccess();
void OnError();
// desfire_crypto.h
void *mifare_cryto_preprocess_data (desfiretag_t tag, void *data, size_t *nbytes, off_t offset, int communication_settings);
void *mifare_cryto_postprocess_data (desfiretag_t tag, void *data, ssize_t *nbytes, int communication_settings);
void mifare_cypher_single_block (desfirekey_t key, uint8_t *data, uint8_t *ivect, MifareCryptoDirection direction, MifareCryptoOperation operation, size_t block_size);
void mifare_cypher_blocks_chained (desfiretag_t tag, desfirekey_t key, uint8_t *ivect, uint8_t *data, size_t data_size, MifareCryptoDirection direction, MifareCryptoOperation operation);
size_t key_block_size (const desfirekey_t key);
size_t padded_data_length (const size_t nbytes, const size_t block_size);
size_t maced_data_length (const desfirekey_t key, const size_t nbytes);
size_t enciphered_data_length (const desfiretag_t tag, const size_t nbytes, int communication_settings);
void cmac_generate_subkeys (desfirekey_t key);
void cmac (const desfirekey_t key, uint8_t *ivect, const uint8_t *data, size_t len, uint8_t *cmac);
/// iso15693.h /// iso15693.h
void RecordRawAdcSamplesIso15693(void); void RecordRawAdcSamplesIso15693(void);
void AcquireRawAdcSamplesIso15693(void); void AcquireRawAdcSamplesIso15693(void);

View file

@ -44,12 +44,12 @@ static void quicksort(uint32_t* const start, uint32_t* const stop)
else if(*rit > *start) else if(*rit > *start)
--rit; --rit;
else else
*it ^= ( (*it ^= *rit ), *rit ^= *it); *it ^= (*it ^= *rit, *rit ^= *it);
if(*rit >= *start) if(*rit >= *start)
--rit; --rit;
if(rit != start) if(rit != start)
*rit ^= ( (*rit ^= *start), *start ^= *rit); *rit ^= (*rit ^= *start, *start ^= *rit);
quicksort(start, rit - 1); quicksort(start, rit - 1);
quicksort(rit + 1, stop); quicksort(rit + 1, stop);

View file

@ -1,383 +0,0 @@
/* des.c */
/*
This file is part of the ARM-Crypto-Lib.
Copyright (C) 2006-2010 Daniel Otte (daniel.otte@rub.de)
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
/**
* \file des.c
* \author Daniel Otte
* \email daniel.otte@rub.de
* \date 2007-06-16
* \brief DES and EDE-DES implementation
* \license GPLv3 or later
*
*/
#include <stdint.h>
#include <string.h>
const uint8_t sbox[256] = {
/* S-box 1 */
0xE4, 0xD1, 0x2F, 0xB8, 0x3A, 0x6C, 0x59, 0x07,
0x0F, 0x74, 0xE2, 0xD1, 0xA6, 0xCB, 0x95, 0x38,
0x41, 0xE8, 0xD6, 0x2B, 0xFC, 0x97, 0x3A, 0x50,
0xFC, 0x82, 0x49, 0x17, 0x5B, 0x3E, 0xA0, 0x6D,
/* S-box 2 */
0xF1, 0x8E, 0x6B, 0x34, 0x97, 0x2D, 0xC0, 0x5A,
0x3D, 0x47, 0xF2, 0x8E, 0xC0, 0x1A, 0x69, 0xB5,
0x0E, 0x7B, 0xA4, 0xD1, 0x58, 0xC6, 0x93, 0x2F,
0xD8, 0xA1, 0x3F, 0x42, 0xB6, 0x7C, 0x05, 0xE9,
/* S-box 3 */
0xA0, 0x9E, 0x63, 0xF5, 0x1D, 0xC7, 0xB4, 0x28,
0xD7, 0x09, 0x34, 0x6A, 0x28, 0x5E, 0xCB, 0xF1,
0xD6, 0x49, 0x8F, 0x30, 0xB1, 0x2C, 0x5A, 0xE7,
0x1A, 0xD0, 0x69, 0x87, 0x4F, 0xE3, 0xB5, 0x2C,
/* S-box 4 */
0x7D, 0xE3, 0x06, 0x9A, 0x12, 0x85, 0xBC, 0x4F,
0xD8, 0xB5, 0x6F, 0x03, 0x47, 0x2C, 0x1A, 0xE9,
0xA6, 0x90, 0xCB, 0x7D, 0xF1, 0x3E, 0x52, 0x84,
0x3F, 0x06, 0xA1, 0xD8, 0x94, 0x5B, 0xC7, 0x2E,
/* S-box 5 */
0x2C, 0x41, 0x7A, 0xB6, 0x85, 0x3F, 0xD0, 0xE9,
0xEB, 0x2C, 0x47, 0xD1, 0x50, 0xFA, 0x39, 0x86,
0x42, 0x1B, 0xAD, 0x78, 0xF9, 0xC5, 0x63, 0x0E,
0xB8, 0xC7, 0x1E, 0x2D, 0x6F, 0x09, 0xA4, 0x53,
/* S-box 6 */
0xC1, 0xAF, 0x92, 0x68, 0x0D, 0x34, 0xE7, 0x5B,
0xAF, 0x42, 0x7C, 0x95, 0x61, 0xDE, 0x0B, 0x38,
0x9E, 0xF5, 0x28, 0xC3, 0x70, 0x4A, 0x1D, 0xB6,
0x43, 0x2C, 0x95, 0xFA, 0xBE, 0x17, 0x60, 0x8D,
/* S-box 7 */
0x4B, 0x2E, 0xF0, 0x8D, 0x3C, 0x97, 0x5A, 0x61,
0xD0, 0xB7, 0x49, 0x1A, 0xE3, 0x5C, 0x2F, 0x86,
0x14, 0xBD, 0xC3, 0x7E, 0xAF, 0x68, 0x05, 0x92,
0x6B, 0xD8, 0x14, 0xA7, 0x95, 0x0F, 0xE2, 0x3C,
/* S-box 8 */
0xD2, 0x84, 0x6F, 0xB1, 0xA9, 0x3E, 0x50, 0xC7,
0x1F, 0xD8, 0xA3, 0x74, 0xC5, 0x6B, 0x0E, 0x92,
0x7B, 0x41, 0x9C, 0xE2, 0x06, 0xAD, 0xF3, 0x58,
0x21, 0xE7, 0x4A, 0x8D, 0xFC, 0x90, 0x35, 0x6B
};
const uint8_t e_permtab[] ={
4, 6, /* 4 bytes in 6 bytes out*/
32, 1, 2, 3, 4, 5,
4, 5, 6, 7, 8, 9,
8, 9, 10, 11, 12, 13,
12, 13, 14, 15, 16, 17,
16, 17, 18, 19, 20, 21,
20, 21, 22, 23, 24, 25,
24, 25, 26, 27, 28, 29,
28, 29, 30, 31, 32, 1
};
const uint8_t p_permtab[] ={
4, 4, /* 32 bit -> 32 bit */
16, 7, 20, 21,
29, 12, 28, 17,
1, 15, 23, 26,
5, 18, 31, 10,
2, 8, 24, 14,
32, 27, 3, 9,
19, 13, 30, 6,
22, 11, 4, 25
};
const uint8_t ip_permtab[] ={
8, 8, /* 64 bit -> 64 bit */
58, 50, 42, 34, 26, 18, 10, 2,
60, 52, 44, 36, 28, 20, 12, 4,
62, 54, 46, 38, 30, 22, 14, 6,
64, 56, 48, 40, 32, 24, 16, 8,
57, 49, 41, 33, 25, 17, 9, 1,
59, 51, 43, 35, 27, 19, 11, 3,
61, 53, 45, 37, 29, 21, 13, 5,
63, 55, 47, 39, 31, 23, 15, 7
};
const uint8_t inv_ip_permtab[] ={
8, 8, /* 64 bit -> 64 bit */
40, 8, 48, 16, 56, 24, 64, 32,
39, 7, 47, 15, 55, 23, 63, 31,
38, 6, 46, 14, 54, 22, 62, 30,
37, 5, 45, 13, 53, 21, 61, 29,
36, 4, 44, 12, 52, 20, 60, 28,
35, 3, 43, 11, 51, 19, 59, 27,
34, 2, 42, 10, 50, 18, 58, 26,
33, 1, 41, 9, 49, 17, 57, 25
};
const uint8_t pc1_permtab[] ={
8, 7, /* 64 bit -> 56 bit*/
57, 49, 41, 33, 25, 17, 9,
1, 58, 50, 42, 34, 26, 18,
10, 2, 59, 51, 43, 35, 27,
19, 11, 3, 60, 52, 44, 36,
63, 55, 47, 39, 31, 23, 15,
7, 62, 54, 46, 38, 30, 22,
14, 6, 61, 53, 45, 37, 29,
21, 13, 5, 28, 20, 12, 4
};
const uint8_t pc2_permtab[] ={
7, 6, /* 56 bit -> 48 bit */
14, 17, 11, 24, 1, 5,
3, 28, 15, 6, 21, 10,
23, 19, 12, 4, 26, 8,
16, 7, 27, 20, 13, 2,
41, 52, 31, 37, 47, 55,
30, 40, 51, 45, 33, 48,
44, 49, 39, 56, 34, 53,
46, 42, 50, 36, 29, 32
};
const uint8_t splitin6bitword_permtab[] = {
8, 8, /* 64 bit -> 64 bit */
64, 64, 1, 6, 2, 3, 4, 5,
64, 64, 7, 12, 8, 9, 10, 11,
64, 64, 13, 18, 14, 15, 16, 17,
64, 64, 19, 24, 20, 21, 22, 23,
64, 64, 25, 30, 26, 27, 28, 29,
64, 64, 31, 36, 32, 33, 34, 35,
64, 64, 37, 42, 38, 39, 40, 41,
64, 64, 43, 48, 44, 45, 46, 47
};
const uint8_t shiftkey_permtab[] = {
7, 7, /* 56 bit -> 56 bit */
2, 3, 4, 5, 6, 7, 8, 9,
10, 11, 12, 13, 14, 15, 16, 17,
18, 19, 20, 21, 22, 23, 24, 25,
26, 27, 28, 1,
30, 31, 32, 33, 34, 35, 36, 37,
38, 39, 40, 41, 42, 43, 44, 45,
46, 47, 48, 49, 50, 51, 52, 53,
54, 55, 56, 29
};
const uint8_t shiftkeyinv_permtab[] = {
7, 7,
28, 1, 2, 3, 4, 5, 6, 7,
8, 9, 10, 11, 12, 13, 14, 15,
16, 17, 18, 19, 20, 21, 22, 23,
24, 25, 26, 27,
56, 29, 30, 31, 32, 33, 34, 35,
36, 37, 38, 39, 40, 41, 42, 43,
44, 45, 46, 47, 48, 49, 50, 51,
52, 53, 54, 55
};
/*
1 0
1 0
2 1
2 1
2 1
2 1
2 1
2 1
----
1 0
2 1
2 1
2 1
2 1
2 1
2 1
1 0
*/
#define ROTTABLE 0x7EFC
#define ROTTABLE_INV 0x3F7E
/******************************************************************************/
void permute(const uint8_t *ptable, const uint8_t *in, uint8_t *out){
uint8_t ob; /* in-bytes and out-bytes */
uint8_t byte, bit; /* counter for bit and byte */
ob = ptable[1];
ptable = &(ptable[2]);
for(byte=0; byte<ob; ++byte){
uint8_t x,t=0;
for(bit=0; bit<8; ++bit){
x=*ptable++ -1 ;
t<<=1;
if((in[x/8]) & (0x80>>(x%8)) ){
t|=0x01;
}
}
out[byte]=t;
}
}
/******************************************************************************/
void changeendian32(uint32_t * a){
*a = (*a & 0x000000FF) << 24 |
(*a & 0x0000FF00) << 8 |
(*a & 0x00FF0000) >> 8 |
(*a & 0xFF000000) >> 24;
}
/******************************************************************************/
static inline
void shiftkey(uint8_t *key){
uint8_t k[7];
memcpy(k, key, 7);
permute((uint8_t*)shiftkey_permtab, k, key);
}
/******************************************************************************/
static inline
void shiftkey_inv(uint8_t *key){
uint8_t k[7];
memcpy(k, key, 7);
permute((uint8_t*)shiftkeyinv_permtab, k, key);
}
/******************************************************************************/
static inline
uint64_t splitin6bitwords(uint64_t a){
uint64_t ret=0;
a &= 0x0000ffffffffffffLL;
permute((uint8_t*)splitin6bitword_permtab, (uint8_t*)&a, (uint8_t*)&ret);
return ret;
}
/******************************************************************************/
static inline
uint8_t substitute(uint8_t a, uint8_t * sbp){
uint8_t x;
x = sbp[a>>1];
x = (a&1)?x&0x0F:x>>4;
return x;
}
/******************************************************************************/
uint32_t des_f(uint32_t r, uint8_t* kr){
uint8_t i;
uint32_t t=0,ret;
uint64_t data;
uint8_t *sbp; /* sboxpointer */
permute((uint8_t*)e_permtab, (uint8_t*)&r, (uint8_t*)&data);
for(i=0; i<7; ++i)
((uint8_t*)&data)[i] ^= kr[i];
/* Sbox substitution */
data = splitin6bitwords(data);
sbp=(uint8_t*)sbox;
for(i=0; i<8; ++i){
uint8_t x;
x = substitute(((uint8_t*)&data)[i], sbp);
t<<=4;
t |= x;
sbp += 32;
}
changeendian32(&t);
permute((uint8_t*)p_permtab,(uint8_t*)&t, (uint8_t*)&ret);
return ret;
}
/******************************************************************************/
void des_enc(void* out, const void* in, const void* key){
#define R *((uint32_t*)&(data[4]))
#define L *((uint32_t*)&(data[0]))
uint8_t data[8],kr[6],k[7];
uint8_t i;
permute((uint8_t*)ip_permtab, (uint8_t*)in, data);
permute((uint8_t*)pc1_permtab, (const uint8_t*)key, k);
for(i=0; i<8; ++i){
shiftkey(k);
if(ROTTABLE&((1<<((i<<1)+0))) )
shiftkey(k);
permute((uint8_t*)pc2_permtab, k, kr);
L ^= des_f(R, kr);
shiftkey(k);
if(ROTTABLE&((1<<((i<<1)+1))) )
shiftkey(k);
permute((uint8_t*)pc2_permtab, k, kr);
R ^= des_f(L, kr);
}
/* L <-> R*/
R ^= L;
L ^= R;
R ^= L;
permute((uint8_t*)inv_ip_permtab, data, (uint8_t*)out);
}
/******************************************************************************/
void des_dec(void* out, const void* in, const uint8_t* key){
#define R *((uint32_t*)&(data[4]))
#define L *((uint32_t*)&(data[0]))
uint8_t data[8],kr[6],k[7];
int8_t i;
permute((uint8_t*)ip_permtab, (uint8_t*)in, data);
permute((uint8_t*)pc1_permtab, (const uint8_t*)key, k);
for(i=7; i>=0; --i){
permute((uint8_t*)pc2_permtab, k, kr);
L ^= des_f(R, kr);
shiftkey_inv(k);
if(ROTTABLE&((1<<((i<<1)+1))) ){
shiftkey_inv(k);
}
permute((uint8_t*)pc2_permtab, k, kr);
R ^= des_f(L, kr);
shiftkey_inv(k);
if(ROTTABLE&((1<<((i<<1)+0))) ){
shiftkey_inv(k);
}
}
/* L <-> R*/
R ^= L;
L ^= R;
R ^= L;
permute((uint8_t*)inv_ip_permtab, data, (uint8_t*)out);
}
/******************************************************************************/
void tdes_enc(void* out, void* in, const void* key){
des_enc(out, in, (uint8_t*)key + 0);
des_dec(out, out, (uint8_t*)key + 8);
des_enc(out, out, (uint8_t*)key +16);
}
/******************************************************************************/
void tdes_dec(void* out, void* in, const uint8_t* key){
des_dec(out, in, (uint8_t*)key +16);
des_enc(out, out, (uint8_t*)key + 8);
des_dec(out, out, (uint8_t*)key + 0);
}
/******************************************************************************/

View file

@ -1,107 +0,0 @@
/* des.h */
/*
This file is part of the ARM-Crypto-Lib.
Copyright (C) 2008 Daniel Otte (daniel.otte@rub.de)
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
/**
* \file des.h
* \author Daniel Otte
* \date 2007-06-16
* \brief des and tdes declarations
* \license GPLv3 or later
*
*/
#ifndef DES_H_
#define DES_H_
/* the FIPS 46-3 (1999-10-25) name for triple DES is triple data encryption algorithm so TDEA.
* Also we only implement the three key mode */
/** \def tdea_enc
* \brief defining an alias for void tdes_enc(void* out, const void* in, const void* key)
*/
/** \def tdea_dec
* \brief defining an alias for void tdes_dec(void* out, const void* in, const void* key)
*/
#define tdea_enc tdes_enc
#define tdea_dec tdes_dec
/** \fn void des_enc(void* out, const void* in, const void* key)
* \brief encrypt a block with DES
*
* This function encrypts a block of 64 bits (8 bytes) with the DES algorithm.
* Key expansion is done automatically. The key is 64 bits long, but note that
* only 56 bits are used (the LSB of each byte is dropped). The input and output
* blocks may overlap.
*
* \param out pointer to the block (64 bit = 8 byte) where the ciphertext is written to
* \param in pointer to the block (64 bit = 8 byte) where the plaintext is read from
* \param key pointer to the key (64 bit = 8 byte)
*/
void des_enc(void* out, const void* in, const void* key);
/** \fn void des_dec(void* out, const void* in, const void* key)
* \brief decrypt a block with DES
*
* This function decrypts a block of 64 bits (8 bytes) with the DES algorithm.
* Key expansion is done automatically. The key is 64 bits long, but note that
* only 56 bits are used (the LSB of each byte is dropped). The input and output
* blocks may overlap.
*
* \param out pointer to the block (64 bit = 8 byte) where the plaintext is written to
* \param in pointer to the block (64 bit = 8 byte) where the ciphertext is read from
* \param key pointer to the key (64 bit = 8 byte)
*/
void des_dec(void* out, const void* in, const void* key);
/** \fn void tdes_enc(void* out, const void* in, const void* key)
* \brief encrypt a block with Tripple-DES
*
* This function encrypts a block of 64 bits (8 bytes) with the Tripple-DES (EDE)
* algorithm. Key expansion is done automatically. The key is 192 bits long, but
* note that only 178 bits are used (the LSB of each byte is dropped). The input
* and output blocks may overlap.
*
* \param out pointer to the block (64 bit = 8 byte) where the ciphertext is written to
* \param in pointer to the block (64 bit = 8 byte) where the plaintext is read from
* \param key pointer to the key (192 bit = 24 byte)
*/
void tdes_enc(void* out, const void* in, const void* key);
/** \fn void tdes_dec(void* out, const void* in, const void* key)
* \brief decrypt a block with Tripple-DES
*
* This function decrypts a block of 64 bits (8 bytes) with the Tripple-DES (EDE)
* algorithm. Key expansion is done automatically. The key is 192 bits long, but
* note that only 178 bits are used (the LSB of each byte is dropped). The input
* and output blocks may overlap.
*
* \param out pointer to the block (64 bit = 8 byte) where the plaintext is written to
* \param in pointer to the block (64 bit = 8 byte) where the ciphertext is read from
* \param key pointer to the key (192 bit = 24 byte)
*/
void tdes_dec(void* out, const void* in, const void* key);
#endif /*DES_H_*/
// Copied from des.h in desfire imp.
typedef unsigned long DES_KS[16][2]; /* Single-key DES key schedule */
typedef unsigned long DES3_KS[48][2]; /* Triple-DES key schedule */
extern int Asmversion; /* 1 if we're linked with an asm version, 0 if C */

View file

@ -1,642 +0,0 @@
/*-
* Copyright (C) 2010, Romain Tartiere.
*
* This program is free software: you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published by the
* Free Software Foundation, either version 3 of the License, or (at your
* option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>
*
* $Id$
*/
/*
* This implementation was written based on information provided by the
* following documents:
*
* NIST Special Publication 800-38B
* Recommendation for Block Cipher Modes of Operation: The CMAC Mode for Authentication
* May 2005
*/
#include "desfire_crypto.h"
static void xor (const uint8_t *ivect, uint8_t *data, const size_t len);
static size_t key_macing_length (desfirekey_t key);
static void xor (const uint8_t *ivect, uint8_t *data, const size_t len) {
for (size_t i = 0; i < len; i++) {
data[i] ^= ivect[i];
}
}
void cmac_generate_subkeys ( desfirekey_t key) {
int kbs = key_block_size (key);
const uint8_t R = (kbs == 8) ? 0x1B : 0x87;
uint8_t l[kbs];
memset (l, 0, kbs);
uint8_t ivect[kbs];
memset (ivect, 0, kbs);
mifare_cypher_blocks_chained (NULL, key, ivect, l, kbs, MCD_RECEIVE, MCO_ENCYPHER);
bool xor = false;
// Used to compute CMAC on complete blocks
memcpy (key->cmac_sk1, l, kbs);
xor = l[0] & 0x80;
lsl (key->cmac_sk1, kbs);
if (xor)
key->cmac_sk1[kbs-1] ^= R;
// Used to compute CMAC on the last block if non-complete
memcpy (key->cmac_sk2, key->cmac_sk1, kbs);
xor = key->cmac_sk1[0] & 0x80;
lsl (key->cmac_sk2, kbs);
if (xor)
key->cmac_sk2[kbs-1] ^= R;
}
void cmac (const desfirekey_t key, uint8_t *ivect, const uint8_t *data, size_t len, uint8_t *cmac) {
int kbs = key_block_size (key);
uint8_t *buffer = malloc (padded_data_length (len, kbs));
memcpy (buffer, data, len);
if ((!len) || (len % kbs)) {
buffer[len++] = 0x80;
while (len % kbs) {
buffer[len++] = 0x00;
}
xor (key->cmac_sk2, buffer + len - kbs, kbs);
} else {
xor (key->cmac_sk1, buffer + len - kbs, kbs);
}
mifare_cypher_blocks_chained (NULL, key, ivect, buffer, len, MCD_SEND, MCO_ENCYPHER);
memcpy (cmac, ivect, kbs);
}
size_t key_block_size (const desfirekey_t key) {
size_t block_size = 8;
switch (key->type) {
case T_DES:
case T_3DES:
case T_3K3DES:
block_size = 8;
break;
case T_AES:
block_size = 16;
break;
}
return block_size;
}
/*
* Size of MACing produced with the key.
*/
static size_t key_macing_length (const desfirekey_t key) {
size_t mac_length = MAC_LENGTH;
switch (key->type) {
case T_DES:
case T_3DES:
mac_length = MAC_LENGTH;
break;
case T_3K3DES:
case T_AES:
mac_length = CMAC_LENGTH;
break;
}
return mac_length;
}
/*
* Size required to store nbytes of data in a buffer of size n*block_size.
*/
size_t padded_data_length (const size_t nbytes, const size_t block_size) {
if ((!nbytes) || (nbytes % block_size))
return ((nbytes / block_size) + 1) * block_size;
else
return nbytes;
}
/*
* Buffer size required to MAC nbytes of data
*/
size_t maced_data_length (const desfirekey_t key, const size_t nbytes) {
return nbytes + key_macing_length (key);
}
/*
* Buffer size required to encipher nbytes of data and a two bytes CRC.
*/
size_t enciphered_data_length (const desfiretag_t tag, const size_t nbytes, int communication_settings) {
size_t crc_length = 0;
if (!(communication_settings & NO_CRC)) {
switch (DESFIRE(tag)->authentication_scheme) {
case AS_LEGACY:
crc_length = 2;
break;
case AS_NEW:
crc_length = 4;
break;
}
}
size_t block_size = DESFIRE(tag)->session_key ? key_block_size (DESFIRE(tag)->session_key) : 1;
return padded_data_length (nbytes + crc_length, block_size);
}
void* mifare_cryto_preprocess_data (desfiretag_t tag, void *data, size_t *nbytes, off_t offset, int communication_settings) {
uint8_t *res = data;
uint8_t mac[4];
size_t edl;
bool append_mac = true;
desfirekey_t key = DESFIRE(tag)->session_key;
if (!key)
return data;
switch (communication_settings & MDCM_MASK) {
case MDCM_PLAIN:
if (AS_LEGACY == DESFIRE(tag)->authentication_scheme)
break;
/*
* When using new authentication methods, PLAIN data transmission from
* the PICC to the PCD are CMACed, so we have to maintain the
* cryptographic initialisation vector up-to-date to check data
* integrity later.
*
* The only difference with CMACed data transmission is that the CMAC
* is not apended to the data send by the PCD to the PICC.
*/
append_mac = false;
/* pass through */
case MDCM_MACED:
switch (DESFIRE(tag)->authentication_scheme) {
case AS_LEGACY:
if (!(communication_settings & MAC_COMMAND))
break;
/* pass through */
edl = padded_data_length (*nbytes - offset, key_block_size (DESFIRE(tag)->session_key)) + offset;
// Fill in the crypto buffer with data ...
memcpy (res, data, *nbytes);
// ... and 0 padding
memset (res + *nbytes, 0, edl - *nbytes);
mifare_cypher_blocks_chained (tag, NULL, NULL, res + offset, edl - offset, MCD_SEND, MCO_ENCYPHER);
memcpy (mac, res + edl - 8, 4);
// Copy again provided data (was overwritten by mifare_cypher_blocks_chained)
memcpy (res, data, *nbytes);
if (!(communication_settings & MAC_COMMAND))
break;
// Append MAC
size_t bla = maced_data_length (DESFIRE(tag)->session_key, *nbytes - offset) + offset;
bla++;
memcpy (res + *nbytes, mac, 4);
*nbytes += 4;
break;
case AS_NEW:
if (!(communication_settings & CMAC_COMMAND))
break;
cmac (key, DESFIRE (tag)->ivect, res, *nbytes, DESFIRE (tag)->cmac);
if (append_mac) {
maced_data_length (key, *nbytes);
memcpy (res, data, *nbytes);
memcpy (res + *nbytes, DESFIRE (tag)->cmac, CMAC_LENGTH);
*nbytes += CMAC_LENGTH;
}
break;
}
break;
case MDCM_ENCIPHERED:
/* |<-------------- data -------------->|
* |<--- offset -->| |
* +---------------+--------------------+-----+---------+
* | CMD + HEADERS | DATA TO BE SECURED | CRC | PADDING |
* +---------------+--------------------+-----+---------+ ----------------
* | |<~~~~v~~~~~~~~~~~~~>| ^ | | (DES / 3DES)
* | | `---- crc16() ----' | |
* | | | ^ | | ----- *or* -----
* |<~~~~~~~~~~~~~~~~~~~~v~~~~~~~~~~~~~>| ^ | | (3K3DES / AES)
* | `---- crc32() ----' | |
* | | ---- *then* ----
* |<---------------------------------->|
* encypher()/decypher()
*/
if (!(communication_settings & ENC_COMMAND))
break;
edl = enciphered_data_length (tag, *nbytes - offset, communication_settings) + offset;
// Fill in the crypto buffer with data ...
memcpy (res, data, *nbytes);
if (!(communication_settings & NO_CRC)) {
// ... CRC ...
switch (DESFIRE (tag)->authentication_scheme) {
case AS_LEGACY:
AppendCrc14443a(res + offset, *nbytes - offset);
*nbytes += 2;
break;
case AS_NEW:
crc32_append (res, *nbytes);
*nbytes += 4;
break;
}
}
// ... and padding
memset (res + *nbytes, 0, edl - *nbytes);
*nbytes = edl;
mifare_cypher_blocks_chained (tag, NULL, NULL, res + offset, *nbytes - offset, MCD_SEND, (AS_NEW == DESFIRE(tag)->authentication_scheme) ? MCO_ENCYPHER : MCO_DECYPHER);
break;
default:
*nbytes = -1;
res = NULL;
break;
}
return res;
}
void* mifare_cryto_postprocess_data (desfiretag_t tag, void *data, ssize_t *nbytes, int communication_settings)
{
void *res = data;
size_t edl;
void *edata = NULL;
uint8_t first_cmac_byte = 0x00;
desfirekey_t key = DESFIRE(tag)->session_key;
if (!key)
return data;
// Return directly if we just have a status code.
if (1 == *nbytes)
return res;
switch (communication_settings & MDCM_MASK) {
case MDCM_PLAIN:
if (AS_LEGACY == DESFIRE(tag)->authentication_scheme)
break;
/* pass through */
case MDCM_MACED:
switch (DESFIRE (tag)->authentication_scheme) {
case AS_LEGACY:
if (communication_settings & MAC_VERIFY) {
*nbytes -= key_macing_length (key);
if (*nbytes <= 0) {
*nbytes = -1;
res = NULL;
#ifdef WITH_DEBUG
Dbprintf ("No room for MAC!");
#endif
break;
}
edl = enciphered_data_length (tag, *nbytes - 1, communication_settings);
edata = malloc (edl);
memcpy (edata, data, *nbytes - 1);
memset ((uint8_t *)edata + *nbytes - 1, 0, edl - *nbytes + 1);
mifare_cypher_blocks_chained (tag, NULL, NULL, edata, edl, MCD_SEND, MCO_ENCYPHER);
if (0 != memcmp ((uint8_t *)data + *nbytes - 1, (uint8_t *)edata + edl - 8, 4)) {
#ifdef WITH_DEBUG
Dbprintf ("MACing not verified");
hexdump ((uint8_t *)data + *nbytes - 1, key_macing_length (key), "Expect ", 0);
hexdump ((uint8_t *)edata + edl - 8, key_macing_length (key), "Actual ", 0);
#endif
DESFIRE (tag)->last_pcd_error = CRYPTO_ERROR;
*nbytes = -1;
res = NULL;
}
}
break;
case AS_NEW:
if (!(communication_settings & CMAC_COMMAND))
break;
if (communication_settings & CMAC_VERIFY) {
if (*nbytes < 9) {
*nbytes = -1;
res = NULL;
break;
}
first_cmac_byte = ((uint8_t *)data)[*nbytes - 9];
((uint8_t *)data)[*nbytes - 9] = ((uint8_t *)data)[*nbytes-1];
}
int n = (communication_settings & CMAC_VERIFY) ? 8 : 0;
cmac (key, DESFIRE (tag)->ivect, ((uint8_t *)data), *nbytes - n, DESFIRE (tag)->cmac);
if (communication_settings & CMAC_VERIFY) {
((uint8_t *)data)[*nbytes - 9] = first_cmac_byte;
if (0 != memcmp (DESFIRE (tag)->cmac, (uint8_t *)data + *nbytes - 9, 8)) {
#ifdef WITH_DEBUG
Dbprintf ("CMAC NOT verified :-(");
hexdump ((uint8_t *)data + *nbytes - 9, 8, "Expect ", 0);
hexdump (DESFIRE (tag)->cmac, 8, "Actual ", 0);
#endif
DESFIRE (tag)->last_pcd_error = CRYPTO_ERROR;
*nbytes = -1;
res = NULL;
} else {
*nbytes -= 8;
}
}
break;
}
free (edata);
break;
case MDCM_ENCIPHERED:
(*nbytes)--;
bool verified = false;
int crc_pos = 0x00;
int end_crc_pos = 0x00;
uint8_t x;
/*
* AS_LEGACY:
* ,-----------------+-------------------------------+--------+
* \ BLOCK n-1 | BLOCK n | STATUS |
* / PAYLOAD | CRC0 | CRC1 | 0x80? | 0x000000000000 | 0x9100 |
* `-----------------+-------------------------------+--------+
*
* <------------ DATA ------------>
* FRAME = PAYLOAD + CRC(PAYLOAD) + PADDING
*
* AS_NEW:
* ,-------------------------------+-----------------------------------------------+--------+
* \ BLOCK n-1 | BLOCK n | STATUS |
* / PAYLOAD | CRC0 | CRC1 | CRC2 | CRC3 | 0x80? | 0x0000000000000000000000000000 | 0x9100 |
* `-------------------------------+-----------------------------------------------+--------+
* <----------------------------------- DATA ------------------------------------->|
*
* <----------------- DATA ---------------->
* FRAME = PAYLOAD + CRC(PAYLOAD + STATUS) + PADDING + STATUS
* `------------------'
*/
mifare_cypher_blocks_chained (tag, NULL, NULL, res, *nbytes, MCD_RECEIVE, MCO_DECYPHER);
/*
* Look for the CRC and ensure it is followed by NULL padding. We
* can't start by the end because the CRC is supposed to be 0 when
* verified, and accumulating 0's in it should not change it.
*/
switch (DESFIRE (tag)->authentication_scheme) {
case AS_LEGACY:
crc_pos = *nbytes - 8 - 1; // The CRC can be over two blocks
if (crc_pos < 0) {
/* Single block */
crc_pos = 0;
}
break;
case AS_NEW:
/* Move status between payload and CRC */
res = DESFIRE (tag)->crypto_buffer;
memcpy (res, data, *nbytes);
crc_pos = (*nbytes) - 16 - 3;
if (crc_pos < 0) {
/* Single block */
crc_pos = 0;
}
memcpy ((uint8_t *)res + crc_pos + 1, (uint8_t *)res + crc_pos, *nbytes - crc_pos);
((uint8_t *)res)[crc_pos] = 0x00;
crc_pos++;
*nbytes += 1;
break;
}
do {
uint16_t crc16 =0x00;
uint32_t crc;
switch (DESFIRE (tag)->authentication_scheme) {
case AS_LEGACY:
end_crc_pos = crc_pos + 2;
AppendCrc14443a (res, end_crc_pos);
//
crc = crc16;
break;
case AS_NEW:
end_crc_pos = crc_pos + 4;
crc32 (res, end_crc_pos, (uint8_t *)&crc);
break;
}
if (!crc) {
verified = true;
for (int n = end_crc_pos; n < *nbytes - 1; n++) {
uint8_t byte = ((uint8_t *)res)[n];
if (!( (0x00 == byte) || ((0x80 == byte) && (n == end_crc_pos)) ))
verified = false;
}
}
if (verified) {
*nbytes = crc_pos;
switch (DESFIRE (tag)->authentication_scheme) {
case AS_LEGACY:
((uint8_t *)data)[(*nbytes)++] = 0x00;
break;
case AS_NEW:
/* The status byte was already before the CRC */
break;
}
} else {
switch (DESFIRE (tag)->authentication_scheme) {
case AS_LEGACY:
break;
case AS_NEW:
x = ((uint8_t *)res)[crc_pos - 1];
((uint8_t *)res)[crc_pos - 1] = ((uint8_t *)res)[crc_pos];
((uint8_t *)res)[crc_pos] = x;
break;
}
crc_pos++;
}
} while (!verified && (end_crc_pos < *nbytes));
if (!verified) {
#ifdef WITH_DEBUG
/* FIXME In some configurations, the file is transmitted PLAIN */
Dbprintf("CRC not verified in decyphered stream");
#endif
DESFIRE (tag)->last_pcd_error = CRYPTO_ERROR;
*nbytes = -1;
res = NULL;
}
break;
default:
Dbprintf("Unknown communication settings");
*nbytes = -1;
res = NULL;
break;
}
return res;
}
void mifare_cypher_single_block (desfirekey_t key, uint8_t *data, uint8_t *ivect, MifareCryptoDirection direction, MifareCryptoOperation operation, size_t block_size)
{
uint8_t ovect[MAX_CRYPTO_BLOCK_SIZE];
if (direction == MCD_SEND) {
xor (ivect, data, block_size);
} else {
memcpy (ovect, data, block_size);
}
uint8_t edata[MAX_CRYPTO_BLOCK_SIZE];
switch (key->type) {
case T_DES:
switch (operation) {
case MCO_ENCYPHER:
//DES_ecb_encrypt ((DES_cblock *) data, (DES_cblock *) edata, &(key->ks1), DES_ENCRYPT);
des_enc(edata, data, key->data);
break;
case MCO_DECYPHER:
//DES_ecb_encrypt ((DES_cblock *) data, (DES_cblock *) edata, &(key->ks1), DES_DECRYPT);
des_dec(edata, data, key->data);
break;
}
break;
case T_3DES:
switch (operation) {
case MCO_ENCYPHER:
// DES_ecb_encrypt ((DES_cblock *) data, (DES_cblock *) edata, &(key->ks1), DES_ENCRYPT);
// DES_ecb_encrypt ((DES_cblock *) edata, (DES_cblock *) data, &(key->ks2), DES_DECRYPT);
// DES_ecb_encrypt ((DES_cblock *) data, (DES_cblock *) edata, &(key->ks1), DES_ENCRYPT);
tdes_enc(edata,data, key->data);
break;
case MCO_DECYPHER:
// DES_ecb_encrypt ((DES_cblock *) data, (DES_cblock *) edata, &(key->ks1), DES_DECRYPT);
// DES_ecb_encrypt ((DES_cblock *) edata, (DES_cblock *) data, &(key->ks2), DES_ENCRYPT);
// DES_ecb_encrypt ((DES_cblock *) data, (DES_cblock *) edata, &(key->ks1), DES_DECRYPT);
tdes_dec(data, edata, key->data);
break;
}
break;
case T_3K3DES:
switch (operation) {
case MCO_ENCYPHER:
tdes_enc(edata,data, key->data);
// DES_ecb_encrypt ((DES_cblock *) data, (DES_cblock *) edata, &(key->ks1), DES_ENCRYPT);
// DES_ecb_encrypt ((DES_cblock *) edata, (DES_cblock *) data, &(key->ks2), DES_DECRYPT);
// DES_ecb_encrypt ((DES_cblock *) data, (DES_cblock *) edata, &(key->ks3), DES_ENCRYPT);
break;
case MCO_DECYPHER:
tdes_dec(data, edata, key->data);
// DES_ecb_encrypt ((DES_cblock *) data, (DES_cblock *) edata, &(key->ks3), DES_DECRYPT);
// DES_ecb_encrypt ((DES_cblock *) edata, (DES_cblock *) data, &(key->ks2), DES_ENCRYPT);
// DES_ecb_encrypt ((DES_cblock *) data, (DES_cblock *) edata, &(key->ks1), DES_DECRYPT);
break;
}
break;
case T_AES:
switch (operation)
{
case MCO_ENCYPHER:
{
AesCtx ctx;
AesCtxIni(&ctx, ivect, key->data, KEY128,CBC);
AesEncrypt(&ctx, data, edata, sizeof(data) );
break;
}
case MCO_DECYPHER:
{
AesCtx ctx;
AesCtxIni(&ctx, ivect, key->data, KEY128,CBC);
AesDecrypt(&ctx, edata, data, sizeof(edata));
break;
}
}
break;
}
memcpy (data, edata, block_size);
if (direction == MCD_SEND) {
memcpy (ivect, data, block_size);
} else {
xor (ivect, data, block_size);
memcpy (ivect, ovect, block_size);
}
}
/*
* This function performs all CBC cyphering / deciphering.
*
* The tag argument may be NULL, in which case both key and ivect shall be set.
* When using the tag session_key and ivect for processing data, these
* arguments should be set to NULL.
*
* Because the tag may contain additional data, one may need to call this
* function with tag, key and ivect defined.
*/
void mifare_cypher_blocks_chained (desfiretag_t tag, desfirekey_t key, uint8_t *ivect, uint8_t *data, size_t data_size, MifareCryptoDirection direction, MifareCryptoOperation operation) {
size_t block_size;
if (tag) {
if (!key)
key = DESFIRE (tag)->session_key;
if (!ivect)
ivect = DESFIRE (tag)->ivect;
switch (DESFIRE (tag)->authentication_scheme) {
case AS_LEGACY:
memset (ivect, 0, MAX_CRYPTO_BLOCK_SIZE);
break;
case AS_NEW:
break;
}
}
block_size = key_block_size (key);
size_t offset = 0;
while (offset < data_size) {
mifare_cypher_single_block (key, data + offset, ivect, direction, operation, block_size);
offset += block_size;
}
}

View file

@ -1,14 +0,0 @@
#ifndef __DESFIRE_CRYPTO_H
#define __DESFIRE_CRYPTO_H
#include <string.h>
#include <strings.h>
#include <stdarg.h>
#include "printf.h"
#include "iso14443a.h"
#include "../common/desfire.h"
#include "des.h"
//#include "aes.h"
#endif

View file

@ -1,155 +0,0 @@
/*-
* Copyright (C) 2010, Romain Tartiere.
*
* This program is free software: you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published by the
* Free Software Foundation, either version 3 of the License, or (at your
* option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>
*
* $Id$
*/
#include <stdlib.h>
#include "desfire_key.h"
static inline void update_key_schedules (desfirekey_t key);
static inline void update_key_schedules (desfirekey_t key) {
// DES_set_key ((DES_cblock *)key->data, &(key->ks1));
// DES_set_key ((DES_cblock *)(key->data + 8), &(key->ks2));
// if (T_3K3DES == key->type) {
// DES_set_key ((DES_cblock *)(key->data + 16), &(key->ks3));
// }
}
void Desfire_des_key_new (const uint8_t value[8], desfirekey_t key) {
uint8_t data[8];
memcpy (data, value, 8);
for (int n=0; n < 8; n++)
data[n] &= 0xfe;
Desfire_des_key_new_with_version (data, key);
}
void Desfire_des_key_new_with_version (const uint8_t value[8], desfirekey_t key) {
if ( key != NULL) {
key->type = T_DES;
memcpy (key->data, value, 8);
memcpy (key->data+8, value, 8);
update_key_schedules (key);
}
}
void Desfire_3des_key_new (const uint8_t value[16], desfirekey_t key) {
uint8_t data[16];
memcpy (data, value, 16);
for (int n=0; n < 8; n++)
data[n] &= 0xfe;
for (int n=8; n < 16; n++)
data[n] |= 0x01;
Desfire_3des_key_new_with_version (data, key);
}
void Desfire_3des_key_new_with_version (const uint8_t value[16], desfirekey_t key) {
if ( key != NULL ){
key->type = T_3DES;
memcpy (key->data, value, 16);
update_key_schedules (key);
}
}
void Desfire_3k3des_key_new (const uint8_t value[24], desfirekey_t key) {
uint8_t data[24];
memcpy (data, value, 24);
for (int n=0; n < 8; n++)
data[n] &= 0xfe;
Desfire_3k3des_key_new_with_version (data, key);
}
void Desfire_3k3des_key_new_with_version (const uint8_t value[24], desfirekey_t key) {
if ( key != NULL){
key->type = T_3K3DES;
memcpy (key->data, value, 24);
update_key_schedules (key);
}
}
void Desfire_aes_key_new (const uint8_t value[16], desfirekey_t key) {
Desfire_aes_key_new_with_version (value, 0, key);
}
void Desfire_aes_key_new_with_version (const uint8_t value[16], uint8_t version, desfirekey_t key) {
if (key != NULL) {
memcpy (key->data, value, 16);
key->type = T_AES;
key->aes_version = version;
}
}
uint8_t Desfire_key_get_version (desfirekey_t key) {
uint8_t version = 0;
for (int n = 0; n < 8; n++) {
version |= ((key->data[n] & 1) << (7 - n));
}
return version;
}
void Desfire_key_set_version (desfirekey_t key, uint8_t version)
{
for (int n = 0; n < 8; n++) {
uint8_t version_bit = ((version & (1 << (7-n))) >> (7-n));
key->data[n] &= 0xfe;
key->data[n] |= version_bit;
if (key->type == T_DES) {
key->data[n+8] = key->data[n];
} else {
// Write ~version to avoid turning a 3DES key into a DES key
key->data[n+8] &= 0xfe;
key->data[n+8] |= ~version_bit;
}
}
}
void Desfire_session_key_new (const uint8_t rnda[], const uint8_t rndb[], desfirekey_t authkey, desfirekey_t key) {
uint8_t buffer[24];
switch (authkey->type) {
case T_DES:
memcpy (buffer, rnda, 4);
memcpy (buffer+4, rndb, 4);
Desfire_des_key_new_with_version (buffer, key);
break;
case T_3DES:
memcpy (buffer, rnda, 4);
memcpy (buffer+4, rndb, 4);
memcpy (buffer+8, rnda+4, 4);
memcpy (buffer+12, rndb+4, 4);
Desfire_3des_key_new_with_version (buffer, key);
break;
case T_3K3DES:
memcpy (buffer, rnda, 4);
memcpy (buffer+4, rndb, 4);
memcpy (buffer+8, rnda+6, 4);
memcpy (buffer+12, rndb+6, 4);
memcpy (buffer+16, rnda+12, 4);
memcpy (buffer+20, rndb+12, 4);
Desfire_3k3des_key_new (buffer, key);
break;
case T_AES:
memcpy (buffer, rnda, 4);
memcpy (buffer+4, rndb, 4);
memcpy (buffer+8, rnda+12, 4);
memcpy (buffer+12, rndb+12, 4);
Desfire_aes_key_new (buffer, key);
break;
}
}

View file

@ -1,17 +0,0 @@
#ifndef __DESFIRE_KEY_INCLUDED
#define __DESFIRE_KEY_INCLUDED
#include "iso14443a.h"
// desfire_key.h
void Desfire_des_key_new (const uint8_t value[8], desfirekey_t key);
void Desfire_3des_key_new (const uint8_t value[16], desfirekey_t key);
void Desfire_des_key_new_with_version (const uint8_t value[8], desfirekey_t key);
void Desfire_3des_key_new_with_version (const uint8_t value[16], desfirekey_t key);
void Desfire_3k3des_key_new (const uint8_t value[24], desfirekey_t key);
void Desfire_3k3des_key_new_with_version (const uint8_t value[24], desfirekey_t key);
void Desfire_aes_key_new (const uint8_t value[16], desfirekey_t key);
void Desfire_aes_key_new_with_version (const uint8_t value[16], uint8_t version,desfirekey_t key);
uint8_t Desfire_key_get_version (desfirekey_t key);
void Desfire_key_set_version (desfirekey_t key, uint8_t version);
void Desfire_session_key_new (const uint8_t rnda[], const uint8_t rndb[], desfirekey_t authkey, desfirekey_t key);
#endif

View file

@ -13,7 +13,7 @@
#include "iso14443a.h" #include "iso14443a.h"
#include "epa.h" #include "epa.h"
#include "../common/cmd.h" #include "cmd.h"
// Protocol and Parameter Selection Request // Protocol and Parameter Selection Request
// use regular (1x) speed in both directions // use regular (1x) speed in both directions
@ -224,7 +224,7 @@ static void EPA_PACE_Collect_Nonce_Abort(uint8_t step, int func_return)
EPA_Finish(); EPA_Finish();
// send the USB packet // send the USB packet
cmd_send(CMD_ACK,step,func_return,0,0,0); cmd_send(CMD_ACK,step,func_return,0,0,0);
} }
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
@ -254,13 +254,11 @@ void EPA_PACE_Collect_Nonce(UsbCommand *c)
func_return = EPA_Setup(); func_return = EPA_Setup();
if (func_return != 0) { if (func_return != 0) {
EPA_PACE_Collect_Nonce_Abort(1, func_return); EPA_PACE_Collect_Nonce_Abort(1, func_return);
Dbprintf("epa: setup fucked up! %d", func_return);
return; return;
} }
// increase the timeout (at least some cards really do need this!) // increase the timeout (at least some cards really do need this!)
iso14a_set_timeout(0x0002FFFF); iso14a_set_timeout(0x0002FFFF);
Dbprintf("epa: Epic!");
// read the CardAccess file // read the CardAccess file
// this array will hold the CardAccess file // this array will hold the CardAccess file
@ -268,13 +266,10 @@ void EPA_PACE_Collect_Nonce(UsbCommand *c)
int card_access_length = EPA_Read_CardAccess(card_access, 256); int card_access_length = EPA_Read_CardAccess(card_access, 256);
// the response has to be at least this big to hold the OID // the response has to be at least this big to hold the OID
if (card_access_length < 18) { if (card_access_length < 18) {
Dbprintf("epa: Too small!");
EPA_PACE_Collect_Nonce_Abort(2, card_access_length); EPA_PACE_Collect_Nonce_Abort(2, card_access_length);
return; return;
} }
Dbprintf("epa: foo!");
// this will hold the PACE info of the card // this will hold the PACE info of the card
pace_version_info_t pace_version_info; pace_version_info_t pace_version_info;
// search for the PACE OID // search for the PACE OID
@ -286,8 +281,6 @@ void EPA_PACE_Collect_Nonce(UsbCommand *c)
return; return;
} }
Dbprintf("epa: bar!");
// initiate the PACE protocol // initiate the PACE protocol
// use the CAN for the password since that doesn't change // use the CAN for the password since that doesn't change
func_return = EPA_PACE_MSE_Set_AT(pace_version_info, 2); func_return = EPA_PACE_MSE_Set_AT(pace_version_info, 2);
@ -309,7 +302,7 @@ void EPA_PACE_Collect_Nonce(UsbCommand *c)
// save received information // save received information
// ack->arg[1] = func_return; // ack->arg[1] = func_return;
// memcpy(ack->d.asBytes, nonce, func_return); // memcpy(ack->d.asBytes, nonce, func_return);
cmd_send(CMD_ACK,0,func_return,0,nonce,func_return); cmd_send(CMD_ACK,0,func_return,0,nonce,func_return);
} }
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------

View file

@ -9,8 +9,7 @@
// Routines to load the FPGA image, and then to configure the FPGA's major // Routines to load the FPGA image, and then to configure the FPGA's major
// mode once it is configured. // mode once it is configured.
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
#include "proxmark3.h"
#include "../include/proxmark3.h"
#include "apps.h" #include "apps.h"
#include "util.h" #include "util.h"
#include "string.h" #include "string.h"

View file

@ -16,10 +16,10 @@
// (c) 2012 Roel Verdult // (c) 2012 Roel Verdult
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
#include "../include/proxmark3.h" #include "proxmark3.h"
#include "apps.h" #include "apps.h"
#include "util.h" #include "util.h"
#include "../include/hitag2.h" #include "hitag2.h"
#include "string.h" #include "string.h"
static bool bQuiet; static bool bQuiet;
@ -744,7 +744,7 @@ void SnoopHitag(uint32_t type) {
// Set up eavesdropping mode, frequency divisor which will drive the FPGA // Set up eavesdropping mode, frequency divisor which will drive the FPGA
// and analog mux selection. // and analog mux selection.
FpgaDownloadAndGo(FPGA_BITSTREAM_LF); FpgaDownloadAndGo(FPGA_BITSTREAM_LF);
FpgaWriteConfWord(FPGA_MAJOR_MODE_LF_EDGE_DETECT | FPGA_LF_EDGE_DETECT_TOGGLE_MODE); FpgaWriteConfWord(FPGA_MAJOR_MODE_LF_EDGE_DETECT);
FpgaSendCommand(FPGA_CMD_SET_DIVISOR, 95); //125Khz FpgaSendCommand(FPGA_CMD_SET_DIVISOR, 95); //125Khz
SetAdcMuxFor(GPIO_MUXSEL_LOPKD); SetAdcMuxFor(GPIO_MUXSEL_LOPKD);
RELAY_OFF(); RELAY_OFF();
@ -968,7 +968,7 @@ void SimulateHitagTag(bool tag_mem_supplied, byte_t* data) {
// Set up simulator mode, frequency divisor which will drive the FPGA // Set up simulator mode, frequency divisor which will drive the FPGA
// and analog mux selection. // and analog mux selection.
FpgaDownloadAndGo(FPGA_BITSTREAM_LF); FpgaDownloadAndGo(FPGA_BITSTREAM_LF);
FpgaWriteConfWord(FPGA_MAJOR_MODE_LF_EDGE_DETECT | FPGA_LF_EDGE_DETECT_READER_FIELD); FpgaWriteConfWord(FPGA_MAJOR_MODE_LF_EDGE_DETECT);
FpgaSendCommand(FPGA_CMD_SET_DIVISOR, 95); //125Khz FpgaSendCommand(FPGA_CMD_SET_DIVISOR, 95); //125Khz
SetAdcMuxFor(GPIO_MUXSEL_LOPKD); SetAdcMuxFor(GPIO_MUXSEL_LOPKD);
RELAY_OFF(); RELAY_OFF();
@ -987,7 +987,7 @@ void SimulateHitagTag(bool tag_mem_supplied, byte_t* data) {
AT91C_BASE_PMC->PMC_PCER = (1 << AT91C_ID_TC1); AT91C_BASE_PMC->PMC_PCER = (1 << AT91C_ID_TC1);
AT91C_BASE_PIOA->PIO_BSR = GPIO_SSC_FRAME; AT91C_BASE_PIOA->PIO_BSR = GPIO_SSC_FRAME;
// Disable timer during configuration // Disable timer during configuration
AT91C_BASE_TC1->TC_CCR = AT91C_TC_CLKDIS; AT91C_BASE_TC1->TC_CCR = AT91C_TC_CLKDIS;
// Capture mode, default timer source = MCK/2 (TIMER_CLOCK1), TIOA is external trigger, // Capture mode, default timer source = MCK/2 (TIMER_CLOCK1), TIOA is external trigger,
@ -1140,7 +1140,7 @@ void ReaderHitag(hitag_function htf, hitag_data* htd) {
case RHT2F_PASSWORD: { case RHT2F_PASSWORD: {
Dbprintf("List identifier in password mode"); Dbprintf("List identifier in password mode");
memcpy(password,htd->pwd.password,4); memcpy(password,htd->pwd.password,4);
blocknr = 0; blocknr = 0;
bQuitTraceFull = false; bQuitTraceFull = false;
bQuiet = false; bQuiet = false;
bPwd = false; bPwd = false;
@ -1158,7 +1158,7 @@ void ReaderHitag(hitag_function htf, hitag_data* htd) {
case RHT2F_CRYPTO: { case RHT2F_CRYPTO: {
DbpString("Authenticating using key:"); DbpString("Authenticating using key:");
memcpy(key,htd->crypto.key,6); // 4 or 6 ?? memcpy(key,htd->crypto.key,4); //HACK; 4 or 6?? I read both in the code.
Dbhexdump(6,key,false); Dbhexdump(6,key,false);
blocknr = 0; blocknr = 0;
bQuiet = false; bQuiet = false;

View file

@ -36,7 +36,7 @@
// //
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
#include "../include/proxmark3.h" #include "proxmark3.h"
#include "apps.h" #include "apps.h"
#include "util.h" #include "util.h"
#include "string.h" #include "string.h"
@ -45,11 +45,9 @@
// Needed for CRC in emulation mode; // Needed for CRC in emulation mode;
// same construction as in ISO 14443; // same construction as in ISO 14443;
// different initial value (CRC_ICLASS) // different initial value (CRC_ICLASS)
#include "../common/iso14443crc.h" #include "iso14443crc.h"
#include "../common/iso15693tools.h"
#include "iso15693tools.h" #include "iso15693tools.h"
static int timeout = 4096; static int timeout = 4096;
@ -353,7 +351,7 @@ static struct {
SUB_SECOND_HALF, SUB_SECOND_HALF,
SUB_BOTH SUB_BOTH
} sub; } sub;
uint8_t *output; uint8_t *output;
} Demod; } Demod;
static RAMFUNC int ManchesterDecoding(int v) static RAMFUNC int ManchesterDecoding(int v)
@ -744,7 +742,7 @@ void RAMFUNC SnoopIClass(void)
//if(!LogTrace(Uart.output,Uart.byteCnt, rsamples, Uart.parityBits,TRUE)) break; //if(!LogTrace(Uart.output,Uart.byteCnt, rsamples, Uart.parityBits,TRUE)) break;
//if(!LogTrace(NULL, 0, Uart.endTime*16 - DELAY_READER_AIR2ARM_AS_SNIFFER, 0, TRUE)) break; //if(!LogTrace(NULL, 0, Uart.endTime*16 - DELAY_READER_AIR2ARM_AS_SNIFFER, 0, TRUE)) break;
if(tracing) { if(tracing) {
uint8_t parity[MAX_PARITY_SIZE]; uint8_t parity[MAX_PARITY_SIZE];
GetParity(Uart.output, Uart.byteCnt, parity); GetParity(Uart.output, Uart.byteCnt, parity);
LogTrace(Uart.output,Uart.byteCnt, (GetCountSspClk()-time_0) << 4, (GetCountSspClk()-time_0) << 4, parity, TRUE); LogTrace(Uart.output,Uart.byteCnt, (GetCountSspClk()-time_0) << 4, (GetCountSspClk()-time_0) << 4, parity, TRUE);
@ -768,7 +766,7 @@ void RAMFUNC SnoopIClass(void)
rsamples = samples - Demod.samples; rsamples = samples - Demod.samples;
LED_B_ON(); LED_B_ON();
if(tracing) { if(tracing) {
uint8_t parity[MAX_PARITY_SIZE]; uint8_t parity[MAX_PARITY_SIZE];
GetParity(Demod.output, Demod.len, parity); GetParity(Demod.output, Demod.len, parity);
LogTrace(Demod.output, Demod.len, (GetCountSspClk()-time_0) << 4, (GetCountSspClk()-time_0) << 4, parity, FALSE); LogTrace(Demod.output, Demod.len, (GetCountSspClk()-time_0) << 4, (GetCountSspClk()-time_0) << 4, parity, FALSE);
@ -1268,17 +1266,17 @@ static void TransmitIClassCommand(const uint8_t *cmd, int len, int *samples, int
{ {
if(*wait < 10) *wait = 10; if(*wait < 10) *wait = 10;
for(c = 0; c < *wait;) { for(c = 0; c < *wait;) {
if(AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_TXRDY)) { if(AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_TXRDY)) {
AT91C_BASE_SSC->SSC_THR = 0x00; // For exact timing! AT91C_BASE_SSC->SSC_THR = 0x00; // For exact timing!
c++; c++;
} }
if(AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_RXRDY)) { if(AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_RXRDY)) {
volatile uint32_t r = AT91C_BASE_SSC->SSC_RHR; volatile uint32_t r = AT91C_BASE_SSC->SSC_RHR;
(void)r; (void)r;
} }
WDT_HIT(); WDT_HIT();
} }
} }
@ -1361,19 +1359,19 @@ void CodeIClassCommand(const uint8_t * cmd, int len)
void ReaderTransmitIClass(uint8_t* frame, int len) void ReaderTransmitIClass(uint8_t* frame, int len)
{ {
int wait = 0; int wait = 0;
int samples = 0; int samples = 0;
// This is tied to other size changes // This is tied to other size changes
CodeIClassCommand(frame,len); CodeIClassCommand(frame,len);
// Select the card // Select the card
TransmitIClassCommand(ToSend, ToSendMax, &samples, &wait); TransmitIClassCommand(ToSend, ToSendMax, &samples, &wait);
if(trigger) if(trigger)
LED_A_ON(); LED_A_ON();
// Store reader command in buffer // Store reader command in buffer
if (tracing) { if (tracing) {
uint8_t par[MAX_PARITY_SIZE]; uint8_t par[MAX_PARITY_SIZE];
GetParity(frame, len, par); GetParity(frame, len, par);
LogTrace(frame, len, rsamples, rsamples, par, TRUE); LogTrace(frame, len, rsamples, rsamples, par, TRUE);
@ -1408,7 +1406,7 @@ static int GetIClassAnswer(uint8_t *receivedResponse, int maxLen, int *samples,
for(;;) { for(;;) {
WDT_HIT(); WDT_HIT();
if(BUTTON_PRESS()) return FALSE; if(BUTTON_PRESS()) return FALSE;
if(AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_TXRDY)) { if(AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_TXRDY)) {
AT91C_BASE_SSC->SSC_THR = 0x00; // To make use of exact timing of next command from reader!! AT91C_BASE_SSC->SSC_THR = 0x00; // To make use of exact timing of next command from reader!!
@ -1433,10 +1431,10 @@ int ReaderReceiveIClass(uint8_t* receivedAnswer)
int samples = 0; int samples = 0;
if (!GetIClassAnswer(receivedAnswer,160,&samples,0)) return FALSE; if (!GetIClassAnswer(receivedAnswer,160,&samples,0)) return FALSE;
rsamples += samples; rsamples += samples;
if (tracing){ if (tracing) {
uint8_t parity[MAX_PARITY_SIZE]; uint8_t parity[MAX_PARITY_SIZE];
GetParity(receivedAnswer, Demod.len, parity); GetParity(receivedAnswer, Demod.len, parity);
LogTrace(receivedAnswer,Demod.len,rsamples,rsamples,parity,FALSE); LogTrace(receivedAnswer,Demod.len,rsamples,rsamples,parity,FALSE);
} }
if(samples == 0) return FALSE; if(samples == 0) return FALSE;
return Demod.len; return Demod.len;
@ -1554,7 +1552,7 @@ void ReaderIClass(uint8_t arg0) {
DbpString("Trace full"); DbpString("Trace full");
break; break;
} }
WDT_HIT(); WDT_HIT();
read_status = handshakeIclassTag(card_data); read_status = handshakeIclassTag(card_data);
@ -1562,24 +1560,24 @@ void ReaderIClass(uint8_t arg0) {
if(read_status == 1) datasize = 8; if(read_status == 1) datasize = 8;
if(read_status == 2) datasize = 16; if(read_status == 2) datasize = 16;
LED_B_ON(); LED_B_ON();
//Send back to client, but don't bother if we already sent this //Send back to client, but don't bother if we already sent this
if(memcmp(last_csn, card_data, 8) != 0) if(memcmp(last_csn, card_data, 8) != 0)
{ {
if(!get_cc || (get_cc && read_status == 2)) if(!get_cc || (get_cc && read_status == 2))
{ {
cmd_send(CMD_ACK,read_status,0,0,card_data,datasize); cmd_send(CMD_ACK,read_status,0,0,card_data,datasize);
if(abort_after_read) { if(abort_after_read) {
LED_A_OFF(); LED_A_OFF();
return; return;
} }
//Save that we already sent this.... //Save that we already sent this....
memcpy(last_csn, card_data, 8); memcpy(last_csn, card_data, 8);
} }
//If 'get_cc' was specified and we didn't get a CC, we'll just keep trying... //If 'get_cc' was specified and we didn't get a CC, we'll just keep trying...
} }
LED_B_OFF(); LED_B_OFF();
} }
cmd_send(CMD_ACK,0,0,0,card_data, 0); cmd_send(CMD_ACK,0,0,0,card_data, 0);
LED_A_OFF(); LED_A_OFF();
@ -1630,20 +1628,20 @@ void ReaderIClass_Replay(uint8_t arg0, uint8_t *MAC) {
uint8_t read_status = handshakeIclassTag(card_data); uint8_t read_status = handshakeIclassTag(card_data);
if(read_status < 2) continue; if(read_status < 2) continue;
//for now replay captured auth (as cc not updated) //for now replay captured auth (as cc not updated)
memcpy(check+5,MAC,4); memcpy(check+5,MAC,4);
if(sendCmdGetResponseWithRetries(check, sizeof(check),resp, 4, 5)) if(sendCmdGetResponseWithRetries(check, sizeof(check),resp, 4, 5))
{ {
Dbprintf("Error: Authentication Fail!"); Dbprintf("Error: Authentication Fail!");
continue; continue;
} }
//first get configuration block (block 1) //first get configuration block (block 1)
crc = block_crc_LUT[1]; crc = block_crc_LUT[1];
read[1]=1; read[1]=1;
read[2] = crc >> 8; read[2] = crc >> 8;
read[3] = crc & 0xff; read[3] = crc & 0xff;
if(sendCmdGetResponseWithRetries(read, sizeof(read),resp, 10, 10)) if(sendCmdGetResponseWithRetries(read, sizeof(read),resp, 10, 10))
{ {
@ -1651,30 +1649,30 @@ void ReaderIClass_Replay(uint8_t arg0, uint8_t *MAC) {
continue; continue;
} }
mem=resp[5]; mem=resp[5];
memory.k16= (mem & 0x80); memory.k16= (mem & 0x80);
memory.book= (mem & 0x20); memory.book= (mem & 0x20);
memory.k2= (mem & 0x8); memory.k2= (mem & 0x8);
memory.lockauth= (mem & 0x2); memory.lockauth= (mem & 0x2);
memory.keyaccess= (mem & 0x1); memory.keyaccess= (mem & 0x1);
cardsize = memory.k16 ? 255 : 32; cardsize = memory.k16 ? 255 : 32;
WDT_HIT(); WDT_HIT();
//then loop around remaining blocks //then loop around remaining blocks
for(int block=0; block < cardsize; block++){ for(int block=0; block < cardsize; block++){
read[1]= block; read[1]= block;
crc = block_crc_LUT[block]; crc = block_crc_LUT[block];
read[2] = crc >> 8; read[2] = crc >> 8;
read[3] = crc & 0xff; read[3] = crc & 0xff;
if(!sendCmdGetResponseWithRetries(read, sizeof(read), resp, 10, 10)) if(!sendCmdGetResponseWithRetries(read, sizeof(read), resp, 10, 10))
{ {
Dbprintf(" %02x: %02x %02x %02x %02x %02x %02x %02x %02x", Dbprintf(" %02x: %02x %02x %02x %02x %02x %02x %02x %02x",
block, resp[0], resp[1], resp[2], block, resp[0], resp[1], resp[2],
resp[3], resp[4], resp[5], resp[3], resp[4], resp[5],
resp[6], resp[7]); resp[6], resp[7]);
}else{ }else{
Dbprintf("Failed to dump block %d", block); Dbprintf("Failed to dump block %d", block);
@ -1702,10 +1700,10 @@ void IClass_iso14443A_write(uint8_t arg0, uint8_t blockNo, uint8_t *data, uint8_
uint16_t crc = 0; uint16_t crc = 0;
uint8_t* resp = (((uint8_t *)BigBuf) + RECV_RESP_OFFSET); uint8_t* resp = (((uint8_t *)BigBuf) + 3560);
// Reset trace buffer // Reset trace buffer
memset(trace, 0x44, RECV_CMD_OFFSET); memset(trace, 0x44, RECV_CMD_OFFSET);
traceLen = 0; traceLen = 0;
// Setup SSC // Setup SSC

View file

@ -10,12 +10,12 @@
// supported. // supported.
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
#include "../include/proxmark3.h" #include "proxmark3.h"
#include "apps.h" #include "apps.h"
#include "util.h" #include "util.h"
#include "string.h" #include "string.h"
#include "../common/iso14443crc.h" #include "iso14443crc.h"
//static void GetSamplesFor14443(int weTx, int n); //static void GetSamplesFor14443(int weTx, int n);

View file

@ -10,12 +10,13 @@
// Routines to support ISO 14443 type A. // Routines to support ISO 14443 type A.
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
#include "../include/proxmark3.h" #include "proxmark3.h"
#include "apps.h" #include "apps.h"
#include "util.h" #include "util.h"
#include "string.h" #include "string.h"
#include "../common/cmd.h" #include "cmd.h"
#include "../common/iso14443crc.h"
#include "iso14443crc.h"
#include "iso14443a.h" #include "iso14443a.h"
#include "crapto1.h" #include "crapto1.h"
#include "mifareutil.h" #include "mifareutil.h"
@ -169,7 +170,7 @@ byte_t oddparity (const byte_t bt)
return OddByteParity[bt]; return OddByteParity[bt];
} }
void GetParity(const uint8_t * pbtCmd, uint16_t iLen, uint8_t *par) void GetParity(const uint8_t *pbtCmd, uint16_t iLen, uint8_t *par)
{ {
uint16_t paritybit_cnt = 0; uint16_t paritybit_cnt = 0;
uint16_t paritybyte_cnt = 0; uint16_t paritybyte_cnt = 0;
@ -179,12 +180,12 @@ void GetParity(const uint8_t * pbtCmd, uint16_t iLen, uint8_t *par)
// Generate the parity bits // Generate the parity bits
parityBits |= ((OddByteParity[pbtCmd[i]]) << (7-paritybit_cnt)); parityBits |= ((OddByteParity[pbtCmd[i]]) << (7-paritybit_cnt));
if (paritybit_cnt == 7) { if (paritybit_cnt == 7) {
par[paritybyte_cnt] = parityBits; // save 8 Bits parity par[paritybyte_cnt] = parityBits; // save 8 Bits parity
parityBits = 0; // and advance to next Parity Byte parityBits = 0; // and advance to next Parity Byte
paritybyte_cnt++; paritybyte_cnt++;
paritybit_cnt = 0; paritybit_cnt = 0;
} else { } else {
paritybit_cnt++; paritybit_cnt++;
} }
} }
@ -203,7 +204,7 @@ bool RAMFUNC LogTrace(const uint8_t *btBytes, uint16_t iLen, uint32_t timestamp_
{ {
if (!tracing) return FALSE; if (!tracing) return FALSE;
uint16_t num_paritybytes = (iLen-1)/8 + 1; // number of valid paritybytes in *parity uint16_t num_paritybytes = (iLen-1)/8 + 1; // number of valid paritybytes in *parity
uint16_t duration = timestamp_end - timestamp_start; uint16_t duration = timestamp_end - timestamp_start;
// Return when trace is full // Return when trace is full
@ -236,13 +237,13 @@ bool RAMFUNC LogTrace(const uint8_t *btBytes, uint16_t iLen, uint32_t timestamp_
// readerToTag flag // readerToTag flag
if (!readerToTag) { if (!readerToTag) {
trace[traceLen - 1] |= 0x80; trace[traceLen - 1] |= 0x80;
} }
// data bytes // data bytes
if (btBytes != NULL && iLen != 0) { if (btBytes != NULL && iLen != 0) {
memcpy(trace + traceLen, btBytes, iLen); memcpy(trace + traceLen, btBytes, iLen);
} }
traceLen += iLen; traceLen += iLen;
// parity bytes // parity bytes
if (parity != NULL && iLen != 0) { if (parity != NULL && iLen != 0) {
@ -307,7 +308,7 @@ static RAMFUNC bool MillerDecoding(uint8_t bit, uint32_t non_real_time)
Uart.twoBits = (Uart.twoBits << 8) | bit; Uart.twoBits = (Uart.twoBits << 8) | bit;
if (Uart.state == STATE_UNSYNCD) { // not yet synced if (Uart.state == STATE_UNSYNCD) { // not yet synced
if (Uart.highCnt < 7) { // wait for a stable unmodulated signal if (Uart.highCnt < 7) { // wait for a stable unmodulated signal
if (Uart.twoBits == 0xffff) { if (Uart.twoBits == 0xffff) {
@ -355,9 +356,9 @@ static RAMFUNC bool MillerDecoding(uint8_t bit, uint32_t non_real_time)
Uart.parityBits |= ((Uart.shiftReg >> 8) & 0x01); // store parity bit Uart.parityBits |= ((Uart.shiftReg >> 8) & 0x01); // store parity bit
Uart.bitCount = 0; Uart.bitCount = 0;
Uart.shiftReg = 0; Uart.shiftReg = 0;
if((Uart.len & 0x0007) == 0) { // every 8 data bytes if((Uart.len&0x0007) == 0) { // every 8 data bytes
Uart.parity[Uart.parityLen++] = Uart.parityBits; // store 8 parity bits Uart.parity[Uart.parityLen++] = Uart.parityBits; // store 8 parity bits
Uart.parityBits = 0; Uart.parityBits = 0;
} }
} }
} }
@ -374,29 +375,29 @@ static RAMFUNC bool MillerDecoding(uint8_t bit, uint32_t non_real_time)
Uart.parityBits |= ((Uart.shiftReg >> 8) & 0x01); // store parity bit Uart.parityBits |= ((Uart.shiftReg >> 8) & 0x01); // store parity bit
Uart.bitCount = 0; Uart.bitCount = 0;
Uart.shiftReg = 0; Uart.shiftReg = 0;
if ((Uart.len & 0x0007) == 0) { // every 8 data bytes if ((Uart.len&0x0007) == 0) { // every 8 data bytes
Uart.parity[Uart.parityLen++] = Uart.parityBits; // store 8 parity bits Uart.parity[Uart.parityLen++] = Uart.parityBits; // store 8 parity bits
Uart.parityBits = 0; Uart.parityBits = 0;
} }
} }
} else { // no modulation in both halves - Sequence Y } else { // no modulation in both halves - Sequence Y
if (Uart.state == STATE_MILLER_Z || Uart.state == STATE_MILLER_Y) { // Y after logic "0" - End of Communication if (Uart.state == STATE_MILLER_Z || Uart.state == STATE_MILLER_Y) { // Y after logic "0" - End of Communication
Uart.state = STATE_UNSYNCD; Uart.state = STATE_UNSYNCD;
Uart.bitCount--; // last "0" was part of EOC sequence Uart.bitCount--; // last "0" was part of EOC sequence
Uart.shiftReg <<= 1; // drop it Uart.shiftReg <<= 1; // drop it
if(Uart.bitCount > 0) { // if we decoded some bits if(Uart.bitCount > 0) { // if we decoded some bits
Uart.shiftReg >>= (9 - Uart.bitCount); // right align them Uart.shiftReg >>= (9 - Uart.bitCount); // right align them
Uart.output[Uart.len++] = (Uart.shiftReg & 0xff); // add last byte to the output Uart.output[Uart.len++] = (Uart.shiftReg & 0xff); // add last byte to the output
Uart.parityBits <<= 1; // add a (void) parity bit Uart.parityBits <<= 1; // add a (void) parity bit
Uart.parityBits <<= (8 - (Uart.len & 0x0007)); // left align parity bits Uart.parityBits <<= (8 - (Uart.len&0x0007)); // left align parity bits
Uart.parity[Uart.parityLen++] = Uart.parityBits; // and store it Uart.parity[Uart.parityLen++] = Uart.parityBits; // and store it
return TRUE; return TRUE;
} else if (Uart.len & 0x0007) { // there are some parity bits to store } else if (Uart.len & 0x0007) { // there are some parity bits to store
Uart.parityBits <<= (8 - (Uart.len & 0x0007)); // left align remaining parity bits Uart.parityBits <<= (8 - (Uart.len&0x0007)); // left align remaining parity bits
Uart.parity[Uart.parityLen++] = Uart.parityBits; // and store them Uart.parity[Uart.parityLen++] = Uart.parityBits; // and store them
} }
if ( Uart.len) { if (Uart.len) {
return TRUE; // we are finished with decoding the raw data sequence return TRUE; // we are finished with decoding the raw data sequence
} else { } else {
UartReset(); // Nothing receiver - start over UartReset(); // Nothing receiver - start over
} }
@ -414,8 +415,8 @@ static RAMFUNC bool MillerDecoding(uint8_t bit, uint32_t non_real_time)
Uart.parityBits |= ((Uart.shiftReg >> 8) & 0x01); // store parity bit Uart.parityBits |= ((Uart.shiftReg >> 8) & 0x01); // store parity bit
Uart.bitCount = 0; Uart.bitCount = 0;
Uart.shiftReg = 0; Uart.shiftReg = 0;
if ((Uart.len & 0x0007) == 0) { // every 8 data bytes if ((Uart.len&0x0007) == 0) { // every 8 data bytes
Uart.parity[Uart.parityLen++] = Uart.parityBits; // store 8 parity bits Uart.parity[Uart.parityLen++] = Uart.parityBits; // store 8 parity bits
Uart.parityBits = 0; Uart.parityBits = 0;
} }
} }
@ -527,8 +528,8 @@ static RAMFUNC int ManchesterDecoding(uint8_t bit, uint16_t offset, uint32_t non
Demod.parityBits |= ((Demod.shiftReg >> 8) & 0x01); // store parity bit Demod.parityBits |= ((Demod.shiftReg >> 8) & 0x01); // store parity bit
Demod.bitCount = 0; Demod.bitCount = 0;
Demod.shiftReg = 0; Demod.shiftReg = 0;
if((Demod.len & 0x0007) == 0) { // every 8 data bytes if((Demod.len&0x0007) == 0) { // every 8 data bytes
Demod.parity[Demod.parityLen++] = Demod.parityBits; // store 8 parity bits Demod.parity[Demod.parityLen++] = Demod.parityBits; // store 8 parity bits
Demod.parityBits = 0; Demod.parityBits = 0;
} }
} }
@ -543,26 +544,26 @@ static RAMFUNC int ManchesterDecoding(uint8_t bit, uint16_t offset, uint32_t non
Demod.parityBits |= ((Demod.shiftReg >> 8) & 0x01); // store parity bit Demod.parityBits |= ((Demod.shiftReg >> 8) & 0x01); // store parity bit
Demod.bitCount = 0; Demod.bitCount = 0;
Demod.shiftReg = 0; Demod.shiftReg = 0;
if ((Demod.len & 0x0007) == 0) { // every 8 data bytes if ((Demod.len&0x0007) == 0) { // every 8 data bytes
Demod.parity[Demod.parityLen++] = Demod.parityBits; // store 8 parity bits1 Demod.parity[Demod.parityLen++] = Demod.parityBits; // store 8 parity bits1
Demod.parityBits = 0; Demod.parityBits = 0;
} }
} }
Demod.endTime = Demod.startTime + 8*(9*Demod.len + Demod.bitCount + 1); Demod.endTime = Demod.startTime + 8*(9*Demod.len + Demod.bitCount + 1);
} else { // no modulation in both halves - End of communication } else { // no modulation in both halves - End of communication
if(Demod.bitCount > 0) { // there are some remaining data bits if(Demod.bitCount > 0) { // there are some remaining data bits
Demod.shiftReg >>= (9 - Demod.bitCount); // right align the decoded bits Demod.shiftReg >>= (9 - Demod.bitCount); // right align the decoded bits
Demod.output[Demod.len++] = Demod.shiftReg & 0xff; // and add them to the output Demod.output[Demod.len++] = Demod.shiftReg & 0xff; // and add them to the output
Demod.parityBits <<= 1; // add a (void) parity bit Demod.parityBits <<= 1; // add a (void) parity bit
Demod.parityBits <<= (8 - (Demod.len & 0x0007)); // left align remaining parity bits Demod.parityBits <<= (8 - (Demod.len&0x0007)); // left align remaining parity bits
Demod.parity[Demod.parityLen++] = Demod.parityBits; // and store them Demod.parity[Demod.parityLen++] = Demod.parityBits; // and store them
return TRUE; return TRUE;
} else if (Demod.len & 0x0007) { // there are some parity bits to store } else if (Demod.len & 0x0007) { // there are some parity bits to store
Demod.parityBits <<= (8 - (Demod.len & 0x0007)); // left align remaining parity bits Demod.parityBits <<= (8 - (Demod.len&0x0007)); // left align remaining parity bits
Demod.parity[Demod.parityLen++] = Demod.parityBits; // and store them Demod.parity[Demod.parityLen++] = Demod.parityBits; // and store them
} }
if (Demod.len) { if (Demod.len) {
return TRUE; // we are finished with decoding the raw data sequence return TRUE; // we are finished with decoding the raw data sequence
} else { // nothing received. Start over } else { // nothing received. Start over
DemodReset(); DemodReset();
} }
@ -688,11 +689,11 @@ void RAMFUNC SnoopIso14443a(uint8_t param) {
if(triggered) { if(triggered) {
if (!LogTrace(receivedCmd, if (!LogTrace(receivedCmd,
Uart.len, Uart.len,
Uart.startTime*16 - DELAY_READER_AIR2ARM_AS_SNIFFER, Uart.startTime*16 - DELAY_READER_AIR2ARM_AS_SNIFFER,
Uart.endTime*16 - DELAY_READER_AIR2ARM_AS_SNIFFER, Uart.endTime*16 - DELAY_READER_AIR2ARM_AS_SNIFFER,
Uart.parity, Uart.parity,
TRUE)) break; TRUE)) break;
} }
/* And ready to receive another command. */ /* And ready to receive another command. */
UartReset(); UartReset();
@ -710,11 +711,11 @@ void RAMFUNC SnoopIso14443a(uint8_t param) {
LED_B_ON(); LED_B_ON();
if (!LogTrace(receivedResponse, if (!LogTrace(receivedResponse,
Demod.len, Demod.len,
Demod.startTime*16 - DELAY_TAG_AIR2ARM_AS_SNIFFER, Demod.startTime*16 - DELAY_TAG_AIR2ARM_AS_SNIFFER,
Demod.endTime*16 - DELAY_TAG_AIR2ARM_AS_SNIFFER, Demod.endTime*16 - DELAY_TAG_AIR2ARM_AS_SNIFFER,
Demod.parity, Demod.parity,
FALSE)) break; FALSE)) break;
if ((!triggered) && (param & 0x01)) triggered = TRUE; if ((!triggered) && (param & 0x01)) triggered = TRUE;
@ -745,7 +746,7 @@ void RAMFUNC SnoopIso14443a(uint8_t param) {
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
// Prepare tag messages // Prepare tag messages
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
static void CodeIso14443aAsTagPar(const uint8_t *cmd, uint16_t len, uint8_t *parity) static void CodeIso14443aAsTagPar(const uint8_t *cmd, uint16_t len, uint8_t *parity)
{ {
ToSendReset(); ToSendReset();
@ -763,7 +764,7 @@ static void CodeIso14443aAsTagPar(const uint8_t *cmd, uint16_t len, uint8_t *pa
ToSend[++ToSendMax] = SEC_D; ToSend[++ToSendMax] = SEC_D;
LastProxToAirDuration = 8 * ToSendMax - 4; LastProxToAirDuration = 8 * ToSendMax - 4;
for( uint16_t i = 0; i < len; i++) { for(uint16_t i = 0; i < len; i++) {
uint8_t b = cmd[i]; uint8_t b = cmd[i];
// Data bits // Data bits
@ -1034,7 +1035,7 @@ void SimulateIso14443aTag(int tagType, int uid_1st, int uid_2nd, byte_t* data)
ComputeCrc14443(CRC_14443_A, response3a, 1, &response3a[1], &response3a[2]); ComputeCrc14443(CRC_14443_A, response3a, 1, &response3a[1], &response3a[2]);
uint8_t response5[] = { 0x00, 0x00, 0x00, 0x00 }; // Very random tag nonce uint8_t response5[] = { 0x00, 0x00, 0x00, 0x00 }; // Very random tag nonce
uint8_t response6[] = { 0x04, 0x58, 0x80, 0x02, 0x00, 0x00 }; // dummy ATS (pseudo-ATR), answer to RATS: uint8_t response6[] = { 0x04, 0x58, 0x80, 0x02, 0x00, 0x00 }; // dummy ATS (pseudo-ATR), answer to RATS:
// Format byte = 0x58: FSCI=0x08 (FSC=256), TA(1) and TC(1) present, // Format byte = 0x58: FSCI=0x08 (FSC=256), TA(1) and TC(1) present,
// TA(1) = 0x80: different divisors not supported, DR = 1, DS = 1 // TA(1) = 0x80: different divisors not supported, DR = 1, DS = 1
// TB(1) = not present. Defaults: FWI = 4 (FWT = 256 * 16 * 2^4 * 1/fc = 4833us), SFGI = 0 (SFG = 256 * 16 * 2^0 * 1/fc = 302us) // TB(1) = not present. Defaults: FWI = 4 (FWT = 256 * 16 * 2^4 * 1/fc = 4833us), SFGI = 0 (SFG = 256 * 16 * 2^0 * 1/fc = 302us)
@ -1330,7 +1331,7 @@ static void TransmitFor14443a(const uint8_t *cmd, uint16_t len, uint32_t *timing
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
// Prepare reader command (in bits, support short frames) to send to FPGA // Prepare reader command (in bits, support short frames) to send to FPGA
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
void CodeIso14443aBitsAsReaderPar(const uint8_t * cmd, uint16_t bits, const uint8_t *parity) void CodeIso14443aBitsAsReaderPar(const uint8_t *cmd, uint16_t bits, const uint8_t *parity)
{ {
int i, j; int i, j;
int last; int last;
@ -1411,7 +1412,7 @@ void CodeIso14443aBitsAsReaderPar(const uint8_t * cmd, uint16_t bits, const uint
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
// Prepare reader command to send to FPGA // Prepare reader command to send to FPGA
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
void CodeIso14443aAsReaderPar(const uint8_t * cmd, uint16_t len, const uint8_t *parity) void CodeIso14443aAsReaderPar(const uint8_t *cmd, uint16_t len, const uint8_t *parity)
{ {
CodeIso14443aBitsAsReaderPar(cmd, len*8, parity); CodeIso14443aBitsAsReaderPar(cmd, len*8, parity);
} }
@ -1610,16 +1611,16 @@ bool EmLogTrace(uint8_t *reader_data, uint16_t reader_len, uint32_t reader_Start
uint8_t *tag_data, uint16_t tag_len, uint32_t tag_StartTime, uint32_t tag_EndTime, uint8_t *tag_Parity) uint8_t *tag_data, uint16_t tag_len, uint32_t tag_StartTime, uint32_t tag_EndTime, uint8_t *tag_Parity)
{ {
if (tracing) { if (tracing) {
// we cannot exactly measure the end and start of a received command from reader. However we know that the delay from // we cannot exactly measure the end and start of a received command from reader. However we know that the delay from
// end of the received command to start of the tag's (simulated by us) answer is n*128+20 or n*128+84 resp. // end of the received command to start of the tag's (simulated by us) answer is n*128+20 or n*128+84 resp.
// with n >= 9. The start of the tags answer can be measured and therefore the end of the received command be calculated: // with n >= 9. The start of the tags answer can be measured and therefore the end of the received command be calculated:
uint16_t reader_modlen = reader_EndTime - reader_StartTime; uint16_t reader_modlen = reader_EndTime - reader_StartTime;
uint16_t approx_fdt = tag_StartTime - reader_EndTime; uint16_t approx_fdt = tag_StartTime - reader_EndTime;
uint16_t exact_fdt = (approx_fdt - 20 + 32)/64 * 64 + 20; uint16_t exact_fdt = (approx_fdt - 20 + 32)/64 * 64 + 20;
reader_EndTime = tag_StartTime - exact_fdt; reader_EndTime = tag_StartTime - exact_fdt;
reader_StartTime = reader_EndTime - reader_modlen; reader_StartTime = reader_EndTime - reader_modlen;
if (!LogTrace(reader_data, reader_len, reader_StartTime, reader_EndTime, reader_Parity, TRUE)) { if (!LogTrace(reader_data, reader_len, reader_StartTime, reader_EndTime, reader_Parity, TRUE)) {
return FALSE; return FALSE;
} else return(!LogTrace(tag_data, tag_len, tag_StartTime, tag_EndTime, tag_Parity, FALSE)); } else return(!LogTrace(tag_data, tag_len, tag_StartTime, tag_EndTime, tag_Parity, FALSE));
} else { } else {
return TRUE; return TRUE;
@ -1685,23 +1686,23 @@ void ReaderTransmitPar(uint8_t* frame, uint16_t len, uint8_t *par, uint32_t *tim
void ReaderTransmitBits(uint8_t* frame, uint16_t len, uint32_t *timing) void ReaderTransmitBits(uint8_t* frame, uint16_t len, uint32_t *timing)
{ {
// Generate parity and redirect // Generate parity and redirect
uint8_t par[MAX_PARITY_SIZE]; uint8_t par[MAX_PARITY_SIZE];
GetParity(frame, len/8, par); GetParity(frame, len/8, par);
ReaderTransmitBitsPar(frame, len, par, timing); ReaderTransmitBitsPar(frame, len, par, timing);
} }
void ReaderTransmit(uint8_t* frame, uint16_t len, uint32_t *timing) void ReaderTransmit(uint8_t* frame, uint16_t len, uint32_t *timing)
{ {
// Generate parity and redirect // Generate parity and redirect
uint8_t par[MAX_PARITY_SIZE]; uint8_t par[MAX_PARITY_SIZE];
GetParity(frame, len, par); GetParity(frame, len, par);
ReaderTransmitBitsPar(frame, len*8, par, timing); ReaderTransmitBitsPar(frame, len*8, par, timing);
} }
int ReaderReceiveOffset(uint8_t* receivedAnswer, uint16_t offset, uint8_t *parity) int ReaderReceiveOffset(uint8_t* receivedAnswer, uint16_t offset, uint8_t *parity)
{ {
if (!GetIso14443aAnswerFromTag(receivedAnswer,parity,offset)) return FALSE; if (!GetIso14443aAnswerFromTag(receivedAnswer, parity, offset)) return FALSE;
if (tracing) { if (tracing) {
LogTrace(receivedAnswer, Demod.len, Demod.startTime*16 - DELAY_AIR2ARM_AS_READER, Demod.endTime*16 - DELAY_AIR2ARM_AS_READER, parity, FALSE); LogTrace(receivedAnswer, Demod.len, Demod.startTime*16 - DELAY_AIR2ARM_AS_READER, Demod.endTime*16 - DELAY_AIR2ARM_AS_READER, parity, FALSE);
} }
@ -1720,30 +1721,22 @@ int ReaderReceive(uint8_t *receivedAnswer, uint8_t *parity)
/* performs iso14443a anticollision procedure /* performs iso14443a anticollision procedure
* fills the uid pointer unless NULL * fills the uid pointer unless NULL
* fills resp_data unless NULL */ * fills resp_data unless NULL */
int iso14443a_select_card(byte_t* uid_ptr, iso14a_card_select_t* p_hi14a_card, uint32_t* cuid_ptr) { int iso14443a_select_card(byte_t *uid_ptr, iso14a_card_select_t *p_hi14a_card, uint32_t *cuid_ptr) {
uint8_t wupa[] = { 0x52 }; // 0x26 - REQA 0x52 - WAKE-UP
//uint8_t deselect[] = {0xc2}; //DESELECT
//uint8_t halt[] = { 0x50, 0x00, 0x57, 0xCD }; // HALT
uint8_t wupa[] = { 0x52 }; // WAKE-UP
//uint8_t reqa[] = { 0x26 }; // REQUEST A
uint8_t sel_all[] = { 0x93,0x20 }; uint8_t sel_all[] = { 0x93,0x20 };
uint8_t sel_uid[] = { 0x93,0x70,0x00,0x00,0x00,0x00,0x00,0x00,0x00}; uint8_t sel_uid[] = { 0x93,0x70,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
uint8_t rats[] = { 0xE0,0x80,0x00,0x00 }; // FSD=256, FSDI=8, CID=0 uint8_t rats[] = { 0xE0,0x80,0x00,0x00 }; // FSD=256, FSDI=8, CID=0
uint8_t *resp = ((uint8_t *)BigBuf) + RECV_RESP_OFFSET; uint8_t *resp = ((uint8_t *)BigBuf) + RECV_RESP_OFFSET;
uint8_t *resp_par = ((uint8_t *)BigBuf) + RECV_RESP_PAR_OFFSET; uint8_t *resp_par = ((uint8_t *)BigBuf) + RECV_RESP_PAR_OFFSET;
byte_t uid_resp[4]; byte_t uid_resp[4];
size_t uid_resp_len; size_t uid_resp_len;
uint8_t sak = 0x04; // cascade uid uint8_t sak = 0x04; // cascade uid
int cascade_level = 0; int cascade_level = 0;
int len =0; int len;
// test for the SKYLANDERS TOY.
// ReaderTransmit(deselect,sizeof(deselect), NULL);
// len = ReaderReceive(resp, resp_par);
// Broadcast for a card, WUPA (0x52) will force response from all cards in the field // Broadcast for a card, WUPA (0x52) will force response from all cards in the field
ReaderTransmitBitsPar(wupa,7,0, NULL); ReaderTransmitBitsPar(wupa,7,0, NULL);
// Receive the ATQA // Receive the ATQA
if(!ReaderReceive(resp, resp_par)) return 0; if(!ReaderReceive(resp, resp_par)) return 0;
@ -1759,95 +1752,91 @@ int iso14443a_select_card(byte_t* uid_ptr, iso14a_card_select_t* p_hi14a_card, u
memset(uid_ptr,0,10); memset(uid_ptr,0,10);
} }
// OK we will select at least at cascade 1, lets see if first byte of UID was 0x88 in // OK we will select at least at cascade 1, lets see if first byte of UID was 0x88 in
// which case we need to make a cascade 2 request and select - this is a long UID // which case we need to make a cascade 2 request and select - this is a long UID
// While the UID is not complete, the 3nd bit (from the right) is set in the SAK. // While the UID is not complete, the 3nd bit (from the right) is set in the SAK.
for(; sak & 0x04; cascade_level++) { for(; sak & 0x04; cascade_level++) {
// SELECT_* (L1: 0x93, L2: 0x95, L3: 0x97) // SELECT_* (L1: 0x93, L2: 0x95, L3: 0x97)
sel_uid[0] = sel_all[0] = 0x93 + cascade_level * 2; sel_uid[0] = sel_all[0] = 0x93 + cascade_level * 2;
// SELECT_ALL // SELECT_ALL
ReaderTransmit(sel_all,sizeof(sel_all), NULL); 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 if (Demod.collisionPos) { // we had a collision and need to construct the UID bit by bit
memset(uid_resp, 0, 4); memset(uid_resp, 0, 4);
uint16_t uid_resp_bits = 0; uint16_t uid_resp_bits = 0;
uint16_t collision_answer_offset = 0; uint16_t collision_answer_offset = 0;
// anti-collision-loop: // anti-collision-loop:
while (Demod.collisionPos) { while (Demod.collisionPos) {
Dbprintf("Multiple tags detected. Collision after Bit %d", Demod.collisionPos); Dbprintf("Multiple tags detected. Collision after Bit %d", Demod.collisionPos);
for (uint16_t i = collision_answer_offset; i < Demod.collisionPos; i++, uid_resp_bits++) { // add valid UID bits before collision point for (uint16_t i = collision_answer_offset; i < Demod.collisionPos; i++, uid_resp_bits++) { // add valid UID bits before collision point
uint16_t UIDbit = (resp[i/8] >> (i % 8)) & 0x01; uint16_t UIDbit = (resp[i/8] >> (i % 8)) & 0x01;
uid_resp[uid_resp_bits & 0xf8] |= UIDbit << (uid_resp_bits % 8); uid_resp[uid_resp_bits & 0xf8] |= UIDbit << (uid_resp_bits % 8);
}
uid_resp[uid_resp_bits/8] |= 1 << (uid_resp_bits % 8); // next time select the card(s) with a 1 in the collision position
uid_resp_bits++;
// construct anticollosion command:
sel_uid[1] = ((2 + uid_resp_bits/8) << 4) | (uid_resp_bits & 0x07); // length of data in bytes and bits
for (uint16_t i = 0; i <= uid_resp_bits/8; i++) {
sel_uid[2+i] = uid_resp[i];
}
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;
} }
uid_resp[uid_resp_bits/8] |= 1 << (uid_resp_bits % 8); // next time select the card(s) with a 1 in the collision position // finally, add the last bits and BCC of the UID
uid_resp_bits++; for (uint16_t i = collision_answer_offset; i < (Demod.len-1)*8; i++, uid_resp_bits++) {
// construct anticollosion command: uint16_t UIDbit = (resp[i/8] >> (i%8)) & 0x01;
sel_uid[1] = ((2 + uid_resp_bits/8) << 4) | (uid_resp_bits & 0x07); // length of data in bytes and bits uid_resp[uid_resp_bits/8] |= UIDbit << (uid_resp_bits % 8);
for (uint16_t i = 0; i <= uid_resp_bits/8; i++) {
sel_uid[2+i] = uid_resp[i];
} }
collision_answer_offset = uid_resp_bits%8;
ReaderTransmitBits(sel_uid, 16 + uid_resp_bits, NULL); } else { // no collision, use the response to SELECT_ALL as current uid
if (!ReaderReceiveOffset(resp, collision_answer_offset,resp_par)) return 0; memcpy(uid_resp, resp, 4);
} }
// finally, add the last bits and BCC of the UID uid_resp_len = 4;
for (uint16_t i = collision_answer_offset; i < (Demod.len-1)*8; i++, uid_resp_bits++) {
uint16_t UIDbit = (resp[i/8] >> (i%8)) & 0x01; // calculate crypto UID. Always use last 4 Bytes.
uid_resp[uid_resp_bits/8] |= UIDbit << (uid_resp_bits % 8); if(cuid_ptr) {
*cuid_ptr = bytes_to_num(uid_resp, 4);
} }
} else { // no collision, use the response to SELECT_ALL as current uid // Construct SELECT UID command
memcpy(uid_resp,resp,4); sel_uid[1] = 0x70; // transmitting a full UID (1 Byte cmd, 1 Byte NVB, 4 Byte UID, 1 Byte BCC, 2 Bytes CRC)
} memcpy(sel_uid+2, uid_resp, 4); // the UID
uid_resp_len = 4; sel_uid[6] = sel_uid[2] ^ sel_uid[3] ^ sel_uid[4] ^ sel_uid[5]; // calculate and add BCC
AppendCrc14443a(sel_uid, 7); // calculate and add CRC
ReaderTransmit(sel_uid, sizeof(sel_uid), NULL);
// calculate crypto UID. Always use last 4 Bytes. // Receive the SAK
if(cuid_ptr) { if (!ReaderReceive(resp, resp_par)) return 0;
*cuid_ptr = bytes_to_num(uid_resp, 4); sak = resp[0];
}
// Construct SELECT UID command // Test if more parts of the uid are comming
sel_uid[1] = 0x70; // transmitting a full UID (1 Byte cmd, 1 Byte NVB, 4 Byte UID, 1 Byte BCC, 2 Bytes CRC) if ((sak & 0x04) /* && uid_resp[0] == 0x88 */) {
memcpy(sel_uid+2,uid_resp,4); // the UID // Remove first byte, 0x88 is not an UID byte, it CT, see page 3 of:
sel_uid[6] = sel_uid[2] ^ sel_uid[3] ^ sel_uid[4] ^ sel_uid[5]; // calculate and add BCC // http://www.nxp.com/documents/application_note/AN10927.pdf
AppendCrc14443a(sel_uid,7); // calculate and add CRC uid_resp[0] = uid_resp[1];
ReaderTransmit(sel_uid,sizeof(sel_uid), NULL); uid_resp[1] = uid_resp[2];
uid_resp[2] = uid_resp[3];
// Receive the SAK uid_resp_len = 3;
if (!ReaderReceive(resp, resp_par)){ }
return 0;
if(uid_ptr) {
memcpy(uid_ptr + (cascade_level*3), uid_resp, uid_resp_len);
}
if(p_hi14a_card) {
memcpy(p_hi14a_card->uid + (cascade_level*3), uid_resp, uid_resp_len);
p_hi14a_card->uidlen += uid_resp_len;
}
} }
if(p_hi14a_card) {
sak = resp[0]; p_hi14a_card->sak = sak;
p_hi14a_card->ats_len = 0;
// Test if more parts of the uid are coming }
if ((sak & 0x04) /* && uid_resp[0] == 0x88 */) {
// Remove first byte, 0x88 is not an UID byte, it CT, see page 3 of:
// http://www.nxp.com/documents/application_note/AN10927.pdf
uid_resp[0] = uid_resp[1];
uid_resp[1] = uid_resp[2];
uid_resp[2] = uid_resp[3];
uid_resp_len = 3;
}
if(uid_ptr) {
memcpy(uid_ptr + (cascade_level*3), uid_resp, uid_resp_len);
}
if(p_hi14a_card) {
memcpy(p_hi14a_card->uid + (cascade_level*3), uid_resp, uid_resp_len);
p_hi14a_card->uidlen += uid_resp_len;
}
}
if(p_hi14a_card) {
p_hi14a_card->sak = sak;
p_hi14a_card->ats_len = 0;
}
// non iso14443a compliant tag // non iso14443a compliant tag
if( (sak & 0x20) == 0) return 2; if( (sak & 0x20) == 0) return 2;
@ -1877,7 +1866,8 @@ void iso14443a_setup(uint8_t fpga_minor_mode) {
SetAdcMuxFor(GPIO_MUXSEL_HIPKD); SetAdcMuxFor(GPIO_MUXSEL_HIPKD);
// Signal field is on with the appropriate LED // Signal field is on with the appropriate LED
if (fpga_minor_mode == FPGA_HF_ISO14443A_READER_MOD || fpga_minor_mode == FPGA_HF_ISO14443A_READER_LISTEN) { if (fpga_minor_mode == FPGA_HF_ISO14443A_READER_MOD
|| fpga_minor_mode == FPGA_HF_ISO14443A_READER_LISTEN) {
LED_D_ON(); LED_D_ON();
} else { } else {
LED_D_OFF(); LED_D_OFF();
@ -1890,7 +1880,7 @@ void iso14443a_setup(uint8_t fpga_minor_mode) {
DemodReset(); DemodReset();
UartReset(); UartReset();
NextTransferTime = 2*DELAY_ARM2AIR_AS_READER; NextTransferTime = 2*DELAY_ARM2AIR_AS_READER;
iso14a_set_timeout(1050); // 10ms default 10*105 = iso14a_set_timeout(1050); // 10ms default
} }
int iso14_apdu(uint8_t *cmd, uint16_t cmd_len, void *data) { int iso14_apdu(uint8_t *cmd, uint16_t cmd_len, void *data) {
@ -1905,7 +1895,7 @@ int iso14_apdu(uint8_t *cmd, uint16_t cmd_len, void *data) {
ReaderTransmit(real_cmd, cmd_len+4, NULL); ReaderTransmit(real_cmd, cmd_len+4, NULL);
size_t len = ReaderReceive(data, parity); size_t len = ReaderReceive(data, parity);
uint8_t * data_bytes = (uint8_t *) data; uint8_t *data_bytes = (uint8_t *) data;
if (!len) if (!len)
return 0; //DATA LINK ERROR return 0; //DATA LINK ERROR
// if we received an I- or R(ACK)-Block with a block number equal to the // if we received an I- or R(ACK)-Block with a block number equal to the
@ -2168,7 +2158,7 @@ void ReaderMifare(bool first_try)
led_on = !led_on; led_on = !led_on;
if(led_on) LED_B_ON(); else LED_B_OFF(); if(led_on) LED_B_ON(); else LED_B_OFF();
par_list[nt_diff] = SwapBits(par[0], 8); par_list[nt_diff] = SwapBits(par[0], 8);
ks_list[nt_diff] = receivedAnswer[0] ^ 0x05; ks_list[nt_diff] = receivedAnswer[0] ^ 0x05;
// Test if the information is complete // Test if the information is complete

View file

@ -12,7 +12,7 @@
#ifndef __ISO14443A_H #ifndef __ISO14443A_H
#define __ISO14443A_H #define __ISO14443A_H
#include "../include/common.h" #include "common.h"
#include "mifaresniff.h" #include "mifaresniff.h"
typedef struct { typedef struct {
@ -28,8 +28,8 @@ typedef struct {
uint16_t bitCount; uint16_t bitCount;
uint16_t collisionPos; uint16_t collisionPos;
uint16_t syncBit; uint16_t syncBit;
uint8_t parityBits; uint8_t parityBits;
uint8_t parityLen; uint8_t parityLen;
uint16_t shiftReg; uint16_t shiftReg;
uint16_t samples; uint16_t samples;
uint16_t len; uint16_t len;
@ -61,8 +61,8 @@ typedef struct {
uint16_t byteCntMax; uint16_t byteCntMax;
uint16_t posCnt; uint16_t posCnt;
uint16_t syncBit; uint16_t syncBit;
uint8_t parityBits; uint8_t parityBits;
uint8_t parityLen; uint8_t parityLen;
uint16_t highCnt; uint16_t highCnt;
uint16_t twoBits; uint16_t twoBits;
uint32_t startTime, endTime; uint32_t startTime, endTime;

View file

@ -58,14 +58,12 @@
// *) document all the functions // *) document all the functions
#include "../include/proxmark3.h" #include "proxmark3.h"
#include "util.h" #include "util.h"
#include "apps.h" #include "apps.h"
#include "string.h" #include "string.h"
#include "../common/iso15693tools.h" #include "iso15693tools.h"
#include "../common/cmd.h" #include "cmd.h"
#include "crapto1.h"
#include "mifareutil.h"
#define arraylen(x) (sizeof(x)/sizeof((x)[0])) #define arraylen(x) (sizeof(x)/sizeof((x)[0]))
@ -453,7 +451,7 @@ static int GetIso15693AnswerFromSniff(uint8_t *receivedResponse, int maxLen, int
int8_t prev = 0; int8_t prev = 0;
// NOW READ RESPONSE // NOW READ RESPONSE
FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_READER_RX_XCORR); FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_READER_RX_XCORR);
//spindelay(60); // greg - experiment to get rid of some of the 0 byte/failed reads //spindelay(60); // greg - experiment to get rid of some of the 0 byte/failed reads
c = 0; c = 0;
@ -469,9 +467,21 @@ static int GetIso15693AnswerFromSniff(uint8_t *receivedResponse, int maxLen, int
// tone that the tag AM-modulates, so every other sample is I, // tone that the tag AM-modulates, so every other sample is I,
// every other is Q. We just want power, so abs(I) + abs(Q) is // every other is Q. We just want power, so abs(I) + abs(Q) is
// close to what we want. // close to what we want.
if (getNext) { if(getNext) {
int8_t r;
dest[c++] = abs(b) + abs(prev); if(b < 0) {
r = -b;
} else {
r = b;
}
if(prev < 0) {
r -= prev;
} else {
r += prev;
}
dest[c++] = (uint8_t)r;
if(c >= 20000) { if(c >= 20000) {
break; break;
@ -679,8 +689,8 @@ void RecordRawAdcSamplesIso15693(void)
FpgaSetupSsc(); FpgaSetupSsc();
// Start from off (no field generated) // Start from off (no field generated)
FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
SpinDelay(200); SpinDelay(200);
SetAdcMuxFor(GPIO_MUXSEL_HIPKD); SetAdcMuxFor(GPIO_MUXSEL_HIPKD);
@ -982,7 +992,7 @@ void SetDebugIso15693(uint32_t debug) {
// Simulate an ISO15693 reader, perform anti-collision and then attempt to read a sector // Simulate an ISO15693 reader, perform anti-collision and then attempt to read a sector
// all demodulation performed in arm rather than host. - greg // all demodulation performed in arm rather than host. - greg
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
void ReaderIso15693(uint32_t parameter ) void ReaderIso15693(uint32_t parameter)
{ {
LED_A_ON(); LED_A_ON();
LED_B_ON(); LED_B_ON();
@ -1014,8 +1024,8 @@ void ReaderIso15693(uint32_t parameter )
FpgaSetupSsc(); FpgaSetupSsc();
// Start from off (no field generated) // Start from off (no field generated)
FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
SpinDelay(200); SpinDelay(200);
// Give the tags time to energize // Give the tags time to energize
FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_READER_RX_XCORR); FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_READER_RX_XCORR);
@ -1055,7 +1065,7 @@ void ReaderIso15693(uint32_t parameter )
Dbhexdump(answerLen1,answer1,true); Dbhexdump(answerLen1,answer1,true);
// UID is reverse // UID is reverse
if (answerLen1 >= 12) if (answerLen1>=12)
Dbprintf("UID = %02hX%02hX%02hX%02hX%02hX%02hX%02hX%02hX", Dbprintf("UID = %02hX%02hX%02hX%02hX%02hX%02hX%02hX%02hX",
TagUID[7],TagUID[6],TagUID[5],TagUID[4], TagUID[7],TagUID[6],TagUID[5],TagUID[4],
TagUID[3],TagUID[2],TagUID[1],TagUID[0]); TagUID[3],TagUID[2],TagUID[1],TagUID[0]);
@ -1069,14 +1079,14 @@ void ReaderIso15693(uint32_t parameter )
DbdecodeIso15693Answer(answerLen3,answer3); DbdecodeIso15693Answer(answerLen3,answer3);
Dbhexdump(answerLen3,answer3,true); Dbhexdump(answerLen3,answer3,true);
// read all pages // read all pages
if (answerLen1 >= 12 && DEBUG) { if (answerLen1>=12 && DEBUG) {
i=0; i=0;
while (i < 32) { // sanity check, assume max 32 pages while (i<32) { // sanity check, assume max 32 pages
BuildReadBlockRequest(TagUID,i); BuildReadBlockRequest(TagUID,i);
TransmitTo15693Tag(ToSend,ToSendMax,&tsamples, &wait); TransmitTo15693Tag(ToSend,ToSendMax,&tsamples, &wait);
answerLen2 = GetIso15693AnswerFromTag(answer2, 100, &samples, &elapsed); answerLen2 = GetIso15693AnswerFromTag(answer2, 100, &samples, &elapsed);
if (answerLen2 > 0) { if (answerLen2>0) {
Dbprintf("READ SINGLE BLOCK %d returned %d octets:",i,answerLen2); Dbprintf("READ SINGLE BLOCK %d returned %d octets:",i,answerLen2);
DbdecodeIso15693Answer(answerLen2,answer2); DbdecodeIso15693Answer(answerLen2,answer2);
Dbhexdump(answerLen2,answer2,true); Dbhexdump(answerLen2,answer2,true);
@ -1118,8 +1128,8 @@ void SimTagIso15693(uint32_t parameter, uint8_t *uid)
FpgaSetupSsc(); FpgaSetupSsc();
// Start from off (no field generated) // Start from off (no field generated)
FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
SpinDelay(200); SpinDelay(200);
LED_A_OFF(); LED_A_OFF();
LED_B_OFF(); LED_B_OFF();
@ -1136,7 +1146,7 @@ void SimTagIso15693(uint32_t parameter, uint8_t *uid)
BuildInventoryResponse(uid); BuildInventoryResponse(uid);
TransmitTo15693Reader(ToSend, ToSendMax, &tsamples, &wait); TransmitTo15693Reader(ToSend,ToSendMax, &tsamples, &wait);
} }
Dbprintf("%d octets read from reader command: %x %x %x %x %x %x %x %x %x", answerLen1, Dbprintf("%d octets read from reader command: %x %x %x %x %x %x %x %x %x", answerLen1,

View file

@ -8,14 +8,14 @@
// LEGIC RF simulation code // LEGIC RF simulation code
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
#include "../include/proxmark3.h" #include "proxmark3.h"
#include "apps.h" #include "apps.h"
#include "util.h" #include "util.h"
#include "string.h" #include "string.h"
#include "legicrf.h" #include "legicrf.h"
#include "../include/legic_prng.h" #include "legic_prng.h"
#include "../common/crc.h" #include "crc.h"
static struct legic_frame { static struct legic_frame {
int bits; int bits;

File diff suppressed because it is too large Load diff

View file

@ -15,9 +15,6 @@
#include "mifarecmd.h" #include "mifarecmd.h"
#include "apps.h" #include "apps.h"
#include "util.h"
#include "desfire.h"
#include "../common/crc.h"
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
// Select, Authenticate, Read a MIFARE tag. // Select, Authenticate, Read a MIFARE tag.
@ -76,75 +73,13 @@ void MifareReadBlock(uint8_t arg0, uint8_t arg1, uint8_t arg2, uint8_t *datain)
// ----------------------------- crypto1 destroy // ----------------------------- crypto1 destroy
crypto1_destroy(pcs); crypto1_destroy(pcs);
if (MF_DBGLEVEL >= 2) DbpString("READ BLOCK FINISHED"); if (MF_DBGLEVEL >= 2) DbpString("READ BLOCK FINISHED");
LED_B_ON(); LED_B_ON();
cmd_send(CMD_ACK,isOK,0,0,dataoutbuf,16); cmd_send(CMD_ACK,isOK,0,0,dataoutbuf,16);
LED_B_OFF(); LED_B_OFF();
FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
LEDsoff();
}
void MifareUC_Auth1(uint8_t arg0, uint8_t *datain){
// variables
byte_t isOK = 0;
byte_t dataoutbuf[16];
uint8_t uid[10];
uint32_t cuid;
// clear trace
iso14a_clear_trace();
iso14443a_setup(FPGA_HF_ISO14443A_READER_LISTEN);
LED_A_ON();
LED_B_OFF();
LED_C_OFF();
if(!iso14443a_select_card(uid, NULL, &cuid)) {
if (MF_DBGLEVEL >= 1) Dbprintf("Can't select card, something went wrong before auth");
};
if(mifare_ultra_auth1(cuid, dataoutbuf)){
if (MF_DBGLEVEL >= 1) Dbprintf("Authentication part1: Fail.");
}
isOK=1;
if (MF_DBGLEVEL >= 2) DbpString("AUTH 1 FINISHED");
LED_B_ON();
cmd_send(CMD_ACK,isOK,cuid,0,dataoutbuf,11);
LED_B_OFF();
// Thats it... // Thats it...
LEDsoff();
}
void MifareUC_Auth2(uint32_t arg0, uint8_t *datain){
// params
uint32_t cuid = arg0;
uint8_t key[16]={0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
// variables
byte_t isOK = 0;
byte_t dataoutbuf[16];
memcpy(key, datain, 16);
LED_A_ON();
LED_B_OFF();
LED_C_OFF();
if(mifare_ultra_auth2(cuid, key, dataoutbuf)){
if (MF_DBGLEVEL >= 1) Dbprintf("Authentication part2: Fail...");
}
isOK=1;
if (MF_DBGLEVEL >= 2) DbpString("AUTH 2 FINISHED");
LED_B_ON();
cmd_send(CMD_ACK,isOK,0,0,dataoutbuf,11);
LED_B_OFF();
FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
LEDsoff(); LEDsoff();
} }
@ -265,38 +200,37 @@ void MifareReadSector(uint8_t arg0, uint8_t arg1, uint8_t arg2, uint8_t *datain)
LEDsoff(); LEDsoff();
} }
void MifareUReadCard(uint8_t arg0, int arg1, uint8_t *datain)
void MifareUReadCard(uint8_t arg0, uint8_t *datain)
{ {
// params // params
uint8_t sectorNo = arg0; uint8_t sectorNo = arg0;
int Pages=arg1;
int count_Pages=0;
// variables
byte_t isOK = 0;
byte_t dataoutbuf[176];
uint8_t uid[10];
uint32_t cuid;
// clear trace // variables
iso14a_clear_trace(); byte_t isOK = 0;
byte_t dataoutbuf[16 * 4];
uint8_t uid[10];
uint32_t cuid;
iso14443a_setup(FPGA_HF_ISO14443A_READER_LISTEN); // clear trace
iso14a_clear_trace();
// iso14a_set_tracing(false);
iso14443a_setup(FPGA_HF_ISO14443A_READER_LISTEN);
LED_A_ON();
LED_B_OFF();
LED_C_OFF();
LED_A_ON();
LED_B_OFF();
LED_C_OFF();
Dbprintf("Pages %d",Pages);
while (true) { while (true) {
if(!iso14443a_select_card(uid, NULL, &cuid)) { if(!iso14443a_select_card(uid, NULL, &cuid)) {
if (MF_DBGLEVEL >= 1) Dbprintf("Can't select card"); if (MF_DBGLEVEL >= 1) Dbprintf("Can't select card");
break; break;
}; };
for(int sec=0;sec<Pages;sec++){ for(int sec=0;sec<16;sec++){
if(mifare_ultra_readblock(cuid, sectorNo * 4 + sec, dataoutbuf + 4 * sec)) { if(mifare_ultra_readblock(cuid, sectorNo * 4 + sec, dataoutbuf + 4 * sec)) {
if (MF_DBGLEVEL >= 1) Dbprintf("Read block %d error",sec); if (MF_DBGLEVEL >= 1) Dbprintf("Read block %d error",sec);
break; break;
}else{
count_Pages++;
}; };
} }
if(mifare_ultra_halt(cuid)) { if(mifare_ultra_halt(cuid)) {
@ -307,18 +241,16 @@ void MifareUReadCard(uint8_t arg0, int arg1, uint8_t *datain)
isOK = 1; isOK = 1;
break; break;
} }
Dbprintf("Pages read %d",count_Pages);
if (MF_DBGLEVEL >= 2) DbpString("READ CARD FINISHED"); if (MF_DBGLEVEL >= 2) DbpString("READ CARD FINISHED");
LED_B_ON(); LED_B_ON();
if (Pages==16) cmd_send(CMD_ACK,isOK,0,0,dataoutbuf,64); cmd_send(CMD_ACK,isOK,0,0,dataoutbuf,64);
if (Pages==44 && count_Pages==16) cmd_send(CMD_ACK,isOK,0,0,dataoutbuf,64);
if (Pages==44 && count_Pages>16) cmd_send(CMD_ACK,isOK,0,0,dataoutbuf,176);
LED_B_OFF(); LED_B_OFF();
// Thats it... // Thats it...
FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
LEDsoff(); LEDsoff();
} }
@ -505,7 +437,7 @@ void MifareUWriteBlock_Special(uint8_t arg0, uint8_t *datain)
} }
// Return 1 if the nonce is invalid else return 0 // Return 1 if the nonce is invalid else return 0
int valid_nonce(uint32_t Nt, uint32_t NtEnc, uint32_t Ks1, uint8_t * parity) { int valid_nonce(uint32_t Nt, uint32_t NtEnc, uint32_t Ks1, uint8_t *parity) {
return ((oddparity((Nt >> 24) & 0xFF) == ((parity[0]) ^ oddparity((NtEnc >> 24) & 0xFF) ^ BIT(Ks1,16))) & \ return ((oddparity((Nt >> 24) & 0xFF) == ((parity[0]) ^ oddparity((NtEnc >> 24) & 0xFF) ^ BIT(Ks1,16))) & \
(oddparity((Nt >> 16) & 0xFF) == ((parity[1]) ^ oddparity((NtEnc >> 16) & 0xFF) ^ BIT(Ks1,8))) & \ (oddparity((Nt >> 16) & 0xFF) == ((parity[1]) ^ oddparity((NtEnc >> 16) & 0xFF) ^ BIT(Ks1,8))) & \
(oddparity((Nt >> 8) & 0xFF) == ((parity[2]) ^ oddparity((NtEnc >> 8) & 0xFF) ^ BIT(Ks1,0)))) ? 1 : 0; (oddparity((Nt >> 8) & 0xFF) == ((parity[2]) ^ oddparity((NtEnc >> 8) & 0xFF) ^ BIT(Ks1,0)))) ? 1 : 0;
@ -541,7 +473,7 @@ void MifareNested(uint32_t arg0, uint32_t arg1, uint32_t calibrate, uint8_t *dat
struct Crypto1State mpcs = {0, 0}; struct Crypto1State mpcs = {0, 0};
struct Crypto1State *pcs; struct Crypto1State *pcs;
pcs = &mpcs; pcs = &mpcs;
uint8_t* receivedAnswer = get_bigbufptr_recvrespbuf(); uint8_t* receivedAnswer = get_bigbufptr_recvrespbuf();
uint32_t auth1_time, auth2_time; uint32_t auth1_time, auth2_time;
static uint16_t delta_time; static uint16_t delta_time;
@ -599,7 +531,7 @@ void MifareNested(uint32_t arg0, uint32_t arg1, uint32_t calibrate, uint8_t *dat
}; };
nttmp = prng_successor(nt1, 100); //NXP Mifare is typical around 840,but for some unlicensed/compatible mifare card this can be 160 nttmp = prng_successor(nt1, 100); //NXP Mifare is typical around 840,but for some unlicensed/compatible mifare card this can be 160
for (i = 141; i < 1200; i++) { for (i = 101; i < 1200; i++) {
nttmp = prng_successor(nttmp, 1); nttmp = prng_successor(nttmp, 1);
if (nttmp == nt2) break; if (nttmp == nt2) break;
} }
@ -617,7 +549,7 @@ void MifareNested(uint32_t arg0, uint32_t arg1, uint32_t calibrate, uint8_t *dat
} }
} }
if (rtr <= 1) return; if (rtr <= 1) return;
davg = (davg + (rtr - 1)/2) / (rtr - 1); davg = (davg + (rtr - 1)/2) / (rtr - 1);
@ -636,15 +568,6 @@ void MifareNested(uint32_t arg0, uint32_t arg1, uint32_t calibrate, uint8_t *dat
// get crypted nonces for target sector // get crypted nonces for target sector
for(i=0; i < 2; i++) { // look for exactly two different nonces for(i=0; i < 2; i++) { // look for exactly two different nonces
WDT_HIT();
if(BUTTON_PRESS()) {
DbpString("Nested: cancelled");
crypto1_destroy(pcs);
FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
LEDsoff();
return;
}
target_nt[i] = 0; target_nt[i] = 0;
while(target_nt[i] == 0) { // continue until we have an unambiguous nonce while(target_nt[i] == 0) { // continue until we have an unambiguous nonce
@ -941,7 +864,7 @@ void MifareCSetBlock(uint32_t arg0, uint32_t arg1, uint32_t arg2, uint8_t *datai
uint8_t d_block[18] = {0x00}; uint8_t d_block[18] = {0x00};
uint32_t cuid; uint32_t cuid;
uint8_t* receivedAnswer = get_bigbufptr_recvrespbuf(); uint8_t *receivedAnswer = get_bigbufptr_recvrespbuf();
uint8_t *receivedAnswerPar = receivedAnswer + MAX_FRAME_SIZE; uint8_t *receivedAnswerPar = receivedAnswer + MAX_FRAME_SIZE;
// reset FPGA and LED // reset FPGA and LED
@ -1148,75 +1071,3 @@ void MifareCIdent(){
// //
// DESFIRE // DESFIRE
// //
void Mifare_DES_Auth1(uint8_t arg0, uint8_t *datain){
// variables
byte_t isOK = 0;
byte_t dataoutbuf[16];
uint8_t uid[10];
uint32_t cuid;
// clear trace
iso14a_clear_trace();
iso14443a_setup(FPGA_HF_ISO14443A_READER_LISTEN);
LED_A_ON();
LED_B_OFF();
LED_C_OFF();
if(!iso14443a_select_card(uid, NULL, &cuid)) {
if (MF_DBGLEVEL >= 1) Dbprintf("Can't select card, something went wrong before auth");
};
if(mifare_desfire_des_auth1(cuid, dataoutbuf)){
if (MF_DBGLEVEL >= 1) Dbprintf("Authentication part1: Fail.");
}
isOK=1;
if (MF_DBGLEVEL >= 2) DbpString("AUTH 1 FINISHED");
LED_B_ON();
cmd_send(CMD_ACK,isOK,cuid,0,dataoutbuf,11);
LED_B_OFF();
// Thats it...
//FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
LEDsoff();
}
void Mifare_DES_Auth2(uint32_t arg0, uint8_t *datain){
// params
uint32_t cuid = arg0;
uint8_t key[16]={0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
// variables
byte_t isOK = 0;
byte_t dataoutbuf[16];
memcpy(key, datain, 16);
// clear trace
//iso14a_clear_trace();
//iso14443a_setup(FPGA_HF_ISO14443A_READER_LISTEN);
LED_A_ON();
LED_B_OFF();
LED_C_OFF();
// Dbprintf("Sending %02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x",
// key[0],key[1],key[2],key[3],key[4],key[5],key[6],key[7],key[8],
// key[9],key[10],key[11],key[12],key[13],key[14],key[15]);
if(mifare_desfire_des_auth2(cuid, key, dataoutbuf)){
if (MF_DBGLEVEL >= 1) Dbprintf("Authentication part2: Fail...");
}
isOK=1;
if (MF_DBGLEVEL >= 2) DbpString("AUTH 2 FINISHED");
LED_B_ON();
cmd_send(CMD_ACK,isOK,0,0,dataoutbuf,12);
LED_B_OFF();
// Thats it...
FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
LEDsoff();
}

View file

@ -13,15 +13,16 @@
#ifndef __MIFARECMD_H #ifndef __MIFARECMD_H
#define __MIFARECMD_H #define __MIFARECMD_H
#include "../include/proxmark3.h" #include "proxmark3.h"
#include "apps.h" #include "apps.h"
#include "util.h" #include "util.h"
#include "string.h" #include "string.h"
#include "../common/iso14443crc.h" #include "iso14443crc.h"
#include "iso14443a.h" #include "iso14443a.h"
#include "crapto1.h" #include "crapto1.h"
#include "mifareutil.h" #include "mifareutil.h"
#include "../include/common.h" #include "common.h"
#endif #endif

View file

@ -1,521 +0,0 @@
#include "mifaredesfire.h"
#include "des.h"
#define MAX_APPLICATION_COUNT 28
#define MAX_FILE_COUNT 16
#define MAX_DESFIRE_FRAME_SIZE 60
#define NOT_YET_AUTHENTICATED 255
#define FRAME_PAYLOAD_SIZE (MAX_DESFIRE_FRAME_SIZE - 5)
#define RECEIVE_SIZE 64
// the block number for the ISO14443-4 PCB
uint8_t pcb_blocknum = 0;
// Deselect card by sending a s-block. the crc is precalced for speed
static uint8_t deselect_cmd[] = {0xc2,0xe0,0xb4};
//static uint8_t __msg[MAX_FRAME_SIZE] = { 0x0A, 0x00, 0x00, /* ..., */ 0x00 };
/* PCB CID CMD PAYLOAD */
//static uint8_t __res[MAX_FRAME_SIZE];
bool InitDesfireCard(){
// Make sure it is off.
// FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
// SpinDelay(300);
byte_t cardbuf[USB_CMD_DATA_SIZE];
memset(cardbuf,0,sizeof(cardbuf));
iso14a_card_select_t *card = (iso14a_card_select_t*)cardbuf;
iso14a_set_tracing(TRUE);
iso14443a_setup(FPGA_HF_ISO14443A_READER_LISTEN);
int len = iso14443a_select_card(NULL,card,NULL);
if (!len) {
if (MF_DBGLEVEL >= 1) Dbprintf("Can't select card");
OnError();
return false;
}
return true;
}
// ARG0 flag enums
enum {
NONE = 0x00,
INIT = 0x01,
DISCONNECT = 0x02,
CLEARTRACE = 0x04,
BAR = 0x08,
} CmdOptions ;
void MifareSendCommand(uint8_t arg0, uint8_t arg1, uint8_t *datain){
/* ARG0 contains flags.
0x01 = init card.
0x02 = Disconnect
0x03
*/
uint8_t flags = arg0;
size_t datalen = arg1;
uint8_t resp[RECEIVE_SIZE];
memset(resp,0,sizeof(resp));
if (MF_DBGLEVEL >= 4) {
Dbprintf(" flags : %02X", flags);
Dbprintf(" len : %02X", datalen);
print_result(" RX : ", datain, datalen);
}
if ( flags & CLEARTRACE ){
iso14a_clear_trace();
}
if ( flags & INIT ){
if ( !InitDesfireCard() )
return;
}
int len = DesfireAPDU(datain, datalen, resp);
if (MF_DBGLEVEL >= 4) {
print_result("ERR <--: ", resp, len);
}
if ( !len ) {
OnError();
return;
}
// reset the pcb_blocknum,
pcb_blocknum = 0;
if ( flags & DISCONNECT ){
OnSuccess();
}
cmd_send(CMD_ACK,1,len,0,resp,len);
}
void MifareDesfireGetInformation(){
int len = 0;
uint8_t resp[USB_CMD_DATA_SIZE];
uint8_t dataout[USB_CMD_DATA_SIZE];
byte_t cardbuf[USB_CMD_DATA_SIZE];
memset(resp,0,sizeof(resp));
memset(dataout,0, sizeof(dataout));
memset(cardbuf,0,sizeof(cardbuf));
/*
1 = PCB 1
2 = cid 2
3 = desfire command 3
4-5 = crc 4 key
5-6 crc
PCB == 0x0A because sending CID byte.
CID == 0x00 first card?
*/
iso14a_clear_trace();
iso14a_set_tracing(TRUE);
iso14443a_setup(FPGA_HF_ISO14443A_READER_LISTEN);
// card select - information
iso14a_card_select_t *card = (iso14a_card_select_t*)cardbuf;
byte_t isOK = iso14443a_select_card(NULL, card, NULL);
if ( isOK == 0) {
if (MF_DBGLEVEL >= 1) {
Dbprintf("Can't select card");
}
OnError();
return;
}
memcpy(dataout,card->uid,7);
LED_A_ON();
LED_B_OFF();
LED_C_OFF();
uint8_t cmd[] = {GET_VERSION};
size_t cmd_len = sizeof(cmd);
len = DesfireAPDU(cmd, cmd_len, resp);
if ( !len ) {
print_result("ERROR <--: ", resp, len);
OnError();
return;
}
LED_A_OFF();
LED_B_ON();
memcpy(dataout+7,resp+3,7);
// ADDITION_FRAME 1
cmd[0] = ADDITIONAL_FRAME;
len = DesfireAPDU(cmd, cmd_len, resp);
if ( !len ) {
print_result("ERROR <--: ", resp, len);
OnError();
return;
}
LED_B_OFF();
LED_C_ON();
memcpy(dataout+7+7,resp+3,7);
// ADDITION_FRAME 2
len = DesfireAPDU(cmd, cmd_len, resp);
if ( !len ) {
print_result("ERROR <--: ", resp, len);
OnError();
return;
}
memcpy(dataout+7+7+7,resp+3,14);
cmd_send(CMD_ACK,1,0,0,dataout,sizeof(dataout));
// reset the pcb_blocknum,
pcb_blocknum = 0;
OnSuccess();
}
void MifareDES_Auth1(uint8_t mode, uint8_t algo, uint8_t keyno, uint8_t *datain){
int len = 0;
//uint8_t PICC_MASTER_KEY8[8] = { 0x40,0x41,0x42,0x43,0x44,0x45,0x46,0x47};
uint8_t PICC_MASTER_KEY16[16] = { 0x40,0x41,0x42,0x43,0x44,0x45,0x46,0x47,0x48,0x49,0x4a,0x4b,0x4c,0x4d,0x4e,0x4f };
uint8_t null_key_data8[8] = {0x00};
//uint8_t null_key_data16[16] = {0x00};
//uint8_t new_key_data8[8] = { 0x00,0x11,0x22,0x33,0x44,0x55,0x66,0x77};
//uint8_t new_key_data16[16] = { 0x00,0x11,0x22,0x33,0x44,0x55,0x66,0x77,0x88,0x99,0xAA,0xBB,0xCC,0xDD,0xEE,0xFF};
//uint8_t* bigbuffer = get_bigbufptr_recvrespbuf();
uint8_t resp[256] = {0x00};
uint8_t IV[16] = {0x00};
size_t datalen = datain[0];
uint8_t cmd[40] = {0x00};
uint8_t encRndB[16] = {0x00};
uint8_t decRndB[16] = {0x00};
uint8_t nonce[16] = {0x00};
uint8_t both[32] = {0x00};
uint8_t encBoth[32] = {0x00};
InitDesfireCard();
LED_A_ON();
LED_B_OFF();
LED_C_OFF();
// 3 olika sätt att authenticera. AUTH (CRC16) , AUTH_ISO (CRC32) , AUTH_AES (CRC32)
// 4 olika crypto algo DES, 3DES, 3K3DES, AES
// 3 olika kommunikations sätt, PLAIN,MAC,CRYPTO
// des, nyckel 0,
switch (mode){
case 1:{
if (algo == 1) {
uint8_t keybytes[8];
uint8_t RndA[8] = {0x00};
uint8_t RndB[8] = {0x00};
if (datain[1] == 0xff){
memcpy(keybytes,null_key_data8,8);
} else{
memcpy(keybytes, datain+1, datalen);
}
struct desfire_key defaultkey = {0};
desfirekey_t key = &defaultkey;
Desfire_des_key_new(keybytes, key);
cmd[0] = AUTHENTICATE;
cmd[1] = keyno; //keynumber
len = DesfireAPDU(cmd, 2, resp);
if ( !len ) {
if (MF_DBGLEVEL >= 1) {
DbpString("Authentication failed. Card timeout.");
}
OnError();
return;
}
if ( resp[2] == 0xaf ){
} else {
DbpString("Authetication failed. Invalid key number.");
OnError();
return;
}
memcpy( encRndB, resp+3, 8);
des_dec(&decRndB, &encRndB, key->data);
memcpy(RndB, decRndB, 8);
rol(decRndB,8);
// This should be random
uint8_t decRndA[8] = {0x00};
memcpy(RndA, decRndA, 8);
uint8_t encRndA[8] = {0x00};
des_dec(&encRndA, &decRndA, key->data);
memcpy(both, encRndA, 8);
for (int x = 0; x < 8; x++) {
decRndB[x] = decRndB[x] ^ encRndA[x];
}
des_dec(&encRndB, &decRndB, key->data);
memcpy(both + 8, encRndB, 8);
cmd[0] = ADDITIONAL_FRAME;
memcpy(cmd+1, both, 16 );
len = DesfireAPDU(cmd, 17, resp);
if ( !len ) {
if (MF_DBGLEVEL >= 1) {
DbpString("Authentication failed. Card timeout.");
}
OnError();
return;
}
if ( resp[2] == 0x00 ){
struct desfire_key sessionKey = {0};
desfirekey_t skey = &sessionKey;
Desfire_session_key_new( RndA, RndB , key, skey );
//print_result("SESSION : ", skey->data, 8);
memcpy(encRndA, resp+3, 8);
des_dec(&encRndA, &encRndA, key->data);
rol(decRndA,8);
for (int x = 0; x < 8; x++) {
if (decRndA[x] != encRndA[x]) {
DbpString("Authetication failed. Cannot varify PICC.");
OnError();
return;
}
}
//Change the selected key to a new value.
/*
cmd[0] = CHANGE_KEY;
cmd[1] = keyno;
uint8_t newKey[16] = {0x00,0x11,0x22,0x33,0x44,0x55,0x66,0x77,0x00,0x11,0x22,0x33,0x44,0x55,0x66,0x77};
uint8_t first, second;
uint8_t buff1[8] = {0x00};
uint8_t buff2[8] = {0x00};
uint8_t buff3[8] = {0x00};
memcpy(buff1,newKey, 8);
memcpy(buff2,newKey + 8, 8);
ComputeCrc14443(CRC_14443_A, newKey, 16, &first, &second);
memcpy(buff3, &first, 1);
memcpy(buff3 + 1, &second, 1);
des_dec(&buff1, &buff1, skey->data);
memcpy(cmd+2,buff1,8);
for (int x = 0; x < 8; x++) {
buff2[x] = buff2[x] ^ buff1[x];
}
des_dec(&buff2, &buff2, skey->data);
memcpy(cmd+10,buff2,8);
for (int x = 0; x < 8; x++) {
buff3[x] = buff3[x] ^ buff2[x];
}
des_dec(&buff3, &buff3, skey->data);
memcpy(cmd+18,buff3,8);
// The command always times out on the first attempt, this will retry until a response
// is recieved.
len = 0;
while(!len) {
len = DesfireAPDU(cmd,26,resp);
}
*/
OnSuccess();
cmd_send(CMD_ACK,1,0,0,skey->data,8);
} else {
DbpString("Authetication failed.");
OnError();
return;
}
}
}
break;
case 2:
//SendDesfireCommand(AUTHENTICATE_ISO, &keyno, resp);
break;
case 3:{
//defaultkey
uint8_t keybytes[16];
if (datain[1] == 0xff){
memcpy(keybytes,PICC_MASTER_KEY16,16);
} else{
memcpy(keybytes, datain+1, datalen);
}
struct desfire_key defaultkey = {0};
desfirekey_t key = &defaultkey;
Desfire_aes_key_new( keybytes, key);
AesCtx ctx;
if ( AesCtxIni(&ctx, IV, key->data, KEY128, CBC) < 0 ){
if( MF_DBGLEVEL >= 4) {
Dbprintf("AES context failed to init");
}
OnError();
return;
}
cmd[0] = AUTHENTICATE_AES;
cmd[1] = 0x00; //keynumber
len = DesfireAPDU(cmd, 2, resp);
if ( !len ) {
if (MF_DBGLEVEL >= 1) {
DbpString("Authentication failed. Card timeout.");
}
OnError();
return;
}
memcpy( encRndB, resp+3, 16);
// dekryptera tagnonce.
AesDecrypt(&ctx, encRndB, decRndB, 16);
rol(decRndB,16);
memcpy(both, nonce,16);
memcpy(both+16, decRndB ,16 );
AesEncrypt(&ctx, both, encBoth, 32 );
cmd[0] = ADDITIONAL_FRAME;
memcpy(cmd+1, encBoth, 32 );
len = DesfireAPDU(cmd, 33, resp); // 1 + 32 == 33
if ( !len ) {
if (MF_DBGLEVEL >= 1) {
DbpString("Authentication failed. Card timeout.");
}
OnError();
return;
}
if ( resp[2] == 0x00 ){
// Create AES Session key
struct desfire_key sessionKey = {0};
desfirekey_t skey = &sessionKey;
Desfire_session_key_new( nonce, decRndB , key, skey );
print_result("SESSION : ", skey->data, 16);
} else {
DbpString("Authetication failed.");
OnError();
return;
}
break;
}
}
OnSuccess();
cmd_send(CMD_ACK,1,len,0,resp,len);
}
// 3 olika ISO sätt att skicka data till DESFIRE (direkt, inkapslat, inkapslat ISO)
// cmd = cmd bytes to send
// cmd_len = length of cmd
// dataout = pointer to response data array
int DesfireAPDU(uint8_t *cmd, size_t cmd_len, uint8_t *dataout){
size_t len = 0;
size_t wrappedLen = 0;
uint8_t wCmd[USB_CMD_DATA_SIZE] = {0};
uint8_t *resp = ((uint8_t *)BigBuf) + RECV_RESP_OFFSET;
uint8_t *resp_par = ((uint8_t *)BigBuf) + RECV_RESP_PAR_OFFSET;
wrappedLen = CreateAPDU( cmd, cmd_len, wCmd);
if (MF_DBGLEVEL >= 4) {
print_result("WCMD <--: ", wCmd, wrappedLen);
}
ReaderTransmit( wCmd, wrappedLen, NULL);
len = ReaderReceive(resp, resp_par);
if( len == 0x00 ){
if (MF_DBGLEVEL >= 4) {
Dbprintf("fukked");
}
return FALSE; //DATA LINK ERROR
}
// if we received an I- or R(ACK)-Block with a block number equal to the
// current block number, toggle the current block number
else if (len >= 4 // PCB+CID+CRC = 4 bytes
&& ((resp[0] & 0xC0) == 0 // I-Block
|| (resp[0] & 0xD0) == 0x80) // R-Block with ACK bit set to 0
&& (resp[0] & 0x01) == pcb_blocknum) // equal block numbers
{
pcb_blocknum ^= 1; //toggle next block
}
memcpy(dataout, resp, len);
return len;
}
// CreateAPDU
size_t CreateAPDU( uint8_t *datain, size_t len, uint8_t *dataout){
size_t cmdlen = MIN(len+4, USB_CMD_DATA_SIZE-1);
uint8_t cmd[cmdlen];
memset(cmd, 0, cmdlen);
cmd[0] = 0x0A; // 0x0A = skicka cid, 0x02 = ingen cid. Särskilda bitar //
cmd[0] |= pcb_blocknum; // OR the block number into the PCB
cmd[1] = 0x00; // CID: 0x00 //TODO: allow multiple selected cards
memcpy(cmd+2, datain, len);
AppendCrc14443a(cmd, len+2);
memcpy(dataout, cmd, cmdlen);
return cmdlen;
}
// crc_update(&desfire_crc32, 0, 1); /* CMD_WRITE */
// crc_update(&desfire_crc32, addr, addr_sz);
// crc_update(&desfire_crc32, byte, 8);
// uint32_t crc = crc_finish(&desfire_crc32);
void OnSuccess(){
pcb_blocknum = 0;
ReaderTransmit(deselect_cmd, 3 , NULL);
FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
LEDsoff();
}
void OnError(){
pcb_blocknum = 0;
ReaderTransmit(deselect_cmd, 3 , NULL);
FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
cmd_send(CMD_ACK,0,0,0,0,0);
LEDsoff();
}

View file

@ -1,15 +0,0 @@
#ifndef __MIFAREDESFIRE_H
#define __MIFAREDESFIRE_H
#include "../include/proxmark3.h"
#include "apps.h"
#include "util.h"
#include "string.h"
#include "../common/iso14443crc.h"
#include "iso14443a.h"
#include "desfire_key.h"
#include "mifareutil.h"
#include "../include/common.h"
#endif

View file

@ -11,16 +11,16 @@
#ifndef __MIFARESNIFF_H #ifndef __MIFARESNIFF_H
#define __MIFARESNIFF_H #define __MIFARESNIFF_H
#include "../include/proxmark3.h" #include "proxmark3.h"
#include "apps.h" #include "apps.h"
#include "util.h" #include "util.h"
#include "string.h" #include "string.h"
#include "../common/iso14443crc.h" #include "iso14443crc.h"
#include "iso14443a.h" #include "iso14443a.h"
#include "crapto1.h" #include "crapto1.h"
#include "mifareutil.h" #include "mifareutil.h"
#include "../include/common.h" #include "common.h"
#define SNF_INIT 0 #define SNF_INIT 0
#define SNF_NO_FIELD 1 #define SNF_NO_FIELD 1

View file

@ -9,12 +9,12 @@
// Work with mifare cards. // Work with mifare cards.
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
#include "../include/proxmark3.h" #include "proxmark3.h"
#include "apps.h" #include "apps.h"
#include "util.h" #include "util.h"
#include "string.h" #include "string.h"
#include "../common/iso14443crc.h" #include "iso14443crc.h"
#include "iso14443a.h" #include "iso14443a.h"
#include "crapto1.h" #include "crapto1.h"
#include "mifareutil.h" #include "mifareutil.h"
@ -76,7 +76,7 @@ uint8_t mf_crypto1_encrypt4bit(struct Crypto1State *pcs, uint8_t data) {
} }
// send commands // send commands
int mifare_sendcmd_short(struct Crypto1State *pcs, uint8_t crypted, uint8_t cmd, uint8_t data, uint8_t *answer, uint8_t *answer_parity, uint32_t *timing) int mifare_sendcmd_short(struct Crypto1State *pcs, uint8_t crypted, uint8_t cmd, uint8_t data, uint8_t* answer, uint8_t *answer_parity, uint32_t *timing)
{ {
return mifare_sendcmd_shortex(pcs, crypted, cmd, data, answer, answer_parity, timing); return mifare_sendcmd_shortex(pcs, crypted, cmd, data, answer, answer_parity, timing);
} }
@ -84,7 +84,7 @@ int mifare_sendcmd_short(struct Crypto1State *pcs, uint8_t crypted, uint8_t cmd,
int mifare_sendcmd_short_special(struct Crypto1State *pcs, uint8_t crypted, uint8_t cmd, uint8_t* data, uint8_t* answer, uint8_t *answer_parity, uint32_t *timing) int mifare_sendcmd_short_special(struct Crypto1State *pcs, uint8_t crypted, uint8_t cmd, uint8_t* data, uint8_t* answer, uint8_t *answer_parity, uint32_t *timing)
{ {
uint8_t dcmd[8]; uint8_t dcmd[8];
dcmd[0] = cmd; dcmd[0] = cmd;
dcmd[1] = data[0]; dcmd[1] = data[0];
dcmd[2] = data[1]; dcmd[2] = data[1];
dcmd[3] = data[2]; dcmd[3] = data[2];
@ -93,30 +93,10 @@ int mifare_sendcmd_short_special(struct Crypto1State *pcs, uint8_t crypted, uint
AppendCrc14443a(dcmd, 6); AppendCrc14443a(dcmd, 6);
ReaderTransmit(dcmd, sizeof(dcmd), NULL); ReaderTransmit(dcmd, sizeof(dcmd), NULL);
int len = ReaderReceive(answer, answer_parity); int len = ReaderReceive(answer, answer_parity);
if(!len) { if(!len)
if (MF_DBGLEVEL >= 1) Dbprintf("Authentication failed. Card timeout."); {
return 2; if (MF_DBGLEVEL >= 1) Dbprintf("Authentication failed. Card timeout.");
} return 2;
return len;
}
int mifare_sendcmd_short_mfucauth(struct Crypto1State *pcs, uint8_t crypted, uint8_t cmd, uint8_t *data, uint8_t *answer, uint8_t *answer_parity, uint32_t *timing)
{
uint8_t dcmd[19];
int len;
dcmd[0] = cmd;
memcpy(dcmd+1,data,16);
AppendCrc14443a(dcmd, 17);
ReaderTransmit(dcmd, sizeof(dcmd), timing);
len = ReaderReceive(answer, answer_parity);
if(!len) {
if (MF_DBGLEVEL >= 1) Dbprintf("Authentication failed. Card timeout.");
len = ReaderReceive(answer,answer_parity);
}
if(len==1) {
if (MF_DBGLEVEL >= 1) Dbprintf("NAK - Authentication failed.");
return 1;
} }
return len; return len;
} }
@ -175,7 +155,7 @@ int mifare_classic_auth(struct Crypto1State *pcs, uint32_t uid, uint8_t blockNo,
return mifare_classic_authex(pcs, uid, blockNo, keyType, ui64Key, isNested, NULL, NULL); return mifare_classic_authex(pcs, uid, blockNo, keyType, ui64Key, isNested, NULL, NULL);
} }
int mifare_classic_authex(struct Crypto1State *pcs, uint32_t uid, uint8_t blockNo, uint8_t keyType, uint64_t ui64Key, uint8_t isNested, uint32_t * ntptr, uint32_t *timing) int mifare_classic_authex(struct Crypto1State *pcs, uint32_t uid, uint8_t blockNo, uint8_t keyType, uint64_t ui64Key, uint8_t isNested, uint32_t *ntptr, uint32_t *timing)
{ {
// variables // variables
int len; int len;
@ -186,7 +166,7 @@ int mifare_classic_authex(struct Crypto1State *pcs, uint32_t uid, uint8_t blockN
uint32_t nt, ntpp; // Supplied tag nonce uint32_t nt, ntpp; // Supplied tag nonce
uint8_t mf_nr_ar[] = { 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 }; uint8_t mf_nr_ar[] = { 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 };
uint8_t* receivedAnswer = get_bigbufptr_recvrespbuf(); uint8_t *receivedAnswer = get_bigbufptr_recvrespbuf();
uint8_t *receivedAnswerPar = receivedAnswer + MAX_FRAME_SIZE; uint8_t *receivedAnswerPar = receivedAnswer + MAX_FRAME_SIZE;
// Transmit MIFARE_CLASSIC_AUTH // Transmit MIFARE_CLASSIC_AUTH
@ -298,56 +278,6 @@ int mifare_classic_readblock(struct Crypto1State *pcs, uint32_t uid, uint8_t blo
return 0; return 0;
} }
int mifare_ultra_auth1(uint32_t uid, uint8_t *blockData){
// variables
uint16_t len;
uint8_t* receivedAnswer = get_bigbufptr_recvrespbuf();
uint8_t* receivedAnswerPar = receivedAnswer + MAX_FRAME_SIZE;
// command MIFARE_CLASSIC_READBLOCK
len = mifare_sendcmd_short(NULL, 1, 0x1A, 0x00, receivedAnswer,receivedAnswerPar ,NULL);
if (len == 1) {
if (MF_DBGLEVEL >= 1) Dbprintf("Cmd Error: %02x", receivedAnswer[0]);
return 1;
}
if (len == 11) {
if (MF_DBGLEVEL >= 1) Dbprintf("Auth1 Resp: %02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x",
receivedAnswer[0],receivedAnswer[1],receivedAnswer[2],receivedAnswer[3],receivedAnswer[4],
receivedAnswer[5],receivedAnswer[6],receivedAnswer[7],receivedAnswer[8],receivedAnswer[9],
receivedAnswer[10]);
memcpy(blockData, receivedAnswer, 11);
return 0;
}
//else something went wrong???
return 1;
}
int mifare_ultra_auth2(uint32_t uid, uint8_t *key, uint8_t *blockData){
// variables
uint16_t len;
uint8_t* receivedAnswer = get_bigbufptr_recvrespbuf();
uint8_t* receivedAnswerPar = receivedAnswer + MAX_FRAME_SIZE;
// command MIFARE_CLASSIC_READBLOCK
len = mifare_sendcmd_short_mfucauth(NULL, 1, 0xAF, key, receivedAnswer, receivedAnswerPar, NULL);
if (len == 1) {
if (MF_DBGLEVEL >= 1) Dbprintf("Cmd Error: %02x", receivedAnswer[0]);
return 1;
}
if (len == 11){
if (MF_DBGLEVEL >= 1) Dbprintf("Auth2 Resp: %02x%02x%02x%02x%02x%02x%02x%02x%02x%02x",
receivedAnswer[0],receivedAnswer[1],receivedAnswer[2],receivedAnswer[3],receivedAnswer[4],
receivedAnswer[5],receivedAnswer[6],receivedAnswer[7],receivedAnswer[8],receivedAnswer[9],
receivedAnswer[10]);
memcpy(blockData, receivedAnswer, 11);
return 0;
}
//something went wrong?
return 1;
}
int mifare_ultra_readblock(uint32_t uid, uint8_t blockNo, uint8_t *blockData) int mifare_ultra_readblock(uint32_t uid, uint8_t blockNo, uint8_t *blockData)
{ {
// variables // variables
@ -430,20 +360,20 @@ int mifare_classic_writeblock(struct Crypto1State *pcs, uint32_t uid, uint8_t bl
int mifare_ultra_writeblock(uint32_t uid, uint8_t blockNo, uint8_t *blockData) int mifare_ultra_writeblock(uint32_t uid, uint8_t blockNo, uint8_t *blockData)
{ {
// variables // variables
uint16_t len; uint16_t len;
uint8_t par[3] = {0}; // enough for 18 parity bits uint8_t par[3] = {0}; // enough for 18 parity bits
uint8_t d_block[18]; uint8_t d_block[18];
uint8_t* receivedAnswer = get_bigbufptr_recvrespbuf(); uint8_t* receivedAnswer = get_bigbufptr_recvrespbuf();
uint8_t* receivedAnswerPar = receivedAnswer + MAX_FRAME_SIZE; uint8_t* receivedAnswerPar = receivedAnswer + MAX_FRAME_SIZE;
// command MIFARE_CLASSIC_WRITEBLOCK // command MIFARE_CLASSIC_WRITEBLOCK
len = mifare_sendcmd_short(NULL, true, 0xA0, blockNo, receivedAnswer, receivedAnswerPar, NULL); len = mifare_sendcmd_short(NULL, true, 0xA0, blockNo, receivedAnswer, receivedAnswerPar, NULL);
if ((len != 1) || (receivedAnswer[0] != 0x0A)) { // 0x0a - ACK if ((len != 1) || (receivedAnswer[0] != 0x0A)) { // 0x0a - ACK
if (MF_DBGLEVEL >= 1) Dbprintf("Cmd Addr Error: %02x", receivedAnswer[0]); if (MF_DBGLEVEL >= 1) Dbprintf("Cmd Addr Error: %02x", receivedAnswer[0]);
return 1; return 1;
} }
memset(d_block,'\0',18); memset(d_block,'\0',18);
memcpy(d_block, blockData, 16); memcpy(d_block, blockData, 16);
@ -451,13 +381,13 @@ int mifare_ultra_writeblock(uint32_t uid, uint8_t blockNo, uint8_t *blockData)
ReaderTransmitPar(d_block, sizeof(d_block), par, NULL); ReaderTransmitPar(d_block, sizeof(d_block), par, NULL);
// Receive the response // Receive the response
len = ReaderReceive(receivedAnswer, receivedAnswerPar); len = ReaderReceive(receivedAnswer, receivedAnswerPar);
if ((len != 1) || (receivedAnswer[0] != 0x0A)) { // 0x0a - ACK if ((len != 1) || (receivedAnswer[0] != 0x0A)) { // 0x0a - ACK
if (MF_DBGLEVEL >= 1) Dbprintf("Cmd Data Error: %02x %d", receivedAnswer[0],len); if (MF_DBGLEVEL >= 1) Dbprintf("Cmd Data Error: %02x %d", receivedAnswer[0],len);
return 2; return 2;
} }
return 0; return 0;
} }
@ -465,8 +395,8 @@ int mifare_ultra_writeblock(uint32_t uid, uint8_t blockNo, uint8_t *blockData)
int mifare_ultra_special_writeblock(uint32_t uid, uint8_t blockNo, uint8_t *blockData) int mifare_ultra_special_writeblock(uint32_t uid, uint8_t blockNo, uint8_t *blockData)
{ {
uint16_t len; uint16_t len;
uint8_t d_block[8]; uint8_t d_block[8];
uint8_t* receivedAnswer = get_bigbufptr_recvrespbuf(); uint8_t *receivedAnswer = get_bigbufptr_recvrespbuf();
uint8_t *receivedAnswerPar = receivedAnswer + MAX_FRAME_SIZE; uint8_t *receivedAnswerPar = receivedAnswer + MAX_FRAME_SIZE;
// command MIFARE_CLASSIC_WRITEBLOCK // command MIFARE_CLASSIC_WRITEBLOCK
@ -478,17 +408,17 @@ int mifare_ultra_special_writeblock(uint32_t uid, uint8_t blockNo, uint8_t *bloc
//i know the data send here is correct //i know the data send here is correct
len = mifare_sendcmd_short_special(NULL, 1, 0xA2, d_block, receivedAnswer, receivedAnswerPar, NULL); len = mifare_sendcmd_short_special(NULL, 1, 0xA2, d_block, receivedAnswer, receivedAnswerPar, NULL);
if (receivedAnswer[0] != 0x0A) { // 0x0a - ACK if (receivedAnswer[0] != 0x0A) { // 0x0a - ACK
if (MF_DBGLEVEL >= 1) Dbprintf("Cmd Send Error: %02x %d", receivedAnswer[0],len); if (MF_DBGLEVEL >= 1) Dbprintf("Cmd Send Error: %02x %d", receivedAnswer[0],len);
return 1; return 1;
} }
return 0; return 0;
} }
int mifare_classic_halt(struct Crypto1State *pcs, uint32_t uid) int mifare_classic_halt(struct Crypto1State *pcs, uint32_t uid)
{ {
uint16_t len; uint16_t len;
uint8_t* receivedAnswer = get_bigbufptr_recvrespbuf(); uint8_t *receivedAnswer = get_bigbufptr_recvrespbuf();
uint8_t *receivedAnswerPar = receivedAnswer + MAX_FRAME_SIZE; uint8_t *receivedAnswerPar = receivedAnswer + MAX_FRAME_SIZE;
len = mifare_sendcmd_short(pcs, pcs == NULL ? false:true, 0x50, 0x00, receivedAnswer, receivedAnswerPar, NULL); len = mifare_sendcmd_short(pcs, pcs == NULL ? false:true, 0x50, 0x00, receivedAnswer, receivedAnswerPar, NULL);
@ -503,7 +433,7 @@ int mifare_classic_halt(struct Crypto1State *pcs, uint32_t uid)
int mifare_ultra_halt(uint32_t uid) int mifare_ultra_halt(uint32_t uid)
{ {
uint16_t len; uint16_t len;
uint8_t* receivedAnswer = get_bigbufptr_recvrespbuf(); uint8_t *receivedAnswer = get_bigbufptr_recvrespbuf();
uint8_t *receivedAnswerPar = receivedAnswer + MAX_FRAME_SIZE; uint8_t *receivedAnswerPar = receivedAnswer + MAX_FRAME_SIZE;
len = mifare_sendcmd_short(NULL, true, 0x50, 0x00, receivedAnswer, receivedAnswerPar, NULL); len = mifare_sendcmd_short(NULL, true, 0x50, 0x00, receivedAnswer, receivedAnswerPar, NULL);
@ -623,91 +553,3 @@ void emlClearMem(void) {
emlSetMem((uint8_t *)uid, 0, 1); emlSetMem((uint8_t *)uid, 0, 1);
return; return;
} }
//
//DESFIRE
//
int mifare_sendcmd_special(struct Crypto1State *pcs, uint8_t crypted, uint8_t cmd, uint8_t* data, uint8_t* answer, uint8_t *answer_parity, uint32_t *timing)
{
uint8_t dcmd[5] = {0x00};
dcmd[0] = cmd;
memcpy(dcmd+1,data,2);
AppendCrc14443a(dcmd, 3);
ReaderTransmit(dcmd, sizeof(dcmd), NULL);
int len = ReaderReceive(answer, answer_parity);
if(!len) {
if (MF_DBGLEVEL >= 1) Dbprintf("Authentication failed. Card timeout.");
return 2;
}
return len;
}
int mifare_sendcmd_special2(struct Crypto1State *pcs, uint8_t crypted, uint8_t cmd, uint8_t* data, uint8_t* answer,uint8_t *answer_parity, uint32_t *timing)
{
uint8_t dcmd[20] = {0x00};
dcmd[0] = cmd;
memcpy(dcmd+1,data,17);
AppendCrc14443a(dcmd, 18);
ReaderTransmit(dcmd, sizeof(dcmd), NULL);
int len = ReaderReceive(answer, answer_parity);
if(!len){
if (MF_DBGLEVEL >= 1) Dbprintf("Authentication failed. Card timeout.");
return 2;
}
return len;
}
int mifare_desfire_des_auth1(uint32_t uid, uint8_t *blockData){
// variables
int len;
// load key, keynumber
uint8_t data[2]={0x0a, 0x00};
uint8_t* receivedAnswer = get_bigbufptr_recvrespbuf();
uint8_t *receivedAnswerPar = receivedAnswer + MAX_FRAME_SIZE;
// command MIFARE_CLASSIC_READBLOCK
len = mifare_sendcmd_special(NULL, 1, 0x02, data, receivedAnswer,receivedAnswerPar,NULL);
if (len == 1) {
if (MF_DBGLEVEL >= 1) Dbprintf("Cmd Error: %02x", receivedAnswer[0]);
return 1;
}
if (len == 12) {
if (MF_DBGLEVEL >= 1) Dbprintf("Auth1 Resp: %02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x",
receivedAnswer[0],receivedAnswer[1],receivedAnswer[2],receivedAnswer[3],receivedAnswer[4],
receivedAnswer[5],receivedAnswer[6],receivedAnswer[7],receivedAnswer[8],receivedAnswer[9],
receivedAnswer[10],receivedAnswer[11]);
memcpy(blockData, receivedAnswer, 12);
return 0;
}
return 1;
}
int mifare_desfire_des_auth2(uint32_t uid, uint8_t *key, uint8_t *blockData){
// variables
int len;
uint8_t data[17]={0xaf,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
memcpy(data+1,key,16);
uint8_t* receivedAnswer = get_bigbufptr_recvrespbuf();
uint8_t *receivedAnswerPar = receivedAnswer + MAX_FRAME_SIZE;
// command MIFARE_CLASSIC_READBLOCK
len = mifare_sendcmd_special2(NULL, 1, 0x03, data, receivedAnswer, receivedAnswerPar ,NULL);
if ((receivedAnswer[0] == 0x03)&&(receivedAnswer[1] == 0xae)) {
if (MF_DBGLEVEL >= 1) Dbprintf("Auth Error: %02x %02x", receivedAnswer[0], receivedAnswer[1]);
return 1;
}
if (len == 12){
if (MF_DBGLEVEL >= 1) Dbprintf("Auth2 Resp: %02x%02x%02x%02x%02x%02x%02x%02x%02x%02x",
receivedAnswer[0],receivedAnswer[1],receivedAnswer[2],receivedAnswer[3],receivedAnswer[4],
receivedAnswer[5],receivedAnswer[6],receivedAnswer[7],receivedAnswer[8],receivedAnswer[9],
receivedAnswer[10],receivedAnswer[11]);
memcpy(blockData, receivedAnswer, 12);
return 0;
}
return 1;
}

View file

@ -55,16 +55,12 @@ extern int MF_DBGLEVEL;
//functions //functions
uint8_t* mifare_get_bigbufptr(void); uint8_t* mifare_get_bigbufptr(void);
int mifare_sendcmd_short(struct Crypto1State *pcs, uint8_t crypted, uint8_t cmd, uint8_t data, uint8_t* answer, uint8_t *answer_parity, uint32_t *timing); int mifare_sendcmd_short(struct Crypto1State *pcs, uint8_t crypted, uint8_t cmd, uint8_t data, uint8_t* answer, uint8_t *answer_parity, uint32_t *timing);
int mifare_sendcmd_short_special(struct Crypto1State *pcs, uint8_t crypted, uint8_t cmd, uint8_t *data, uint8_t *answer, uint8_t *answer_parity, uint32_t *timing); int mifare_sendcmd_short_special(struct Crypto1State *pcs, uint8_t crypted, uint8_t cmd, uint8_t *data, uint8_t* answer, uint8_t *answer_parity, uint32_t *timing);
int mifare_sendcmd_short_mfucauth(struct Crypto1State *pcs, uint8_t crypted, uint8_t cmd, uint8_t *data, uint8_t *answer, uint8_t *answer_parity, uint32_t *timing);
int mifare_sendcmd_shortex(struct Crypto1State *pcs, uint8_t crypted, uint8_t cmd, uint8_t data, uint8_t* answer, uint8_t *answer_parity, uint32_t *timing); int mifare_sendcmd_shortex(struct Crypto1State *pcs, uint8_t crypted, uint8_t cmd, uint8_t data, uint8_t* answer, uint8_t *answer_parity, uint32_t *timing);
int mifare_classic_auth(struct Crypto1State *pcs, uint32_t uid, uint8_t blockNo, uint8_t keyType, uint64_t ui64Key, uint8_t isNested); int mifare_classic_auth(struct Crypto1State *pcs, uint32_t uid, uint8_t blockNo, uint8_t keyType, uint64_t ui64Key, uint8_t isNested);
int mifare_classic_authex(struct Crypto1State *pcs, uint32_t uid, uint8_t blockNo, uint8_t keyType, uint64_t ui64Key, uint8_t isNested, uint32_t * ntptr, uint32_t *timing); int mifare_classic_authex(struct Crypto1State *pcs, uint32_t uid, uint8_t blockNo, uint8_t keyType, uint64_t ui64Key, uint8_t isNested, uint32_t * ntptr, uint32_t *timing);
int mifare_classic_readblock(struct Crypto1State *pcs, uint32_t uid, uint8_t blockNo, uint8_t *blockData); int mifare_classic_readblock(struct Crypto1State *pcs, uint32_t uid, uint8_t blockNo, uint8_t *blockData);
int mifare_ultra_auth1(uint32_t cuid, uint8_t *blockData);
int mifare_ultra_auth2(uint32_t cuid, uint8_t *key, uint8_t *blockData);
int mifare_ultra_readblock(uint32_t uid, uint8_t blockNo, uint8_t *blockData); int mifare_ultra_readblock(uint32_t uid, uint8_t blockNo, uint8_t *blockData);
int mifare_classic_writeblock(struct Crypto1State *pcs, uint32_t uid, uint8_t blockNo, uint8_t *blockData); int mifare_classic_writeblock(struct Crypto1State *pcs, uint32_t uid, uint8_t blockNo, uint8_t *blockData);
int mifare_ultra_writeblock(uint32_t uid, uint8_t blockNo, uint8_t *blockData); int mifare_ultra_writeblock(uint32_t uid, uint8_t blockNo, uint8_t *blockData);
@ -72,12 +68,6 @@ int mifare_ultra_special_writeblock(uint32_t uid, uint8_t blockNo, uint8_t *bloc
int mifare_classic_halt(struct Crypto1State *pcs, uint32_t uid); int mifare_classic_halt(struct Crypto1State *pcs, uint32_t uid);
int mifare_ultra_halt(uint32_t uid); int mifare_ultra_halt(uint32_t uid);
// desfire
int mifare_sendcmd_special(struct Crypto1State *pcs, uint8_t crypted, uint8_t cmd, uint8_t* data, uint8_t* answer, uint8_t *answer_parity, uint32_t *timing);
int mifare_sendcmd_special2(struct Crypto1State *pcs, uint8_t crypted, uint8_t cmd, uint8_t* data, uint8_t* answer,uint8_t *answer_parity, uint32_t *timing);
int mifare_desfire_des_auth1(uint32_t uid, uint8_t *blockData);
int mifare_desfire_des_auth2(uint32_t uid, uint8_t *key, uint8_t *blockData);
// crypto functions // crypto functions
void mf_crypto1_decrypt(struct Crypto1State *pcs, uint8_t *receivedCmd, int len); void mf_crypto1_decrypt(struct Crypto1State *pcs, uint8_t *receivedCmd, int len);
void mf_crypto1_encrypt(struct Crypto1State *pcs, uint8_t *data, uint16_t len, uint8_t *par); void mf_crypto1_encrypt(struct Crypto1State *pcs, uint8_t *data, uint16_t len, uint8_t *par);

View file

@ -9,7 +9,7 @@
// with the linker script. // with the linker script.
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
#include "../include/proxmark3.h" #include "proxmark3.h"
#include "apps.h" #include "apps.h"
extern char __data_start__, __data_src_start__, __data_end__, __bss_start__, __bss_end__; extern char __data_start__, __data_src_start__, __data_end__, __bss_start__, __bss_end__;

View file

@ -48,11 +48,6 @@ int memcmp(const void *av, const void *bv, int len)
return 0; return 0;
} }
void memxor(uint8_t * dest, uint8_t * src, size_t len) {
for( ; len > 0; len--,dest++,src++)
*dest ^= *src;
}
int strlen(const char *str) int strlen(const char *str)
{ {
int l = 0; int l = 0;

View file

@ -12,14 +12,10 @@
#ifndef __STRING_H #ifndef __STRING_H
#define __STRING_H #define __STRING_H
#include <stdint.h>
#include <util.h>
int strlen(const char *str); int strlen(const char *str);
RAMFUNC void *memcpy(void *dest, const void *src, int len); void *memcpy(void *dest, const void *src, int len);
void *memset(void *dest, int c, int len); void *memset(void *dest, int c, int len);
RAMFUNC int memcmp(const void *av, const void *bv, int len); int memcmp(const void *av, const void *bv, int len);
void memxor(uint8_t * dest, uint8_t * src, size_t len);
char *strncat(char *dest, const char *src, unsigned int n); char *strncat(char *dest, const char *src, unsigned int n);
char *strcat(char *dest, const char *src); char *strcat(char *dest, const char *src);
void strreverse(char s[]); void strreverse(char s[]);

View file

@ -8,31 +8,11 @@
// Utility functions used in many places, not specific to any piece of code. // Utility functions used in many places, not specific to any piece of code.
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
#include "../include/proxmark3.h" #include "proxmark3.h"
#include "util.h" #include "util.h"
#include "string.h" #include "string.h"
#include "apps.h" #include "apps.h"
void print_result(char *name, uint8_t *buf, size_t len) {
uint8_t *p = buf;
if ( len % 16 == 0 ) {
for(; p-buf < len; p += 16)
Dbprintf("[%s:%d/%d] %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x",
name,
p-buf,
len,
p[0], p[1], p[2], p[3], p[4], p[5], p[6], p[7],p[8], p[9], p[10], p[11], p[12], p[13], p[14], p[15]
);
}
else {
for(; p-buf < len; p += 8)
Dbprintf("[%s:%d/%d] %02x %02x %02x %02x %02x %02x %02x %02x", name, p-buf, len, p[0], p[1], p[2], p[3], p[4], p[5], p[6], p[7]);
}
}
size_t nbytes(size_t nbits) { size_t nbytes(size_t nbits) {
return (nbits/8)+((nbits%8)>0); return (nbits/8)+((nbits%8)>0);
} }
@ -65,26 +45,6 @@ uint64_t bytes_to_num(uint8_t* src, size_t len)
return num; return num;
} }
// RotateLeft - Ultralight, Desfire
void rol(uint8_t *data, const size_t len){
uint8_t first = data[0];
for (size_t i = 0; i < len-1; i++) {
data[i] = data[i+1];
}
data[len-1] = first;
}
void lsl (uint8_t *data, size_t len) {
for (size_t n = 0; n < len - 1; n++) {
data[n] = (data[n] << 1) | (data[n+1] >> 7);
}
data[len - 1] <<= 1;
}
int32_t le24toh (uint8_t data[3])
{
return (data[2] << 16) | (data[1] << 8) | data[0];
}
void LEDsoff() void LEDsoff()
{ {
LED_A_OFF(); LED_A_OFF();

View file

@ -13,7 +13,7 @@
#include <stddef.h> #include <stddef.h>
#include <stdint.h> #include <stdint.h>
#include "../include/common.h" #include <common.h>
#define BYTEx(x, n) (((x) >> (n * 8)) & 0xff ) #define BYTEx(x, n) (((x) >> (n * 8)) & 0xff )
@ -27,14 +27,10 @@
#define BUTTON_DOUBLE_CLICK -2 #define BUTTON_DOUBLE_CLICK -2
#define BUTTON_ERROR -99 #define BUTTON_ERROR -99
void print_result(char *name, uint8_t *buf, size_t len);
size_t nbytes(size_t nbits); size_t nbytes(size_t nbits);
uint32_t SwapBits(uint32_t value, int nrbits); uint32_t SwapBits(uint32_t value, int nrbits);
void num_to_bytes(uint64_t n, size_t len, uint8_t* dest); void num_to_bytes(uint64_t n, size_t len, uint8_t* dest);
uint64_t bytes_to_num(uint8_t* src, size_t len); uint64_t bytes_to_num(uint8_t* src, size_t len);
void rol(uint8_t *data, const size_t len);
void lsl (uint8_t *data, size_t len);
int32_t le24toh (uint8_t data[3]);
void SpinDelay(int ms); void SpinDelay(int ms);
void SpinDelayUs(int us); void SpinDelayUs(int us);

View file

@ -13,14 +13,14 @@ CXX=g++
VPATH = ../common VPATH = ../common
OBJDIR = obj OBJDIR = obj
LDLIBS = -L/mingw/lib -L/opt/local/lib -L/usr/local/lib ../liblua/liblua.a -lm -lreadline -lpthread -lcrypto -lgdi32 LDLIBS = -L/opt/local/lib -L/usr/local/lib -lreadline -lpthread ../liblua/liblua.a
LDFLAGS = $(COMMON_FLAGS) LDFLAGS = $(COMMON_FLAGS)
CFLAGS = -std=c99 -I. -I../include -I../common -I/mingw/include -I/opt/local/include -I../liblua -Wall $(COMMON_FLAGS) -g -O4 $(ICE_FLAGS) CFLAGS = -std=c99 -lcrypto -I. -I../include -I../common -I/opt/local/include -I../liblua -Wall $(COMMON_FLAGS) -g -O4
LUAPLATFORM = generic LUAPLATFORM = generic
ifneq (,$(findstring MINGW,$(platform))) ifneq (,$(findstring MINGW,$(platform)))
CXXFLAGS = -I$(QTDIR)/include -I$(QTDIR)/include/QtCore -I$(QTDIR)/include/QtGui -I$(QTDIR)/include/QtWidgets -I/mingw/include CXXFLAGS = -I$(QTDIR)/include -I$(QTDIR)/include/QtCore -I$(QTDIR)/include/QtGui
QTLDLIBS = -L$(QTDIR)/lib -lQt5Core -lQt5Gui -lQt5Widgets QTLDLIBS = -L$(QTDIR)/lib -lQtCore4 -lQtGui4
MOC = $(QTDIR)/bin/moc MOC = $(QTDIR)/bin/moc
LUAPLATFORM = mingw LUAPLATFORM = mingw
else ifeq ($(platform),Darwin) else ifeq ($(platform),Darwin)
@ -56,14 +56,13 @@ CORESRCS = uart.c \
CMDSRCS = nonce2key/crapto1.c\ CMDSRCS = nonce2key/crapto1.c\
nonce2key/crypto1.c\ nonce2key/crypto1.c\
nonce2key/nonce2key.c\ nonce2key/nonce2key.c\
loclass/cipher.c \ loclass/cipher.c \
loclass/cipherutils.c \ loclass/cipherutils.c \
loclass/des.c \ loclass/des.c \
loclass/ikeys.c \ loclass/ikeys.c \
loclass/elite_crack.c \ loclass/elite_crack.c\
loclass/fileutils.c \ loclass/fileutils.c\
loclass/hash1_brute.c \ mifarehost.c\
mifarehost.c \
crc16.c \ crc16.c \
iso14443crc.c \ iso14443crc.c \
iso15693tools.c \ iso15693tools.c \
@ -80,12 +79,8 @@ CMDSRCS = nonce2key/crapto1.c\
cmdhflegic.c \ cmdhflegic.c \
cmdhficlass.c \ cmdhficlass.c \
cmdhfmf.c \ cmdhfmf.c \
cmdhfmfu.c \
cmdhfmfdes.c \
cmdhfdes.c \
cmdhw.c \ cmdhw.c \
cmdlf.c \ cmdlf.c \
cmdlfawid26.c \
cmdlfio.c \ cmdlfio.c \
cmdlfhid.c \ cmdlfhid.c \
cmdlfem4x.c \ cmdlfem4x.c \

File diff suppressed because it is too large Load diff

View file

@ -43,10 +43,11 @@ int CmdManchesterMod(const char *Cmd);
int CmdNorm(const char *Cmd); int CmdNorm(const char *Cmd);
int CmdPlot(const char *Cmd); int CmdPlot(const char *Cmd);
int CmdSamples(const char *Cmd); int CmdSamples(const char *Cmd);
int CmdTuneSamples(const char *Cmd);
int CmdSave(const char *Cmd); int CmdSave(const char *Cmd);
int CmdScale(const char *Cmd); int CmdScale(const char *Cmd);
int CmdThreshold(const char *Cmd); int CmdThreshold(const char *Cmd);
int CmdDirectionalThreshold(const char *Cmd); int CmdDirectionalThreshold(const char *Cmd);
int CmdZerocrossings(const char *Cmd); int CmdZerocrossings(const char *Cmd);
int CmdTuneSamples(const char *Cmd);
#endif #endif

View file

@ -22,9 +22,6 @@
#include "cmdhflegic.h" #include "cmdhflegic.h"
#include "cmdhficlass.h" #include "cmdhficlass.h"
#include "cmdhfmf.h" #include "cmdhfmf.h"
#include "cmdhfmfu.h"
#include "cmdhfmfdes.h"
#include "cmdhfdes.h"
static int CmdHelp(const char *Cmd); static int CmdHelp(const char *Cmd);
@ -317,13 +314,10 @@ static command_t CommandTable[] =
{"epa", CmdHFEPA, 1, "{ German Identification Card... }"}, {"epa", CmdHFEPA, 1, "{ German Identification Card... }"},
{"legic", CmdHFLegic, 0, "{ LEGIC RFIDs... }"}, {"legic", CmdHFLegic, 0, "{ LEGIC RFIDs... }"},
{"iclass", CmdHFiClass, 1, "{ ICLASS RFIDs... }"}, {"iclass", CmdHFiClass, 1, "{ ICLASS RFIDs... }"},
{"mf", CmdHFMF, 1, "{ MIFARE RFIDs... }"}, {"mf", CmdHFMF, 1, "{ MIFARE RFIDs... }"},
{"mfu", CmdHFMFUltra, 1, "{ MIFARE Ultralight RFIDs... }"},
{"mfdes", CmdHFMFDes, 1, "{ MIFARE Desfire RFIDs... }"},
{"des", CmdHFDES, 0, "{ MIFARE DESfire}"},
{"tune", CmdHFTune, 0, "Continuously measure HF antenna tuning"}, {"tune", CmdHFTune, 0, "Continuously measure HF antenna tuning"},
{"list", CmdHFList, 1, "List protocol data in trace buffer"}, {"list", CmdHFList, 1, "List protocol data in trace buffer"},
{NULL, NULL, 0, NULL} {NULL, NULL, 0, NULL}
}; };
int CmdHF(const char *Cmd) int CmdHF(const char *Cmd)

View file

@ -14,150 +14,22 @@
#include <string.h> #include <string.h>
#include <unistd.h> #include <unistd.h>
#include "util.h" #include "util.h"
#include "../common/iso14443crc.h" #include "iso14443crc.h"
#include "data.h" #include "data.h"
#include "proxmark3.h" #include "proxmark3.h"
#include "ui.h" #include "ui.h"
#include "cmdparser.h" #include "cmdparser.h"
#include "cmdhf14a.h" #include "cmdhf14a.h"
#include "../include/common.h" #include "common.h"
#include "cmdmain.h" #include "cmdmain.h"
#include "../include/mifare.h" #include "mifare.h"
static int CmdHelp(const char *Cmd); static int CmdHelp(const char *Cmd);
static void waitCmd(uint8_t iLen); static void waitCmd(uint8_t iLen);
int CmdHF14AList(const char *Cmd) int CmdHF14AList(const char *Cmd)
{ {
bool ShowWaitCycles = false; PrintAndLog("Deprecated command, use 'hf list 14a' instead");
char param = param_getchar(Cmd, 0);
if (param == 'h' || (param != 0 && param != 'f')) {
PrintAndLog("List data in trace buffer.");
PrintAndLog("Usage: hf 14a list [f]");
PrintAndLog("f - show frame delay times as well");
PrintAndLog("sample: hf 14a list f");
return 0;
}
ShowWaitCycles = (param == 'f');
// for the time being. Need better Bigbuf handling.
#define TRACE_SIZE 3000
uint8_t trace[TRACE_SIZE];
GetFromBigBuf(trace, TRACE_SIZE, 0);
WaitForResponse(CMD_ACK,NULL);
PrintAndLog("Recorded Activity");
PrintAndLog("");
PrintAndLog("Start = Start of Start Bit, End = End of last modulation. Src = Source of Transfer");
PrintAndLog("All times are in carrier periods (1/13.56Mhz)");
PrintAndLog("");
PrintAndLog(" Start | End | Src | Data (! denotes parity error) | CRC ");
PrintAndLog("-----------|-----------|-----|-----------------------------------------------------------------------");
uint16_t tracepos = 0;
uint16_t duration;
uint16_t data_len;
uint16_t parity_len;
bool isResponse;
uint32_t timestamp;
uint32_t first_timestamp;
uint32_t EndOfTransmissionTimestamp;
for (;;) {
if(tracepos >= TRACE_SIZE) break;
timestamp = *((uint32_t *)(trace + tracepos));
// Break and stick with current result if buffer was not completely full
if (timestamp == 0x44444444) break;
if(tracepos == 0) {
first_timestamp = timestamp;
}
tracepos += 4;
duration = *((uint16_t *)(trace + tracepos));
tracepos += 2;
data_len = *((uint16_t *)(trace + tracepos));
tracepos += 2;
isResponse = false;
if (data_len & 0x8000) {
data_len &= 0x7fff;
isResponse = true;
}
parity_len = (data_len-1)/8 + 1;
if (tracepos + data_len + parity_len >= TRACE_SIZE) break;
uint8_t *frame = trace + tracepos;
tracepos += data_len;
uint8_t *parityBytes = trace + tracepos;
tracepos += parity_len;
char line[16][110];
for (int j = 0; j < data_len; j++) {
int oddparity = 0x01;
int k;
for (k=0;k<8;k++) {
oddparity ^= (((frame[j] & 0xFF) >> k) & 0x01);
}
uint8_t parityBits = parityBytes[j>>3];
if (isResponse && (oddparity != ((parityBits >> (7-(j&0x0007))) & 0x01))) {
sprintf(line[j/16]+((j%16)*4), "%02x! ", frame[j]);
} else {
sprintf(line[j/16]+((j%16)*4), "%02x ", frame[j]);
}
}
char crc[5] = {0x00};
if (data_len > 2) {
uint8_t b1, b2;
ComputeCrc14443(CRC_14443_A, frame, data_len-2, &b1, &b2);
if (b1 != frame[data_len-2] || b2 != frame[data_len-1]) {
sprintf(crc, (isResponse & (data_len < 6)) ? "" : "!crc");
}
}
EndOfTransmissionTimestamp = timestamp + duration;
int num_lines = (data_len - 1)/16 + 1;
for (int j = 0; j < num_lines; j++) {
if (j == 0) {
PrintAndLog(" %9d | %9d | %s | %-64s| %s",
(timestamp - first_timestamp),
(EndOfTransmissionTimestamp - first_timestamp),
(isResponse ? "Tag" : "Rdr"),
line[j],
(j == num_lines-1)?crc:""
);
} else {
PrintAndLog(" | | | %-64s| %s",
line[j],
(j == num_lines-1)?crc:"");
}
}
bool next_isResponse = *((uint16_t *)(trace + tracepos + 6)) & 0x8000;
if (ShowWaitCycles && !isResponse && next_isResponse) {
uint32_t next_timestamp = *((uint32_t *)(trace + tracepos));
if (next_timestamp != 0x44444444) {
PrintAndLog(" %9d | %9d | %s | fdt (Frame Delay Time): %d",
(EndOfTransmissionTimestamp - first_timestamp),
(next_timestamp - first_timestamp),
" ",
(next_timestamp - EndOfTransmissionTimestamp));
}
}
}
return 0; return 0;
} }
@ -226,6 +98,13 @@ int CmdHF14AReader(const char *Cmd)
card.ats_len = resp.arg[0]; // note: ats_len includes CRC Bytes card.ats_len = resp.arg[0]; // note: ats_len includes CRC Bytes
} }
// disconnect
c.arg[0] = 0;
c.arg[1] = 0;
c.arg[2] = 0;
SendCommand(&c);
if(card.ats_len >= 3) { // a valid ATS consists of at least the length byte (TL) and 2 CRC bytes if(card.ats_len >= 3) { // a valid ATS consists of at least the length byte (TL) and 2 CRC bytes
bool ta1 = 0, tb1 = 0, tc1 = 0; bool ta1 = 0, tb1 = 0, tc1 = 0;
int pos; int pos;
@ -364,24 +243,6 @@ int CmdHF14AReader(const char *Cmd)
PrintAndLog("proprietary non iso14443-4 card found, RATS not supported"); PrintAndLog("proprietary non iso14443-4 card found, RATS not supported");
} }
// try to see if card responses to "chinese magic backdoor" commands.
c.cmd = CMD_MIFARE_CIDENT;
c.arg[0] = 0;
c.arg[1] = 0;
c.arg[2] = 0;
SendCommand(&c);
WaitForResponse(CMD_ACK,&resp);
uint8_t isOK = resp.arg[0] & 0xff;
PrintAndLog(" Answers to chinese magic backdoor commands: %s", (isOK ? "YES" : "NO") );
// disconnect
c.cmd = CMD_READER_ISO_14443a;
c.arg[0] = 0;
c.arg[1] = 0;
c.arg[2] = 0;
SendCommand(&c);
return select_status; return select_status;
} }
@ -536,22 +397,19 @@ int CmdHF14ACmdRaw(const char *cmd) {
uint8_t active=0; uint8_t active=0;
uint8_t active_select=0; uint8_t active_select=0;
uint16_t numbits=0; uint16_t numbits=0;
uint16_t timeout=0;
uint8_t bTimeout=0;
char buf[5]=""; char buf[5]="";
int i=0; int i=0;
uint8_t data[USB_CMD_DATA_SIZE]; uint8_t data[100];
unsigned int datalen=0, temp; unsigned int datalen=0, temp;
if (strlen(cmd)<2) { if (strlen(cmd)<2) {
PrintAndLog("Usage: hf 14a raw [-r] [-c] [-p] [-f] [-b] [-t] <number of bits> <0A 0B 0C ... hex>"); PrintAndLog("Usage: hf 14a raw [-r] [-c] [-p] [-f] [-b] <number of bits> <0A 0B 0C ... hex>");
PrintAndLog(" -r do not read response"); PrintAndLog(" -r do not read response");
PrintAndLog(" -c calculate and append CRC"); PrintAndLog(" -c calculate and append CRC");
PrintAndLog(" -p leave the signal field ON after receive"); PrintAndLog(" -p leave the signal field ON after receive");
PrintAndLog(" -a active signal field ON without select"); PrintAndLog(" -a active signal field ON without select");
PrintAndLog(" -s active signal field ON with select"); PrintAndLog(" -s active signal field ON with select");
PrintAndLog(" -b number of bits to send. Useful for send partial byte"); PrintAndLog(" -b number of bits to send. Useful for send partial byte");
PrintAndLog(" -t timeout");
return 0; return 0;
} }
@ -584,14 +442,6 @@ int CmdHF14ACmdRaw(const char *cmd) {
while(cmd[i]!=' ' && cmd[i]!='\0') { i++; } while(cmd[i]!=' ' && cmd[i]!='\0') { i++; }
i-=2; i-=2;
break; break;
case 't':
bTimeout=1;
sscanf(cmd+i+2,"%d",&temp);
timeout = temp & 0xFFFF;
i+=3;
while(cmd[i]!=' ' && cmd[i]!='\0') { i++; }
i+=2;
break;
default: default:
PrintAndLog("Invalid option"); PrintAndLog("Invalid option");
return 0; return 0;
@ -609,19 +459,15 @@ int CmdHF14ACmdRaw(const char *cmd) {
if (strlen(buf)>=2) { if (strlen(buf)>=2) {
sscanf(buf,"%x",&temp); sscanf(buf,"%x",&temp);
data[datalen]=(uint8_t)(temp & 0xff); data[datalen]=(uint8_t)(temp & 0xff);
datalen++;
*buf=0; *buf=0;
if (++datalen>sizeof(data)){
if (crc)
PrintAndLog("Buffer is full, we can't add CRC to your data");
break;
}
} }
continue; continue;
} }
PrintAndLog("Invalid char on input"); PrintAndLog("Invalid char on input");
return 0; return 0;
} }
if(crc && datalen>0 && datalen<sizeof(data)-2) if(crc && datalen>0)
{ {
uint8_t first, second; uint8_t first, second;
ComputeCrc14443(CRC_14443_A, data, datalen, &first, &second); ComputeCrc14443(CRC_14443_A, data, datalen, &first, &second);
@ -635,22 +481,13 @@ int CmdHF14ACmdRaw(const char *cmd) {
if(active) if(active)
c.arg[0] |= ISO14A_NO_SELECT; c.arg[0] |= ISO14A_NO_SELECT;
} }
if(bTimeout){
#define MAX_TIMEOUT 624*105 // max timeout is 624 ms
c.arg[0] |= ISO14A_SET_TIMEOUT;
c.arg[2] = timeout * 105; // each bit is about 9.4 us
if(c.arg[2]>MAX_TIMEOUT) {
c.arg[2] = MAX_TIMEOUT;
PrintAndLog("Set timeout to 624 ms. The max we can wait for response");
}
}
if(power) if(power)
c.arg[0] |= ISO14A_NO_DISCONNECT; c.arg[0] |= ISO14A_NO_DISCONNECT;
if(datalen>0) if(datalen>0)
c.arg[0] |= ISO14A_RAW; c.arg[0] |= ISO14A_RAW;
// Max buffer is USB_CMD_DATA_SIZE c.arg[1] = datalen;
c.arg[1] = (datalen & 0xFFFF) | (numbits << 16); c.arg[2] = numbits;
memcpy(c.d.asBytes,data,datalen); memcpy(c.d.asBytes,data,datalen);
SendCommand(&c); SendCommand(&c);
@ -670,7 +507,7 @@ static void waitCmd(uint8_t iSelect)
UsbCommand resp; UsbCommand resp;
char *hexout; char *hexout;
if (WaitForResponseTimeout(CMD_ACK,&resp,10000)) { if (WaitForResponseTimeout(CMD_ACK,&resp,1000)) {
recv = resp.d.asBytes; recv = resp.d.asBytes;
uint8_t iLen = iSelect ? resp.arg[1] : resp.arg[0]; uint8_t iLen = iSelect ? resp.arg[1] : resp.arg[0];
PrintAndLog("received %i octets",iLen); PrintAndLog("received %i octets",iLen);

View file

@ -13,15 +13,17 @@
#include <stdbool.h> #include <stdbool.h>
#include <string.h> #include <string.h>
#include <stdint.h> #include <stdint.h>
#include "../common/iso14443crc.h" #include "iso14443crc.h"
#include "proxmark3.h" #include "proxmark3.h"
#include "data.h" #include "data.h"
#include "graph.h" #include "graph.h"
#include "util.h"
#include "ui.h" #include "ui.h"
#include "cmdparser.h" #include "cmdparser.h"
#include "cmdhf14b.h" #include "cmdhf14b.h"
#include "cmdmain.h" #include "cmdmain.h"
static int CmdHelp(const char *Cmd); static int CmdHelp(const char *Cmd);
int CmdHF14BDemod(const char *Cmd) int CmdHF14BDemod(const char *Cmd)
@ -144,7 +146,7 @@ demodError:
int CmdHF14BList(const char *Cmd) int CmdHF14BList(const char *Cmd)
{ {
uint8_t got[TRACE_BUFFER_SIZE]; uint8_t got[960];
GetFromBigBuf(got,sizeof(got),0); GetFromBigBuf(got,sizeof(got),0);
WaitForResponse(CMD_ACK,NULL); WaitForResponse(CMD_ACK,NULL);
@ -156,8 +158,9 @@ int CmdHF14BList(const char *Cmd)
int prev = -1; int prev = -1;
for(;;) { for(;;) {
if(i >= 900) {
if(i >= TRACE_BUFFER_SIZE) { break; } break;
}
bool isResponse; bool isResponse;
int timestamp = *((uint32_t *)(got+i)); int timestamp = *((uint32_t *)(got+i));
@ -174,7 +177,7 @@ int CmdHF14BList(const char *Cmd)
if(len > 100) { if(len > 100) {
break; break;
} }
if(i + len >= TRACE_BUFFER_SIZE) { if(i + len >= 900) {
break; break;
} }
@ -356,7 +359,7 @@ int CmdHF14BCmdRaw (const char *cmd) {
SendCommand(&c); SendCommand(&c);
if (reply) { if (reply) {
if (WaitForResponseTimeout(CMD_ACK,&resp,10000)) { if (WaitForResponseTimeout(CMD_ACK,&resp,1000)) {
recv = resp.d.asBytes; recv = resp.d.asBytes;
PrintAndLog("received %i octets",resp.arg[0]); PrintAndLog("received %i octets",resp.arg[0]);
if(!resp.arg[0]) if(!resp.arg[0])

View file

@ -31,9 +31,10 @@
#include "data.h" #include "data.h"
#include "graph.h" #include "graph.h"
#include "ui.h" #include "ui.h"
#include "util.h"
#include "cmdparser.h" #include "cmdparser.h"
#include "cmdhf15.h" #include "cmdhf15.h"
#include "../common/iso15693tools.h" #include "iso15693tools.h"
#include "cmdmain.h" #include "cmdmain.h"
#define FrameSOF Iso15693FrameSOF #define FrameSOF Iso15693FrameSOF
@ -44,7 +45,6 @@
#define Crc(data,datalen) Iso15693Crc(data,datalen) #define Crc(data,datalen) Iso15693Crc(data,datalen)
#define AddCrc(data,datalen) Iso15693AddCrc(data,datalen) #define AddCrc(data,datalen) Iso15693AddCrc(data,datalen)
#define sprintUID(target,uid) Iso15693sprintUID(target,uid) #define sprintUID(target,uid) Iso15693sprintUID(target,uid)
#define TRACE_BUFF_SIZE 12000
// structure and database for uid -> tagtype lookups // structure and database for uid -> tagtype lookups
typedef struct { typedef struct {
@ -255,17 +255,6 @@ int CmdHF15Read(const char *Cmd)
{ {
UsbCommand c = {CMD_ACQUIRE_RAW_ADC_SAMPLES_ISO_15693}; UsbCommand c = {CMD_ACQUIRE_RAW_ADC_SAMPLES_ISO_15693};
SendCommand(&c); SendCommand(&c);
uint8_t data[TRACE_BUFF_SIZE] = {0x00};
GetFromBigBuf(data,TRACE_BUFF_SIZE,3560); //3560 -- should be offset..
WaitForResponseTimeout(CMD_ACK,NULL, 1500);
for (int j = 0; j < TRACE_BUFF_SIZE; j++) {
GraphBuffer[j] = ((int)data[j]) ;
}
GraphTraceLen = TRACE_BUFF_SIZE;
RepaintGraphWindow();
return 0; return 0;
} }
@ -274,17 +263,6 @@ int CmdHF15Record(const char *Cmd)
{ {
UsbCommand c = {CMD_RECORD_RAW_ADC_SAMPLES_ISO_15693}; UsbCommand c = {CMD_RECORD_RAW_ADC_SAMPLES_ISO_15693};
SendCommand(&c); SendCommand(&c);
uint8_t data[TRACE_BUFF_SIZE] = {0x00};
GetFromBigBuf(data,TRACE_BUFF_SIZE,3560); //3560 -- should be offset..
WaitForResponseTimeout(CMD_ACK,NULL, 1500);
for (int j = 0; j < TRACE_BUFF_SIZE; j++) {
GraphBuffer[j] = ((int)data[j]) ;
}
GraphTraceLen = TRACE_BUFF_SIZE;
RepaintGraphWindow();
return 0; return 0;
} }
@ -582,9 +560,9 @@ int CmdHF15CmdRaw (const char *cmd) {
*/ */
int prepareHF15Cmd(char **cmd, UsbCommand *c, uint8_t iso15cmd[], int iso15cmdlen) { int prepareHF15Cmd(char **cmd, UsbCommand *c, uint8_t iso15cmd[], int iso15cmdlen) {
int temp; int temp;
uint8_t *req = c->d.asBytes; uint8_t *req=c->d.asBytes;
uint8_t uid[8] = {0x00}; uint8_t uid[8] = {0x00};
uint32_t reqlen = 0; uint32_t reqlen=0;
// strip // strip
while (**cmd==' ' || **cmd=='\t') (*cmd)++; while (**cmd==' ' || **cmd=='\t') (*cmd)++;

View file

@ -1,69 +0,0 @@
//-----------------------------------------------------------------------------
// Copyright (C) 2012 nuit
//
// 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.
//-----------------------------------------------------------------------------
// High frequency MIFARE DESfire commands
//-----------------------------------------------------------------------------
#include "cmdhfdes.h"
#include "proxmark3.h"
#include "cmdmain.h"
static int CmdHelp(const char *Cmd);
int CmdHFDESReader(const char *Cmd)
{
UsbCommand c ={CMD_MIFARE_DES_READER, {3, 0x60, 0}};
SendCommand(&c);
UsbCommand resp;
WaitForResponseTimeout(CMD_ACK,&resp,2000);
return 0;
}
int CmdHFDESDbg(const char *Cmd)
{
int dbgMode = param_get32ex(Cmd, 0, 0, 10);
if (dbgMode > 4) {
PrintAndLog("Max debud mode parameter is 4 \n");
}
if (strlen(Cmd) < 1 || !param_getchar(Cmd, 0) || dbgMode > 4) {
PrintAndLog("Usage: hf des dbg <debug level>");
PrintAndLog(" 0 - no debug messages");
PrintAndLog(" 1 - error messages");
PrintAndLog(" 2 - all messages");
PrintAndLog(" 4 - extended debug mode");
return 0;
}
UsbCommand c = {CMD_MIFARE_SET_DBGMODE, {dbgMode, 0, 0}};
SendCommand(&c);
return 0;
}
static command_t CommandTable[] =
{
{"help", CmdHelp, 1, "This help"},
{"dbg", CmdHFDESDbg, 0, "Set default debug mode"},
{"reader", CmdHFDESReader, 0, "Reader"},
{NULL, NULL, 0, NULL}
};
int CmdHFDES(const char *Cmd)
{
//flush
WaitForResponseTimeout(CMD_ACK,NULL,100);
CmdsParse(CommandTable, Cmd);
return 0;
}
int CmdHelp(const char *Cmd)
{
CmdsHelp(CommandTable);
return 0;
}

View file

@ -1,27 +0,0 @@
//-----------------------------------------------------------------------------
// Copyright (C) 2012 nuit
//
// 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.
//-----------------------------------------------------------------------------
// High frequency MIFARE DESfire commands
//-----------------------------------------------------------------------------
#ifndef CMDHFDES_H__
#define CMDHFDES_H__
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include "proxmark3.h"
#include "data.h"
#include "ui.h"
#include "cmdparser.h"
#include "common.h"
#include "util.h"
int CmdHFDES(const char *Cmd);
int CmdHFDESReader(const char *Cmd);
int CmdHFDESDbg(const char *Cmd);
#endif

View file

@ -13,7 +13,7 @@
#include "proxmark3.h" #include "proxmark3.h"
#include "ui.h" #include "ui.h"
#include "cmdparser.h" #include "cmdparser.h"
#include "../include/common.h" #include "common.h"
#include "cmdmain.h" #include "cmdmain.h"
#include "sleep.h" #include "sleep.h"
#include "cmdhfepa.h" #include "cmdhfepa.h"

View file

@ -20,7 +20,7 @@
#include "ui.h" #include "ui.h"
#include "cmdparser.h" #include "cmdparser.h"
#include "cmdhficlass.h" #include "cmdhficlass.h"
#include "../include/common.h" #include "common.h"
#include "util.h" #include "util.h"
#include "cmdmain.h" #include "cmdmain.h"
#include "loclass/des.h" #include "loclass/des.h"
@ -34,53 +34,17 @@ static int CmdHelp(const char *Cmd);
int xorbits_8(uint8_t val) int xorbits_8(uint8_t val)
{ {
uint8_t res = val ^ (val >> 1); //1st pass uint8_t res = val ^ (val >> 1); //1st pass
res = res ^ (res >> 1); // 2nd pass res = res ^ (res >> 1); // 2nd pass
res = res ^ (res >> 2); // 3rd pass res = res ^ (res >> 2); // 3rd pass
res = res ^ (res >> 4); // 4th pass res = res ^ (res >> 4); // 4th pass
return res & 1; return res & 1;
}
#define ICLASS_CMD_ACTALL 0x0A
#define ICLASS_CMD_IDENTIFY 0x0C
#define ICLASS_CMD_READ 0x0C
#define ICLASS_CMD_SELECT 0x81
#define ICLASS_CMD_PAGESEL 0x84
#define ICLASS_CMD_READCHECK 0x88
#define ICLASS_CMD_CHECK 0x05
#define ICLASS_CMD_SOF 0x0F
#define ICLASS_CMD_HALT 0x00
void explain(char *exp, size_t size, uint8_t* cmd, uint8_t cmdsize)
{
if(cmdsize > 1 && cmd[0] == ICLASS_CMD_READ)
{
snprintf(exp,size,"READ(%d)",cmd[1]);
return;
}
switch(cmd[0])
{
case ICLASS_CMD_ACTALL: snprintf(exp,size,"ACTALL"); break;
case ICLASS_CMD_IDENTIFY: snprintf(exp,size,"IDENTIFY"); break;
case ICLASS_CMD_SELECT: snprintf(exp,size,"SELECT"); break;
case ICLASS_CMD_PAGESEL: snprintf(exp,size,"PAGESEL"); break;
case ICLASS_CMD_READCHECK: snprintf(exp,size,"READCHECK"); break;
case ICLASS_CMD_CHECK: snprintf(exp,size,"CHECK"); break;
case ICLASS_CMD_SOF: snprintf(exp,size,"SOF"); break;
case ICLASS_CMD_HALT: snprintf(exp,size,"HALT"); break;
default: snprintf(exp,size,"?"); break;
}
return;
} }
int CmdHFiClassList(const char *Cmd) int CmdHFiClassList(const char *Cmd)
{ {
PrintAndLog("Deprecated command, use 'hf list iclass' instead"); PrintAndLog("Deprecated command, use 'hf list iclass' instead");
return 0; return 0;
} }
int CmdHFiClassSnoop(const char *Cmd) int CmdHFiClassSnoop(const char *Cmd)
@ -140,24 +104,24 @@ int CmdHFiClassSim(const char *Cmd)
0x0c,0x90,0x32,0xf3,0x5d,0xff,0x12,0xe0 }; 0x0c,0x90,0x32,0xf3,0x5d,0xff,0x12,0xe0 };
*/ */
uint8_t csns[8*NUM_CSNS] = { uint8_t csns[8*NUM_CSNS] = {
0x00, 0x0B, 0x0F, 0xFF, 0xF7, 0xFF, 0x12, 0xE0, 0x00, 0x0B, 0x0F, 0xFF, 0xF7, 0xFF, 0x12, 0xE0,
0x00, 0x04, 0x0E, 0x08, 0xF7, 0xFF, 0x12, 0xE0, 0x00, 0x04, 0x0E, 0x08, 0xF7, 0xFF, 0x12, 0xE0,
0x00, 0x09, 0x0D, 0x05, 0xF7, 0xFF, 0x12, 0xE0, 0x00, 0x09, 0x0D, 0x05, 0xF7, 0xFF, 0x12, 0xE0,
0x00, 0x0A, 0x0C, 0x06, 0xF7, 0xFF, 0x12, 0xE0, 0x00, 0x0A, 0x0C, 0x06, 0xF7, 0xFF, 0x12, 0xE0,
0x00, 0x0F, 0x0B, 0x03, 0xF7, 0xFF, 0x12, 0xE0, 0x00, 0x0F, 0x0B, 0x03, 0xF7, 0xFF, 0x12, 0xE0,
0x00, 0x08, 0x0A, 0x0C, 0xF7, 0xFF, 0x12, 0xE0, 0x00, 0x08, 0x0A, 0x0C, 0xF7, 0xFF, 0x12, 0xE0,
0x00, 0x0D, 0x09, 0x09, 0xF7, 0xFF, 0x12, 0xE0, 0x00, 0x0D, 0x09, 0x09, 0xF7, 0xFF, 0x12, 0xE0,
0x00, 0x0E, 0x08, 0x0A, 0xF7, 0xFF, 0x12, 0xE0, 0x00, 0x0E, 0x08, 0x0A, 0xF7, 0xFF, 0x12, 0xE0,
0x00, 0x03, 0x07, 0x17, 0xF7, 0xFF, 0x12, 0xE0, 0x00, 0x03, 0x07, 0x17, 0xF7, 0xFF, 0x12, 0xE0,
0x00, 0x3C, 0x06, 0xE0, 0xF7, 0xFF, 0x12, 0xE0, 0x00, 0x3C, 0x06, 0xE0, 0xF7, 0xFF, 0x12, 0xE0,
0x00, 0x01, 0x05, 0x1D, 0xF7, 0xFF, 0x12, 0xE0, 0x00, 0x01, 0x05, 0x1D, 0xF7, 0xFF, 0x12, 0xE0,
0x00, 0x02, 0x04, 0x1E, 0xF7, 0xFF, 0x12, 0xE0, 0x00, 0x02, 0x04, 0x1E, 0xF7, 0xFF, 0x12, 0xE0,
0x00, 0x07, 0x03, 0x1B, 0xF7, 0xFF, 0x12, 0xE0, 0x00, 0x07, 0x03, 0x1B, 0xF7, 0xFF, 0x12, 0xE0,
0x00, 0x00, 0x02, 0x24, 0xF7, 0xFF, 0x12, 0xE0, 0x00, 0x00, 0x02, 0x24, 0xF7, 0xFF, 0x12, 0xE0,
0x00, 0x05, 0x01, 0x21, 0xF7, 0xFF, 0x12, 0xE0 }; 0x00, 0x05, 0x01, 0x21, 0xF7, 0xFF, 0x12, 0xE0 };
memcpy(c.d.asBytes, csns, 8*NUM_CSNS); memcpy(c.d.asBytes, csns, 8*NUM_CSNS);
SendCommand(&c); SendCommand(&c);
if (!WaitForResponseTimeout(CMD_ACK, &resp, -1)) { if (!WaitForResponseTimeout(CMD_ACK, &resp, -1)) {
@ -166,7 +130,7 @@ int CmdHFiClassSim(const char *Cmd)
} }
uint8_t num_mac_responses = resp.arg[1]; uint8_t num_mac_responses = resp.arg[1];
PrintAndLog("Mac responses: %d MACs obtained (should be %d)", num_mac_responses, NUM_CSNS); PrintAndLog("Mac responses: %d MACs obtained (should be %d)", num_mac_responses,NUM_CSNS);
size_t datalen = NUM_CSNS*24; size_t datalen = NUM_CSNS*24;
/* /*
@ -245,7 +209,7 @@ int CmdHFiClassReader_Replay(const char *Cmd)
if (strlen(Cmd)<1) { if (strlen(Cmd)<1) {
PrintAndLog("Usage: hf iclass replay <MAC>"); PrintAndLog("Usage: hf iclass replay <MAC>");
PrintAndLog(" sample: hf iclass replay 00112233"); PrintAndLog(" sample: hf iclass replay 00112233");
return 0; return 0;
} }
if (param_gethex(Cmd, 0, MAC, 8)) { if (param_gethex(Cmd, 0, MAC, 8)) {
@ -323,7 +287,7 @@ int CmdHFiClassReader_Dump(const char *Cmd)
UsbCommand c = {CMD_READER_ICLASS, {0}}; UsbCommand c = {CMD_READER_ICLASS, {0}};
c.arg[0] = FLAG_ICLASS_READER_ONLY_ONCE| FLAG_ICLASS_READER_GET_CC; c.arg[0] = FLAG_ICLASS_READER_ONLY_ONCE| FLAG_ICLASS_READER_GET_CC;
if(!fake_dummy_test) if(!fake_dummy_test)
SendCommand(&c); SendCommand(&c);
@ -469,19 +433,64 @@ int CmdHFiClass_iso14443A_write(const char *Cmd)
} }
return 0; return 0;
} }
int CmdHFiClass_loclass(const char *Cmd)
{
char opt = param_getchar(Cmd, 0);
if (strlen(Cmd)<1 || opt == 'h') {
PrintAndLog("Usage: hf iclass loclass [options]");
PrintAndLog("Options:");
PrintAndLog("h Show this help");
PrintAndLog("t Perform self-test");
PrintAndLog("f <filename> Bruteforce iclass dumpfile");
PrintAndLog(" An iclass dumpfile is assumed to consist of an arbitrary number of");
PrintAndLog(" malicious CSNs, and their protocol responses");
PrintAndLog(" The the binary format of the file is expected to be as follows: ");
PrintAndLog(" <8 byte CSN><8 byte CC><4 byte NR><4 byte MAC>");
PrintAndLog(" <8 byte CSN><8 byte CC><4 byte NR><4 byte MAC>");
PrintAndLog(" <8 byte CSN><8 byte CC><4 byte NR><4 byte MAC>");
PrintAndLog(" ... totalling N*24 bytes");
return 0;
}
char fileName[255] = {0};
if(opt == 'f')
{
if(param_getstr(Cmd, 1, fileName) > 0)
{
return bruteforceFileNoKeys(fileName);
}else
{
PrintAndLog("You must specify a filename");
}
}
else if(opt == 't')
{
int errors = testCipherUtils();
errors += testMAC();
errors += doKeyTests(0);
errors += testElite();
if(errors)
{
prnlog("OBS! There were errors!!!");
}
return errors;
}
return 0;
}
static command_t CommandTable[] = static command_t CommandTable[] =
{ {
{"help", CmdHelp, 1, "This help"}, {"help", CmdHelp, 1, "This help"},
{"list", CmdHFiClassList, 0, "[Deprecated] List iClass history"}, {"list", CmdHFiClassList, 0, "[Deprecated] List iClass history"},
{"snoop", CmdHFiClassSnoop, 0, "Eavesdrop iClass communication"}, {"snoop", CmdHFiClassSnoop, 0, "Eavesdrop iClass communication"},
{"sim", CmdHFiClassSim, 0, "Simulate iClass tag"}, {"sim", CmdHFiClassSim, 0, "Simulate iClass tag"},
{"reader",CmdHFiClassReader, 0, "Read an iClass tag"}, {"reader",CmdHFiClassReader, 0, "Read an iClass tag"},
{"replay", CmdHFiClassReader_Replay, 0, "Read an iClass tag via Reply Attack"}, {"replay",CmdHFiClassReader_Replay, 0, "Read an iClass tag via Reply Attack"},
{"dump", CmdHFiClassReader_Dump, 0, "Authenticate and Dump iClass tag"}, {"dump", CmdHFiClassReader_Dump, 0, "Authenticate and Dump iClass tag"},
{"write", CmdHFiClass_iso14443A_write, 0, "Authenticate and Write iClass block"}, {"write", CmdHFiClass_iso14443A_write, 0, "Authenticate and Write iClass block"},
{NULL, NULL, 0, NULL} {"loclass", CmdHFiClass_loclass, 1, "Use loclass to perform bruteforce of reader attack dump"},
{NULL, NULL, 0, NULL}
}; };
int CmdHFiClass(const char *Cmd) int CmdHFiClass(const char *Cmd)
@ -493,5 +502,5 @@ int CmdHFiClass(const char *Cmd)
int CmdHelp(const char *Cmd) int CmdHelp(const char *Cmd)
{ {
CmdsHelp(CommandTable); CmdsHelp(CommandTable);
return 0; return 0;
} }

View file

@ -218,24 +218,7 @@ int CmdLegicRFRead(const char *Cmd)
int CmdLegicLoad(const char *Cmd) int CmdLegicLoad(const char *Cmd)
{ {
char filename[FILE_PATH_SIZE] = {0x00}; FILE *f = fopen(Cmd, "r");
int len = 0;
if (param_getchar(Cmd, 0) == 'h' || param_getchar(Cmd, 0)== 0x00) {
PrintAndLog("It loads datasamples from the file `filename`");
PrintAndLog("Usage: hf legic load <file name>");
PrintAndLog(" sample: hf legic load filename");
return 0;
}
len = strlen(Cmd);
if (len > FILE_PATH_SIZE) {
PrintAndLog("Filepath too long (was %s bytes), max allowed is %s ", len, FILE_PATH_SIZE);
return 0;
}
memcpy(filename, Cmd, len);
FILE *f = fopen(filename, "r");
if(!f) { if(!f) {
PrintAndLog("couldn't open '%s'", Cmd); PrintAndLog("couldn't open '%s'", Cmd);
return -1; return -1;
@ -268,7 +251,7 @@ int CmdLegicSave(const char *Cmd)
int requested = 1024; int requested = 1024;
int offset = 0; int offset = 0;
int delivered = 0; int delivered = 0;
char filename[FILE_PATH_SIZE]; char filename[1024];
uint8_t got[1024]; uint8_t got[1024];
sscanf(Cmd, " %s %i %i", filename, &requested, &offset); sscanf(Cmd, " %s %i %i", filename, &requested, &offset);

View file

@ -7,7 +7,7 @@
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
// High frequency MIFARE commands // High frequency MIFARE commands
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
#include "../include/mifare.h"
#include "cmdhfmf.h" #include "cmdhfmf.h"
static int CmdHelp(const char *Cmd); static int CmdHelp(const char *Cmd);
@ -34,7 +34,7 @@ start:
SendCommand(&c); SendCommand(&c);
//flush queue //flush queue
while (ukbhit()) getchar(); while (ukbhit()) getchar();
// wait cycle // wait cycle
while (true) { while (true) {
@ -66,19 +66,20 @@ start:
if (isOK != 1) return 1; if (isOK != 1) return 1;
// execute original function from util nonce2key // execute original function from util nonce2key
if (nonce2key(uid, nt, nr, par_list, ks_list, &r_key)) { if (nonce2key(uid, nt, nr, par_list, ks_list, &r_key))
{
isOK = 2; isOK = 2;
PrintAndLog("Key not found (lfsr_common_prefix list is null). Nt=%08x", nt); PrintAndLog("Key not found (lfsr_common_prefix list is null). Nt=%08x", nt);
} else { } else {
printf("------------------------------------------------------------------\n"); printf("------------------------------------------------------------------\n");
PrintAndLog("Key found :%012"llx" \n", r_key); PrintAndLog("Key found:%012"llx" \n", r_key);
num_to_bytes(r_key, 6, keyBlock); num_to_bytes(r_key, 6, keyBlock);
isOK = mfCheckKeys(0, 0, 1, keyBlock, &r_key); isOK = mfCheckKeys(0, 0, 1, keyBlock, &r_key);
} }
if (!isOK) if (!isOK)
PrintAndLog("Found valid key :%012"llx, r_key); PrintAndLog("Found valid key:%012"llx, r_key);
else else
{ {
if (isOK != 2) PrintAndLog("Found invalid key. "); if (isOK != 2) PrintAndLog("Found invalid key. ");
@ -124,10 +125,10 @@ int CmdHF14AMfWrBl(const char *Cmd)
PrintAndLog("--block no:%d, key type:%c, key:%s", blockNo, keyType?'B':'A', sprint_hex(key, 6)); PrintAndLog("--block no:%d, key type:%c, key:%s", blockNo, keyType?'B':'A', sprint_hex(key, 6));
PrintAndLog("--data: %s", sprint_hex(bldata, 16)); PrintAndLog("--data: %s", sprint_hex(bldata, 16));
UsbCommand c = {CMD_MIFARE_WRITEBL, {blockNo, keyType, 0}}; UsbCommand c = {CMD_MIFARE_WRITEBL, {blockNo, keyType, 0}};
memcpy(c.d.asBytes, key, 6); memcpy(c.d.asBytes, key, 6);
memcpy(c.d.asBytes + 10, bldata, 16); memcpy(c.d.asBytes + 10, bldata, 16);
SendCommand(&c); SendCommand(&c);
UsbCommand resp; UsbCommand resp;
if (WaitForResponseTimeout(CMD_ACK,&resp,1500)) { if (WaitForResponseTimeout(CMD_ACK,&resp,1500)) {
@ -140,6 +141,117 @@ int CmdHF14AMfWrBl(const char *Cmd)
return 0; return 0;
} }
int CmdHF14AMfUWrBl(const char *Cmd)
{
uint8_t blockNo = 0;
bool chinese_card=0;
uint8_t bldata[16] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
UsbCommand resp;
if (strlen(Cmd)<3) {
PrintAndLog("Usage: hf mf uwrbl <block number> <block data (8 hex symbols)> <w>");
PrintAndLog(" sample: hf mf uwrbl 0 01020304");
return 0;
}
blockNo = param_get8(Cmd, 0);
if (param_gethex(Cmd, 1, bldata, 8)) {
PrintAndLog("Block data must include 8 HEX symbols");
return 1;
}
if (strchr(Cmd,'w') != 0) {
chinese_card=1;
}
switch(blockNo){
case 0:
if (!chinese_card){
PrintAndLog("Access Denied");
}else{
PrintAndLog("--specialblock no:%d", blockNo);
PrintAndLog("--data: %s", sprint_hex(bldata, 4));
UsbCommand d = {CMD_MIFAREU_WRITEBL, {blockNo}};
memcpy(d.d.asBytes,bldata, 4);
SendCommand(&d);
if (WaitForResponseTimeout(CMD_ACK,&resp,1500)) {
uint8_t isOK = resp.arg[0] & 0xff;
PrintAndLog("isOk:%02x", isOK);
} else {
PrintAndLog("Command execute timeout");
}
}
break;
case 1:
if (!chinese_card){
PrintAndLog("Access Denied");
}else{
PrintAndLog("--specialblock no:%d", blockNo);
PrintAndLog("--data: %s", sprint_hex(bldata, 4));
UsbCommand d = {CMD_MIFAREU_WRITEBL, {blockNo}};
memcpy(d.d.asBytes,bldata, 4);
SendCommand(&d);
if (WaitForResponseTimeout(CMD_ACK,&resp,1500)) {
uint8_t isOK = resp.arg[0] & 0xff;
PrintAndLog("isOk:%02x", isOK);
} else {
PrintAndLog("Command execute timeout");
}
}
break;
case 2:
if (!chinese_card){
PrintAndLog("Access Denied");
}else{
PrintAndLog("--specialblock no:%d", blockNo);
PrintAndLog("--data: %s", sprint_hex(bldata, 4));
UsbCommand c = {CMD_MIFAREU_WRITEBL, {blockNo}};
memcpy(c.d.asBytes, bldata, 4);
SendCommand(&c);
if (WaitForResponseTimeout(CMD_ACK,&resp,1500)) {
uint8_t isOK = resp.arg[0] & 0xff;
PrintAndLog("isOk:%02x", isOK);
} else {
PrintAndLog("Command execute timeout");
}
}
break;
case 3:
PrintAndLog("--specialblock no:%d", blockNo);
PrintAndLog("--data: %s", sprint_hex(bldata, 4));
UsbCommand d = {CMD_MIFAREU_WRITEBL, {blockNo}};
memcpy(d.d.asBytes,bldata, 4);
SendCommand(&d);
if (WaitForResponseTimeout(CMD_ACK,&resp,1500)) {
uint8_t isOK = resp.arg[0] & 0xff;
PrintAndLog("isOk:%02x", isOK);
} else {
PrintAndLog("Command execute timeout");
}
break;
default:
PrintAndLog("--block no:%d", blockNo);
PrintAndLog("--data: %s", sprint_hex(bldata, 4));
UsbCommand e = {CMD_MIFAREU_WRITEBL, {blockNo}};
memcpy(e.d.asBytes,bldata, 4);
SendCommand(&e);
if (WaitForResponseTimeout(CMD_ACK,&resp,1500)) {
uint8_t isOK = resp.arg[0] & 0xff;
PrintAndLog("isOk:%02x", isOK);
} else {
PrintAndLog("Command execute timeout");
}
break;
}
return 0;
}
int CmdHF14AMfRdBl(const char *Cmd) int CmdHF14AMfRdBl(const char *Cmd)
{ {
uint8_t blockNo = 0; uint8_t blockNo = 0;
@ -168,9 +280,9 @@ int CmdHF14AMfRdBl(const char *Cmd)
} }
PrintAndLog("--block no:%d, key type:%c, key:%s ", blockNo, keyType?'B':'A', sprint_hex(key, 6)); PrintAndLog("--block no:%d, key type:%c, key:%s ", blockNo, keyType?'B':'A', sprint_hex(key, 6));
UsbCommand c = {CMD_MIFARE_READBL, {blockNo, keyType, 0}}; UsbCommand c = {CMD_MIFARE_READBL, {blockNo, keyType, 0}};
memcpy(c.d.asBytes, key, 6); memcpy(c.d.asBytes, key, 6);
SendCommand(&c); SendCommand(&c);
UsbCommand resp; UsbCommand resp;
if (WaitForResponseTimeout(CMD_ACK,&resp,1500)) { if (WaitForResponseTimeout(CMD_ACK,&resp,1500)) {
@ -188,6 +300,87 @@ int CmdHF14AMfRdBl(const char *Cmd)
return 0; return 0;
} }
int CmdHF14AMfURdBl(const char *Cmd)
{
uint8_t blockNo = 0;
if (strlen(Cmd)<1) {
PrintAndLog("Usage: hf mf urdbl <block number>");
PrintAndLog(" sample: hf mf urdbl 0");
return 0;
}
blockNo = param_get8(Cmd, 0);
PrintAndLog("--block no:%d", blockNo);
UsbCommand c = {CMD_MIFAREU_READBL, {blockNo}};
SendCommand(&c);
UsbCommand resp;
if (WaitForResponseTimeout(CMD_ACK,&resp,1500)) {
uint8_t isOK = resp.arg[0] & 0xff;
uint8_t *data = resp.d.asBytes;
if (isOK)
PrintAndLog("isOk:%02x data:%s", isOK, sprint_hex(data, 4));
else
PrintAndLog("isOk:%02x", isOK);
} else {
PrintAndLog("Command execute timeout");
}
return 0;
}
int CmdHF14AMfURdCard(const char *Cmd)
{
int i;
uint8_t sectorNo = 0;
uint8_t *lockbytes_t=NULL;
uint8_t lockbytes[2]={0,0};
bool bit[16]={0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
uint8_t isOK = 0;
uint8_t * data = NULL;
PrintAndLog("Attempting to Read Ultralight... ");
UsbCommand c = {CMD_MIFAREU_READCARD, {sectorNo}};
SendCommand(&c);
UsbCommand resp;
if (WaitForResponseTimeout(CMD_ACK,&resp,1500)) {
isOK = resp.arg[0] & 0xff;
data = resp.d.asBytes;
PrintAndLog("isOk:%02x", isOK);
if (isOK)
{ // bit 0 and 1
PrintAndLog("Block %3d:%s ", 0,sprint_hex(data + 0 * 4, 4));
PrintAndLog("Block %3d:%s ", 1,sprint_hex(data + 1 * 4, 4));
// bit 2
//process lock bytes
lockbytes_t=data+(2*4);
lockbytes[0]=lockbytes_t[2];
lockbytes[1]=lockbytes_t[3];
for(int j=0; j<16; j++){
bit[j]=lockbytes[j/8] & ( 1 <<(7-j%8));
}
//remaining
for (i = 3; i < 16; i++) {
int bitnum = (23-i) % 16;
PrintAndLog("Block %3d:%s [%d]", i,sprint_hex(data + i * 4, 4),bit[bitnum]);
}
}
} else {
PrintAndLog("Command execute timeout");
}
return 0;
}
int CmdHF14AMfRdSc(const char *Cmd) int CmdHF14AMfRdSc(const char *Cmd)
{ {
int i; int i;
@ -278,14 +471,7 @@ int CmdHF14AMfDump(const char *Cmd)
UsbCommand resp; UsbCommand resp;
int size = GetCardSize();
char cmdp = param_getchar(Cmd, 0); char cmdp = param_getchar(Cmd, 0);
if ( size > -1)
cmdp = (char)(48+size);
PrintAndLog("Got %d",cmdp);
switch (cmdp) { switch (cmdp) {
case '0' : numSectors = 5; break; case '0' : numSectors = 5; break;
case '1' : case '1' :
@ -326,8 +512,8 @@ int CmdHF14AMfDump(const char *Cmd)
return 2; return 2;
} }
} }
fclose(fin); fclose(fin);
// Read access rights to sectors
PrintAndLog("|-----------------------------------------|"); PrintAndLog("|-----------------------------------------|");
PrintAndLog("|------ Reading sector access bits...-----|"); PrintAndLog("|------ Reading sector access bits...-----|");
@ -358,6 +544,8 @@ int CmdHF14AMfDump(const char *Cmd)
} }
} }
// Read blocks and print to file
PrintAndLog("|-----------------------------------------|"); PrintAndLog("|-----------------------------------------|");
PrintAndLog("|----- Dumping all blocks to file... -----|"); PrintAndLog("|----- Dumping all blocks to file... -----|");
PrintAndLog("|-----------------------------------------|"); PrintAndLog("|-----------------------------------------|");
@ -381,12 +569,12 @@ int CmdHF14AMfDump(const char *Cmd)
received = WaitForResponseTimeout(CMD_ACK,&resp,1500); received = WaitForResponseTimeout(CMD_ACK,&resp,1500);
} else if (rights[sectorNo][data_area] == 0x07) { // no key would work } else if (rights[sectorNo][data_area] == 0x07) { // no key would work
isOK = false; isOK = false;
PrintAndLog("Access rights do not allow reading of sector %2d block %3d", sectorNo, blockNo); PrintAndLog("Access rights do not allow reading of sector %2d block %3d", sectorNo, blockNo);
} else { // key A would work } else { // key A would work
UsbCommand c = {CMD_MIFARE_READBL, {FirstBlockOfSector(sectorNo) + blockNo, 0, 0}}; UsbCommand c = {CMD_MIFARE_READBL, {FirstBlockOfSector(sectorNo) + blockNo, 0, 0}};
memcpy(c.d.asBytes, keyA[sectorNo], 6); memcpy(c.d.asBytes, keyA[sectorNo], 6);
SendCommand(&c); SendCommand(&c);
received = WaitForResponseTimeout(CMD_ACK,&resp,1500); received = WaitForResponseTimeout(CMD_ACK,&resp,1500);
} }
} }
@ -441,8 +629,8 @@ int CmdHF14AMfRestore(const char *Cmd)
{ {
uint8_t sectorNo,blockNo; uint8_t sectorNo,blockNo;
uint8_t keyType = 0; uint8_t keyType = 0;
uint8_t key[6] = {0xFF}; uint8_t key[6] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF};
uint8_t bldata[16] = {0x00}; uint8_t bldata[16] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
uint8_t keyA[40][6]; uint8_t keyA[40][6];
uint8_t keyB[40][6]; uint8_t keyB[40][6];
uint8_t numSectors; uint8_t numSectors;
@ -460,7 +648,7 @@ int CmdHF14AMfRestore(const char *Cmd)
default: numSectors = 16; default: numSectors = 16;
} }
if (cmdp == 'h' || cmdp == 'H') { if (strlen(Cmd) > 1 || cmdp == 'h' || cmdp == 'H') {
PrintAndLog("Usage: hf mf restore [card memory]"); PrintAndLog("Usage: hf mf restore [card memory]");
PrintAndLog(" [card memory]: 0 = 320 bytes (Mifare Mini), 1 = 1K (default), 2 = 2K, 4 = 4K"); PrintAndLog(" [card memory]: 0 = 320 bytes (Mifare Mini), 1 = 1K (default), 2 = 2K, 4 = 4K");
PrintAndLog(""); PrintAndLog("");
@ -469,14 +657,21 @@ int CmdHF14AMfRestore(const char *Cmd)
return 0; return 0;
} }
if ((fdump = fopen("dumpdata.bin","rb")) == NULL) {
PrintAndLog("Could not find file dumpdata.bin");
return 1;
}
if ((fkeys = fopen("dumpkeys.bin","rb")) == NULL) { if ((fkeys = fopen("dumpkeys.bin","rb")) == NULL) {
PrintAndLog("Could not find file dumpkeys.bin"); PrintAndLog("Could not find file dumpkeys.bin");
fclose(fdump);
return 1; return 1;
} }
for (sectorNo = 0; sectorNo < numSectors; sectorNo++) { for (sectorNo = 0; sectorNo < numSectors; sectorNo++) {
if (fread(keyA[sectorNo], 1, 6, fkeys) == 0) { if (fread(keyA[sectorNo], 1, 6, fkeys) == 0) {
PrintAndLog("File reading error (dumpkeys.bin)."); PrintAndLog("File reading error (dumpkeys.bin).");
fclose(fdump);
fclose(fkeys);
return 2; return 2;
} }
} }
@ -484,16 +679,13 @@ int CmdHF14AMfRestore(const char *Cmd)
for (sectorNo = 0; sectorNo < numSectors; sectorNo++) { for (sectorNo = 0; sectorNo < numSectors; sectorNo++) {
if (fread(keyB[sectorNo], 1, 6, fkeys) == 0) { if (fread(keyB[sectorNo], 1, 6, fkeys) == 0) {
PrintAndLog("File reading error (dumpkeys.bin)."); PrintAndLog("File reading error (dumpkeys.bin).");
fclose(fdump);
fclose(fkeys);
return 2; return 2;
} }
} }
fclose(fkeys); fclose(fkeys);
if ((fdump = fopen("dumpdata.bin","rb")) == NULL) {
PrintAndLog("Could not find file dumpdata.bin");
return 1;
}
PrintAndLog("Restoring dumpdata.bin to card"); PrintAndLog("Restoring dumpdata.bin to card");
for (sectorNo = 0; sectorNo < numSectors; sectorNo++) { for (sectorNo = 0; sectorNo < numSectors; sectorNo++) {
@ -551,7 +743,7 @@ int CmdHF14AMfNested(const char *Cmd)
uint8_t trgKeyType = 0; uint8_t trgKeyType = 0;
uint8_t SectorsCnt = 0; uint8_t SectorsCnt = 0;
uint8_t key[6] = {0, 0, 0, 0, 0, 0}; uint8_t key[6] = {0, 0, 0, 0, 0, 0};
uint8_t keyBlock[13*6]; uint8_t keyBlock[6*6];
uint64_t key64 = 0; uint64_t key64 = 0;
bool transferToEml = false; bool transferToEml = false;
@ -581,15 +773,11 @@ int CmdHF14AMfNested(const char *Cmd)
cmdp = param_getchar(Cmd, 0); cmdp = param_getchar(Cmd, 0);
blockNo = param_get8(Cmd, 1); blockNo = param_get8(Cmd, 1);
ctmp = param_getchar(Cmd, 2); ctmp = param_getchar(Cmd, 2);
if (ctmp != 'a' && ctmp != 'A' && ctmp != 'b' && ctmp != 'B') { if (ctmp != 'a' && ctmp != 'A' && ctmp != 'b' && ctmp != 'B') {
PrintAndLog("Key type must be A or B"); PrintAndLog("Key type must be A or B");
return 1; return 1;
} }
if (ctmp != 'A' && ctmp != 'a') keyType = 1;
if (ctmp != 'A' && ctmp != 'a')
keyType = 1;
if (param_gethex(Cmd, 3, key, 12)) { if (param_gethex(Cmd, 3, key, 12)) {
PrintAndLog("Key must include 12 HEX symbols"); PrintAndLog("Key must include 12 HEX symbols");
return 1; return 1;
@ -603,10 +791,8 @@ int CmdHF14AMfNested(const char *Cmd)
PrintAndLog("Target key type must be A or B"); PrintAndLog("Target key type must be A or B");
return 1; return 1;
} }
if (ctmp != 'A' && ctmp != 'a') if (ctmp != 'A' && ctmp != 'a') trgKeyType = 1;
trgKeyType = 1;
} else { } else {
switch (cmdp) { switch (cmdp) {
case '0': SectorsCnt = 05; break; case '0': SectorsCnt = 05; break;
case '1': SectorsCnt = 16; break; case '1': SectorsCnt = 16; break;
@ -668,14 +854,6 @@ int CmdHF14AMfNested(const char *Cmd)
num_to_bytes(0xa0a1a2a3a4a5, 6, (uint8_t*)(keyBlock + 3 * 6)); num_to_bytes(0xa0a1a2a3a4a5, 6, (uint8_t*)(keyBlock + 3 * 6));
num_to_bytes(0xb0b1b2b3b4b5, 6, (uint8_t*)(keyBlock + 4 * 6)); num_to_bytes(0xb0b1b2b3b4b5, 6, (uint8_t*)(keyBlock + 4 * 6));
num_to_bytes(0xaabbccddeeff, 6, (uint8_t*)(keyBlock + 5 * 6)); num_to_bytes(0xaabbccddeeff, 6, (uint8_t*)(keyBlock + 5 * 6));
num_to_bytes(0x4d3a99c351dd, 6, (uint8_t*)(keyBlock + 6 * 6));
num_to_bytes(0x1a982c7e459a, 6, (uint8_t*)(keyBlock + 7 * 6));
num_to_bytes(0xd3f7d3f7d3f7, 6, (uint8_t*)(keyBlock + 8 * 6));
num_to_bytes(0x714c5c886e97, 6, (uint8_t*)(keyBlock + 9 * 6));
num_to_bytes(0x587ee5f9350f, 6, (uint8_t*)(keyBlock + 10 * 6));
num_to_bytes(0xa0478cc39091, 6, (uint8_t*)(keyBlock + 11 * 6));
num_to_bytes(0x533cb6c723f6, 6, (uint8_t*)(keyBlock + 12 * 6));
num_to_bytes(0x8fd0a4f256e9, 6, (uint8_t*)(keyBlock + 13 * 6));
PrintAndLog("Testing known keys. Sector count=%d", SectorsCnt); PrintAndLog("Testing known keys. Sector count=%d", SectorsCnt);
for (i = 0; i < SectorsCnt; i++) { for (i = 0; i < SectorsCnt; i++) {
@ -691,26 +869,21 @@ int CmdHF14AMfNested(const char *Cmd)
} }
} }
// nested sectors // nested sectors
iterations = 0; iterations = 0;
PrintAndLog("nested..."); PrintAndLog("nested...");
bool calibrate = true; bool calibrate = true;
for (i = 0; i < NESTED_SECTOR_RETRY; i++) { for (i = 0; i < NESTED_SECTOR_RETRY; i++) {
for (uint8_t sectorNo = 0; sectorNo < SectorsCnt; sectorNo++) { for (uint8_t sectorNo = 0; sectorNo < SectorsCnt; sectorNo++) {
if (ukbhit()) {
printf("\naborted via keyboard!\n");
free(e_sector);
return 2;
}
for (trgKeyType = 0; trgKeyType < 2; trgKeyType++) { for (trgKeyType = 0; trgKeyType < 2; trgKeyType++) {
if (e_sector[sectorNo].foundKey[trgKeyType]) continue; if (e_sector[sectorNo].foundKey[trgKeyType]) continue;
PrintAndLog("-----------------------------------------------"); PrintAndLog("-----------------------------------------------");
if(mfnested(blockNo, keyType, key, FirstBlockOfSector(sectorNo), trgKeyType, keyBlock, calibrate)) { if(mfnested(blockNo, keyType, key, FirstBlockOfSector(sectorNo), trgKeyType, keyBlock, calibrate)) {
PrintAndLog("Nested error.\n"); PrintAndLog("Nested error.\n");
free(e_sector); free(e_sector);
return 2; } return 2;
}
else { else {
calibrate = false; calibrate = false;
} }
@ -789,19 +962,17 @@ int CmdHF14AMfNested(const char *Cmd)
int CmdHF14AMfChk(const char *Cmd) int CmdHF14AMfChk(const char *Cmd)
{ {
if (strlen(Cmd)<3) { if (strlen(Cmd)<3) {
PrintAndLog("Usage: hf mf chk <block number>|<*card memory> <key type (A/B/?)> [t|d] [<key (12 hex symbols)>] [<dic (*.dic)>]"); PrintAndLog("Usage: hf mf chk <block number>|<*card memory> <key type (A/B/?)> [t] [<key (12 hex symbols)>] [<dic (*.dic)>]");
PrintAndLog(" * - all sectors"); PrintAndLog(" * - all sectors");
PrintAndLog("card memory - 0 - MINI(320 bytes), 1 - 1K, 2 - 2K, 4 - 4K, <other> - 1K"); PrintAndLog("card memory - 0 - MINI(320 bytes), 1 - 1K, 2 - 2K, 4 - 4K, <other> - 1K");
PrintAndLog("d - write keys to binary file\n"); PrintAndLog("d - write keys to binary file\n");
PrintAndLog("t - write keys to emulator memory");
PrintAndLog(" sample: hf mf chk 0 A 1234567890ab keys.dic"); PrintAndLog(" sample: hf mf chk 0 A 1234567890ab keys.dic");
PrintAndLog(" hf mf chk *1 ? t"); PrintAndLog(" hf mf chk *1 ? t");
PrintAndLog(" hf mf chk *1 ? d");
return 0; return 0;
} }
FILE * f; FILE * f;
char filename[FILE_PATH_SIZE]={0}; char filename[256]={0};
char buf[13]; char buf[13];
uint8_t *keyBlock = NULL, *p; uint8_t *keyBlock = NULL, *p;
uint8_t stKeyBlock = 20; uint8_t stKeyBlock = 20;
@ -893,7 +1064,7 @@ int CmdHF14AMfChk(const char *Cmd)
keycnt++; keycnt++;
} else { } else {
// May be a dic file // May be a dic file
if ( param_getstr(Cmd, 2 + i,filename) >= FILE_PATH_SIZE ) { if ( param_getstr(Cmd, 2 + i,filename) > 255 ) {
PrintAndLog("File name too long"); PrintAndLog("File name too long");
free(keyBlock); free(keyBlock);
return 2; return 2;
@ -944,8 +1115,8 @@ int CmdHF14AMfChk(const char *Cmd)
PrintAndLog("No key specified, trying default keys"); PrintAndLog("No key specified, trying default keys");
for (;keycnt < defaultKeysSize; keycnt++) for (;keycnt < defaultKeysSize; keycnt++)
PrintAndLog("chk default key[%2d] %02x%02x%02x%02x%02x%02x", keycnt, PrintAndLog("chk default key[%2d] %02x%02x%02x%02x%02x%02x", keycnt,
(keyBlock + 6*keycnt)[0],(keyBlock + 6*keycnt)[1], (keyBlock + 6*keycnt)[2], (keyBlock + 6*keycnt)[0],(keyBlock + 6*keycnt)[1], (keyBlock + 6*keycnt)[2],
(keyBlock + 6*keycnt)[3], (keyBlock + 6*keycnt)[4], (keyBlock + 6*keycnt)[5], 6); (keyBlock + 6*keycnt)[3], (keyBlock + 6*keycnt)[4], (keyBlock + 6*keycnt)[5], 6);
} }
// initialize storage for found keys // initialize storage for found keys
@ -990,13 +1161,13 @@ int CmdHF14AMfChk(const char *Cmd)
for (uint16_t t = 0; t < 2; t++) { for (uint16_t t = 0; t < 2; t++) {
if (validKey[t][sectorNo]) { if (validKey[t][sectorNo]) {
memcpy(block + t*10, foundKey[t][sectorNo], 6); memcpy(block + t*10, foundKey[t][sectorNo], 6);
} }
} }
mfEmlSetMem(block, FirstBlockOfSector(sectorNo) + NumBlocksPerSector(sectorNo) - 1, 1); mfEmlSetMem(block, FirstBlockOfSector(sectorNo) + NumBlocksPerSector(sectorNo) - 1, 1);
} }
} }
PrintAndLog("Found keys have been transferred to the emulator memory"); PrintAndLog("Found keys have been transferred to the emulator memory");
} }
if (createDumpFile) { if (createDumpFile) {
FILE *fkeys = fopen("dumpkeys.bin","wb"); FILE *fkeys = fopen("dumpkeys.bin","wb");
@ -1004,7 +1175,7 @@ int CmdHF14AMfChk(const char *Cmd)
PrintAndLog("Could not create file dumpkeys.bin"); PrintAndLog("Could not create file dumpkeys.bin");
free(keyBlock); free(keyBlock);
return 1; return 1;
} }
for (uint16_t t = 0; t < 2; t++) { for (uint16_t t = 0; t < 2; t++) {
fwrite(foundKey[t], 1, 6*SectorsCnt, fkeys); fwrite(foundKey[t], 1, 6*SectorsCnt, fkeys);
} }
@ -1014,7 +1185,7 @@ int CmdHF14AMfChk(const char *Cmd)
free(keyBlock); free(keyBlock);
PrintAndLog(""); PrintAndLog("");
return 0; return 0;
} }
int CmdHF14AMf1kSim(const char *Cmd) int CmdHF14AMf1kSim(const char *Cmd)
@ -1174,44 +1345,26 @@ int CmdHF14AMfESet(const char *Cmd)
int CmdHF14AMfELoad(const char *Cmd) int CmdHF14AMfELoad(const char *Cmd)
{ {
FILE * f; FILE * f;
char filename[FILE_PATH_SIZE]; char filename[20];
char *fnameptr = filename; char *fnameptr = filename;
char buf[64]; char buf[64];
uint8_t buf8[64]; uint8_t buf8[64];
int i, len, blockNum, numBlocks; int i, len, blockNum;
int nameParamNo = 1;
memset(filename, 0, sizeof(filename)); memset(filename, 0, sizeof(filename));
memset(buf, 0, sizeof(buf)); memset(buf, 0, sizeof(buf));
char ctmp = param_getchar(Cmd, 0); if (param_getchar(Cmd, 0) == 'h' || param_getchar(Cmd, 0)== 0x00) {
if ( ctmp == 'h' || ctmp == 0x00) {
PrintAndLog("It loads emul dump from the file `filename.eml`"); PrintAndLog("It loads emul dump from the file `filename.eml`");
PrintAndLog("Usage: hf mf eload [card memory] <file name w/o `.eml`>"); PrintAndLog("Usage: hf mf eload <file name w/o `.eml`>");
PrintAndLog(" [card memory]: 0 = 320 bytes (Mifare Mini), 1 = 1K (default), 2 = 2K, 4 = 4K");
PrintAndLog("");
PrintAndLog(" sample: hf mf eload filename"); PrintAndLog(" sample: hf mf eload filename");
PrintAndLog(" hf mf eload 4 filename");
return 0; return 0;
} }
switch (ctmp) { len = strlen(Cmd);
case '0' : numBlocks = 5*4; break; if (len > 14) len = 14;
case '1' :
case '\0': numBlocks = 16*4; break;
case '2' : numBlocks = 32*4; break;
case '4' : numBlocks = 256; break;
default: {
numBlocks = 16*4;
nameParamNo = 0;
}
}
len = param_getstr(Cmd,nameParamNo,filename);
if (len > FILE_PATH_SIZE) len = FILE_PATH_SIZE;
memcpy(filename, Cmd, len);
fnameptr += len; fnameptr += len;
sprintf(fnameptr, ".eml"); sprintf(fnameptr, ".eml");
@ -1226,16 +1379,14 @@ int CmdHF14AMfELoad(const char *Cmd)
blockNum = 0; blockNum = 0;
while(!feof(f)){ while(!feof(f)){
memset(buf, 0, sizeof(buf)); memset(buf, 0, sizeof(buf));
if (fgets(buf, sizeof(buf), f) == NULL) { if (fgets(buf, sizeof(buf), f) == NULL) {
if((blockNum == 16*4) || (blockNum == 32*4 + 8*16)) { // supports both old (1K) and new (4K) .eml files)
if (blockNum >= numBlocks) break; break;
}
PrintAndLog("File reading error."); PrintAndLog("File reading error.");
fclose(f); fclose(f);
return 2; return 2;
} }
if (strlen(buf) < 32){ if (strlen(buf) < 32){
if(strlen(buf) && feof(f)) if(strlen(buf) && feof(f))
break; break;
@ -1243,7 +1394,6 @@ int CmdHF14AMfELoad(const char *Cmd)
fclose(f); fclose(f);
return 2; return 2;
} }
for (i = 0; i < 32; i += 2) { for (i = 0; i < 32; i += 2) {
sscanf(&buf[i], "%02x", (unsigned int *)&buf8[i / 2]); sscanf(&buf[i], "%02x", (unsigned int *)&buf8[i / 2]);
} }
@ -1255,12 +1405,12 @@ int CmdHF14AMfELoad(const char *Cmd)
} }
blockNum++; blockNum++;
if (blockNum >= numBlocks) break; if (blockNum >= 32*4 + 8*16) break;
} }
fclose(f); fclose(f);
if ((blockNum != numBlocks)) { if ((blockNum != 16*4) && (blockNum != 32*4 + 8*16)) {
PrintAndLog("File content error. Got %d must be %d blocks.",blockNum, numBlocks); PrintAndLog("File content error. There must be 64 or 256 blocks.");
return 4; return 4;
} }
PrintAndLog("Loaded %d blocks from file: %s", blockNum, filename); PrintAndLog("Loaded %d blocks from file: %s", blockNum, filename);
@ -1271,65 +1421,45 @@ int CmdHF14AMfELoad(const char *Cmd)
int CmdHF14AMfESave(const char *Cmd) int CmdHF14AMfESave(const char *Cmd)
{ {
FILE * f; FILE * f;
char filename[FILE_PATH_SIZE]; char filename[20];
char * fnameptr = filename; char * fnameptr = filename;
uint8_t buf[64]; uint8_t buf[64];
int i, j, len, numBlocks; int i, j, len;
int nameParamNo = 1;
memset(filename, 0, sizeof(filename)); memset(filename, 0, sizeof(filename));
memset(buf, 0, sizeof(buf)); memset(buf, 0, sizeof(buf));
char ctmp = param_getchar(Cmd, 0); if (param_getchar(Cmd, 0) == 'h') {
if ( ctmp == 'h') {
PrintAndLog("It saves emul dump into the file `filename.eml` or `cardID.eml`"); PrintAndLog("It saves emul dump into the file `filename.eml` or `cardID.eml`");
PrintAndLog(" Usage: hf mf esave [card memory] [file name w/o `.eml`]"); PrintAndLog("Usage: hf mf esave [file name w/o `.eml`]");
PrintAndLog(" [card memory]: 0 = 320 bytes (Mifare Mini), 1 = 1K (default), 2 = 2K, 4 = 4K");
PrintAndLog("");
PrintAndLog(" sample: hf mf esave "); PrintAndLog(" sample: hf mf esave ");
PrintAndLog(" hf mf esave 4"); PrintAndLog(" hf mf esave filename");
PrintAndLog(" hf mf esave 4 filename");
return 0; return 0;
} }
switch (ctmp) { len = strlen(Cmd);
case '0' : numBlocks = 5*4; break; if (len > 14) len = 14;
case '1' :
case '\0': numBlocks = 16*4; break;
case '2' : numBlocks = 32*4; break;
case '4' : numBlocks = 256; break;
default: {
numBlocks = 16*4;
nameParamNo = 0;
}
}
len = param_getstr(Cmd,nameParamNo,filename);
if (len > FILE_PATH_SIZE) len = FILE_PATH_SIZE;
// user supplied filename?
if (len < 1) { if (len < 1) {
// get filename (UID from memory) // get filename
if (mfEmlGetMem(buf, 0, 1)) { if (mfEmlGetMem(buf, 0, 1)) {
PrintAndLog("Can\'t get UID from block: %d", 0); PrintAndLog("Cant get block: %d", 0);
sprintf(filename, "dump.eml"); return 1;
} }
for (j = 0; j < 7; j++, fnameptr += 2) for (j = 0; j < 7; j++, fnameptr += 2)
sprintf(fnameptr, "%02X", buf[j]); sprintf(fnameptr, "%02x", buf[j]);
} else { } else {
memcpy(filename, Cmd, len);
fnameptr += len; fnameptr += len;
} }
// add file extension
sprintf(fnameptr, ".eml"); sprintf(fnameptr, ".eml");
// open file // open file
f = fopen(filename, "w+"); f = fopen(filename, "w+");
// put hex // put hex
for (i = 0; i < numBlocks; i++) { for (i = 0; i < 32*4 + 8*16; i++) {
if (mfEmlGetMem(buf, i, 1)) { if (mfEmlGetMem(buf, i, 1)) {
PrintAndLog("Cant get block: %d", i); PrintAndLog("Cant get block: %d", i);
break; break;
@ -1340,7 +1470,7 @@ int CmdHF14AMfESave(const char *Cmd)
} }
fclose(f); fclose(f);
PrintAndLog("Saved %d blocks to file: %s", numBlocks, filename); PrintAndLog("Saved to file: %s", filename);
return 0; return 0;
} }
@ -1389,34 +1519,13 @@ int CmdHF14AMfECFill(const char *Cmd)
int CmdHF14AMfEKeyPrn(const char *Cmd) int CmdHF14AMfEKeyPrn(const char *Cmd)
{ {
int i; int i;
uint8_t numSectors;
uint8_t data[16]; uint8_t data[16];
uint64_t keyA, keyB; uint64_t keyA, keyB;
if (param_getchar(Cmd, 0) == 'h') {
PrintAndLog("It prints the keys loaded in the emulator memory");
PrintAndLog("Usage: hf mf ekeyprn [card memory]");
PrintAndLog(" [card memory]: 0 = 320 bytes (Mifare Mini), 1 = 1K (default), 2 = 2K, 4 = 4K");
PrintAndLog("");
PrintAndLog(" sample: hf mf ekeyprn 1");
return 0;
}
char cmdp = param_getchar(Cmd, 0);
switch (cmdp) {
case '0' : numSectors = 5; break;
case '1' :
case '\0': numSectors = 16; break;
case '2' : numSectors = 32; break;
case '4' : numSectors = 40; break;
default: numSectors = 16;
}
PrintAndLog("|---|----------------|----------------|"); PrintAndLog("|---|----------------|----------------|");
PrintAndLog("|sec|key A |key B |"); PrintAndLog("|sec|key A |key B |");
PrintAndLog("|---|----------------|----------------|"); PrintAndLog("|---|----------------|----------------|");
for (i = 0; i < numSectors; i++) { for (i = 0; i < 40; i++) {
if (mfEmlGetMem(data, FirstBlockOfSector(i) + NumBlocksPerSector(i) - 1, 1)) { if (mfEmlGetMem(data, FirstBlockOfSector(i) + NumBlocksPerSector(i) - 1, 1)) {
PrintAndLog("error get block %d", FirstBlockOfSector(i) + NumBlocksPerSector(i) - 1); PrintAndLog("error get block %d", FirstBlockOfSector(i) + NumBlocksPerSector(i) - 1);
break; break;
@ -1458,9 +1567,9 @@ int CmdHF14AMfCSetUID(const char *Cmd)
res = mfCSetUID(uid, oldUid, wipeCard); res = mfCSetUID(uid, oldUid, wipeCard);
if (res) { if (res) {
PrintAndLog("Can't set UID. error=%d", res); PrintAndLog("Can't set UID. error=%d", res);
return 1; return 1;
} }
PrintAndLog("old UID:%s", sprint_hex(oldUid, 4)); PrintAndLog("old UID:%s", sprint_hex(oldUid, 4));
PrintAndLog("new UID:%s", sprint_hex(uid, 4)); PrintAndLog("new UID:%s", sprint_hex(uid, 4));
@ -1506,7 +1615,7 @@ int CmdHF14AMfCSetBlk(const char *Cmd)
int CmdHF14AMfCLoad(const char *Cmd) int CmdHF14AMfCLoad(const char *Cmd)
{ {
FILE * f; FILE * f;
char filename[FILE_PATH_SIZE]; char filename[20];
char * fnameptr = filename; char * fnameptr = filename;
char buf[64]; char buf[64];
uint8_t buf8[64]; uint8_t buf8[64];
@ -1547,7 +1656,7 @@ int CmdHF14AMfCLoad(const char *Cmd)
return 0; return 0;
} else { } else {
len = strlen(Cmd); len = strlen(Cmd);
if (len > FILE_PATH_SIZE) len = FILE_PATH_SIZE; if (len > 14) len = 14;
memcpy(filename, Cmd, len); memcpy(filename, Cmd, len);
fnameptr += len; fnameptr += len;
@ -1592,7 +1701,7 @@ int CmdHF14AMfCLoad(const char *Cmd)
} }
fclose(f); fclose(f);
if (blockNum != 16 * 4 && blockNum != 32 * 4 + 8 * 16){ if (blockNum != 16 * 4){
PrintAndLog("File content error. There must be 64 blocks"); PrintAndLog("File content error. There must be 64 blocks");
return 4; return 4;
} }
@ -1670,7 +1779,7 @@ int CmdHF14AMfCGetSc(const char *Cmd) {
int CmdHF14AMfCSave(const char *Cmd) { int CmdHF14AMfCSave(const char *Cmd) {
FILE * f; FILE * f;
char filename[FILE_PATH_SIZE]; char filename[20];
char * fnameptr = filename; char * fnameptr = filename;
uint8_t fillFromEmulator = 0; uint8_t fillFromEmulator = 0;
uint8_t buf[64]; uint8_t buf[64];
@ -1712,7 +1821,7 @@ int CmdHF14AMfCSave(const char *Cmd) {
return 0; return 0;
} else { } else {
len = strlen(Cmd); len = strlen(Cmd);
if (len > FILE_PATH_SIZE) len = FILE_PATH_SIZE; if (len > 14) len = 14;
if (len < 1) { if (len < 1) {
// get filename // get filename
@ -1876,7 +1985,7 @@ int CmdHF14AMfSniff(const char *Cmd){
mfTraceDecode(bufPtr, len, wantSaveToEmlFile); mfTraceDecode(bufPtr, len, wantSaveToEmlFile);
} }
bufPtr += len; bufPtr += len;
bufPtr += ((len-1)/8+1); // ignore parity bufPtr += ((len-1)/8+1); // ignore parity
num++; num++;
} }
} }
@ -1886,106 +1995,14 @@ int CmdHF14AMfSniff(const char *Cmd){
return 0; return 0;
} }
// Tries to identify cardsize.
// Returns <num> where num is:
// -1 unidentified
// 0 - MINI (320bytes)
// 1 - 1K
// 2 - 2K
// 4 - 4K
int GetCardSize()
{
UsbCommand c = {CMD_READER_ISO_14443a, {ISO14A_CONNECT, 0, 0}};
SendCommand(&c);
UsbCommand resp;
WaitForResponse(CMD_ACK,&resp);
if(resp.arg[0] == 0) {
PrintAndLog("iso14443a card select failed");
return -1;
}
iso14a_card_select_t *card = (iso14a_card_select_t *)resp.d.asBytes;
PrintAndLog("Trying to detect card size.");
uint16_t atqa = 0;
uint8_t sak = 0;
atqa = (card->atqa[1] & 0xff) << 8;
atqa += card->atqa[0] & 0xff;
sak = card->sak;
// https://code.google.com/p/libnfc/source/browse/libnfc/target-subr.c
PrintAndLog("found ATAQ: %04X SAK: %02X", atqa, sak);
// NXP MIFARE Mini 0.3k
if ( ( (atqa & 0xff0f) == 0x0004) && (sak == 0x09) ) return 0;
// MIFARE Classic 1K
if ( ((atqa & 0xff0f) == 0x0004) && (sak == 0x08) ) return 1;
// MIFARE Classik 4K
if ( ((atqa & 0xff0f) == 0x0002) && (sak == 0x18) ) return 4;
// SmartMX with MIFARE 1K emulation
if ( ((atqa & 0xf0ff) == 0x0004) ) return 1;
// SmartMX with MIFARE 4K emulation
if ( ((atqa & 0xf0ff) == 0x0002) ) return 4;
// Infineon MIFARE CLASSIC 1K
if ( ((atqa & 0xffff) == 0x0004) && (sak == 0x88) ) return 1;
// MFC 4K emulated by Nokia 6212 Classic
if ( ((atqa & 0xffff) == 0x0002) && (sak == 0x38) ) return 4;
// MFC 4K emulated by Nokia 6131 NFC
if ( ((atqa & 0xffff) == 0x0008) && (sak == 0x38) ) return 4;
PrintAndLog("BEFOOO 1K %02X", (atqa & 0xff0f));
// MIFARE Plus (4 Byte UID or 4 Byte RID)
// MIFARE Plus (7 Byte UID)
if (
((atqa & 0xffff) == 0x0002) |
((atqa & 0xffff) == 0x0004) |
((atqa & 0xffff) == 0x0042) |
((atqa & 0xffff) == 0x0044)
)
{
switch(sak){
case 0x08:
case 0x10: {
//case 0x20:
PrintAndLog("2");
return 2;
break;
}
case 0x11:
case 0x18:{
//case 0x20:
PrintAndLog("4");
return 4;
break;
}
}
}
return -1;
}
static command_t CommandTable[] = static command_t CommandTable[] =
{ {
{"help", CmdHelp, 1, "This help"}, {"help", CmdHelp, 1, "This help"},
{"dbg", CmdHF14AMfDbg, 0, "Set default debug mode"}, {"dbg", CmdHF14AMfDbg, 0, "Set default debug mode"},
{"rdbl", CmdHF14AMfRdBl, 0, "Read MIFARE classic block"}, {"rdbl", CmdHF14AMfRdBl, 0, "Read MIFARE classic block"},
//{"urdbl", CmdHF14AMfURdBl, 0, "Read MIFARE Ultralight block"}, {"urdbl", CmdHF14AMfURdBl, 0, "Read MIFARE Ultralight block"},
//{"urdcard", CmdHF14AMfURdCard, 0,"Read MIFARE Ultralight Card"}, {"urdcard", CmdHF14AMfURdCard, 0,"Read MIFARE Ultralight Card"},
//{"uwrbl", CmdHF14AMfUWrBl, 0,"Write MIFARE Ultralight block"}, {"uwrbl", CmdHF14AMfUWrBl, 0,"Write MIFARE Ultralight block"},
{"rdsc", CmdHF14AMfRdSc, 0, "Read MIFARE classic sector"}, {"rdsc", CmdHF14AMfRdSc, 0, "Read MIFARE classic sector"},
{"dump", CmdHF14AMfDump, 0, "Dump MIFARE classic tag to binary file"}, {"dump", CmdHF14AMfDump, 0, "Dump MIFARE classic tag to binary file"},
{"restore", CmdHF14AMfRestore, 0, "Restore MIFARE classic binary file to BLANK tag"}, {"restore", CmdHF14AMfRestore, 0, "Restore MIFARE classic binary file to BLANK tag"},

View file

@ -16,11 +16,11 @@
#include <string.h> #include <string.h>
#include <ctype.h> #include <ctype.h>
#include "proxmark3.h" #include "proxmark3.h"
#include "../common/iso14443crc.h" #include "iso14443crc.h"
#include "data.h" #include "data.h"
#include "ui.h" #include "ui.h"
#include "cmdparser.h" #include "cmdparser.h"
#include "../include/common.h" #include "common.h"
#include "util.h" #include "util.h"
#include "mifarehost.h" #include "mifarehost.h"
@ -53,5 +53,5 @@ int CmdHF14AMfCGetBlk(const char* cmd);
int CmdHF14AMfCGetSc(const char* cmd); int CmdHF14AMfCGetSc(const char* cmd);
int CmdHF14AMfCLoad(const char* cmd); int CmdHF14AMfCLoad(const char* cmd);
int CmdHF14AMfCSave(const char* cmd); int CmdHF14AMfCSave(const char* cmd);
int GetCardSize();
#endif #endif

View file

@ -1,685 +0,0 @@
//-----------------------------------------------------------------------------
// Copyright (C) 2014 Iceman
//
// 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.
//-----------------------------------------------------------------------------
// High frequency MIFARE Desfire commands
//-----------------------------------------------------------------------------
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <openssl/des.h>
#include "cmdmain.h"
#include "proxmark3.h"
#include "../include/common.h"
#include "../include/mifare.h"
#include "../common/iso14443crc.h"
#include "data.h"
#include "ui.h"
#include "cmdparser.h"
#include "util.h"
#include "cmdhfmfdes.h"
uint8_t CMDPOS = 0;
uint8_t LENPOS = 1;
uint8_t key_zero_data[16] = { 0x00 };
uint8_t key_ones_data[16] = { 0x01 };
uint8_t key_defa_data[16] = { 0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f };
uint8_t key_picc_data[16] = { 0x40,0x41,0x42,0x43,0x44,0x45,0x46,0x47,0x48,0x49,0x4a,0x4b,0x4c,0x4d,0x4e,0x4f };
static int CmdHelp(const char *Cmd);
static void xor(unsigned char * dst, unsigned char * src, size_t len);
static int32_t le24toh (uint8_t data[3]);
int CmdHF14ADesWb(const char *Cmd)
{
/* uint8_t blockNo = 0;
uint8_t keyType = 0;
uint8_t key[6] = {0, 0, 0, 0, 0, 0};
uint8_t bldata[16] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
char cmdp = 0x00;
if (strlen(Cmd)<3) {
PrintAndLog("Usage: hf mf wrbl <block number> <key A/B> <key (12 hex symbols)> <block data (32 hex symbols)>");
PrintAndLog(" sample: hf mf wrbl 0 A FFFFFFFFFFFF 000102030405060708090A0B0C0D0E0F");
return 0;
}
blockNo = param_get8(Cmd, 0);
cmdp = param_getchar(Cmd, 1);
if (cmdp == 0x00) {
PrintAndLog("Key type must be A or B");
return 1;
}
if (cmdp != 'A' && cmdp != 'a') keyType = 1;
if (param_gethex(Cmd, 2, key, 12)) {
PrintAndLog("Key must include 12 HEX symbols");
return 1;
}
if (param_gethex(Cmd, 3, bldata, 32)) {
PrintAndLog("Block data must include 32 HEX symbols");
return 1;
}
PrintAndLog("--block no:%02x key type:%02x key:%s", blockNo, keyType, sprint_hex(key, 6));
PrintAndLog("--data: %s", sprint_hex(bldata, 16));
UsbCommand c = {CMD_MIFARE_WRITEBL, {blockNo, keyType, 0}};
memcpy(c.d.asBytes, key, 6);
memcpy(c.d.asBytes + 10, bldata, 16);
SendCommand(&c);
UsbCommand resp;
if (WaitForResponseTimeout(CMD_ACK,&resp,1500)) {
uint8_t isOK = resp.arg[0] & 0xff;
PrintAndLog("isOk:%02x", isOK);
} else {
PrintAndLog("Command execute timeout");
}
*/
return 0;
}
int CmdHF14ADesRb(const char *Cmd)
{
// uint8_t blockNo = 0;
// uint8_t keyType = 0;
// uint8_t key[6] = {0, 0, 0, 0, 0, 0};
// char cmdp = 0x00;
// if (strlen(Cmd)<3) {
// PrintAndLog("Usage: hf mf rdbl <block number> <key A/B> <key (12 hex symbols)>");
// PrintAndLog(" sample: hf mf rdbl 0 A FFFFFFFFFFFF ");
// return 0;
// }
// blockNo = param_get8(Cmd, 0);
// cmdp = param_getchar(Cmd, 1);
// if (cmdp == 0x00) {
// PrintAndLog("Key type must be A or B");
// return 1;
// }
// if (cmdp != 'A' && cmdp != 'a') keyType = 1;
// if (param_gethex(Cmd, 2, key, 12)) {
// PrintAndLog("Key must include 12 HEX symbols");
// return 1;
// }
// PrintAndLog("--block no:%02x key type:%02x key:%s ", blockNo, keyType, sprint_hex(key, 6));
// UsbCommand c = {CMD_MIFARE_READBL, {blockNo, keyType, 0}};
// memcpy(c.d.asBytes, key, 6);
// SendCommand(&c);
// UsbCommand resp;
// if (WaitForResponseTimeout(CMD_ACK,&resp,1500)) {
// uint8_t isOK = resp.arg[0] & 0xff;
// uint8_t * data = resp.d.asBytes;
// if (isOK)
// PrintAndLog("isOk:%02x data:%s", isOK, sprint_hex(data, 16));
// else
// PrintAndLog("isOk:%02x", isOK);
// } else {
// PrintAndLog("Command execute timeout");
// }
return 0;
}
int CmdHF14ADesInfo(const char *Cmd){
UsbCommand c = {CMD_MIFARE_DESFIRE_INFO};
SendCommand(&c);
UsbCommand resp;
if ( !WaitForResponseTimeout(CMD_ACK,&resp,1500) ) {
PrintAndLog("Command execute timeout");
return 0;
}
uint8_t isOK = resp.arg[0] & 0xff;
if ( !isOK ){
PrintAndLog("Command unsuccessful");
return 0;
}
PrintAndLog("");
PrintAndLog("-- Desfire Information --------------------------------------");
PrintAndLog("-------------------------------------------------------------");
PrintAndLog(" UID : %s",sprint_hex(resp.d.asBytes, 7));
PrintAndLog(" Batch number : %s",sprint_hex(resp.d.asBytes+28,5));
PrintAndLog(" Production date : week %02x, 20%02x",resp.d.asBytes[33], resp.d.asBytes[34]);
PrintAndLog(" -----------------------------------------------------------");
PrintAndLog(" Hardware Information");
PrintAndLog(" Vendor Id : %s", GetVendorStr(resp.d.asBytes[7]));
PrintAndLog(" Type : 0x%02X",resp.d.asBytes[8]);
PrintAndLog(" Subtype : 0x%02X",resp.d.asBytes[9]);
PrintAndLog(" Version : %d.%d",resp.d.asBytes[10], resp.d.asBytes[11]);
PrintAndLog(" Storage size : %s",GetCardSizeStr(resp.d.asBytes[12]));
PrintAndLog(" Protocol : %s",GetProtocolStr(resp.d.asBytes[13]));
PrintAndLog(" -----------------------------------------------------------");
PrintAndLog(" Software Information");
PrintAndLog(" Vendor Id : %s",GetVendorStr(resp.d.asBytes[14]));
PrintAndLog(" Type : 0x%02X",resp.d.asBytes[15]);
PrintAndLog(" Subtype : 0x%02X",resp.d.asBytes[16]);
PrintAndLog(" Version : %d.%d",resp.d.asBytes[17], resp.d.asBytes[18]);
PrintAndLog(" storage size : %s", GetCardSizeStr(resp.d.asBytes[19]));
PrintAndLog(" Protocol : %s", GetProtocolStr(resp.d.asBytes[20]));
PrintAndLog("-------------------------------------------------------------");
// Master Key settings
GetKeySettings(NULL);
// Free memory on card
c.cmd = CMD_MIFARE_DESFIRE;
c.arg[0] = (INIT | DISCONNECT);
c.arg[1] = 0x01;
c.d.asBytes[0] = GET_FREE_MEMORY;
SendCommand(&c);
if ( !WaitForResponseTimeout(CMD_ACK,&resp,1500)) {
return 0;
}
uint8_t tmp[3];
memcpy(tmp, resp.d.asBytes+3,3);
PrintAndLog(" Available free memory on card : %d bytes", le24toh( tmp ));
PrintAndLog("-------------------------------------------------------------");
/*
Card Master key (CMK) 0x00 AID = 00 00 00 (card level)
Application Master Key (AMK) 0x00 AID != 00 00 00
Application keys (APK) 0x01-0x0D
Application free 0x0E
Application never 0x0F
ACCESS RIGHTS:
keys 0,1,2,3 C
keys 4,5,6,7 RW
keys 8,9,10,11 W
keys 12,13,14,15 R
*/
return 1;
}
char * GetVendorStr( uint8_t id){
static char buf[30];
char *retStr = buf;
if ( id == 0x04 )
sprintf(retStr, "0x%02X (NXP)",id);
else
sprintf(retStr,"0x%02X (Unknown)",id);
return buf;
}
/*
The 7 MSBits (= n) code the storage size itself based on 2^n,
the LSBit is set to '0' if the size is exactly 2^n
and set to '1' if the storage size is between 2^n and 2^(n+1).
For this version of DESFire the 7 MSBits are set to 0x0C (2^12 = 4096) and the LSBit is '0'.
*/
char * GetCardSizeStr( uint8_t fsize ){
static char buf[30];
char *retStr = buf;
uint16_t usize = 1 << ((fsize >>1) + 1);
uint16_t lsize = 1 << (fsize >>1);
// is LSB set?
if ( fsize & (1 << 0 ) )
sprintf(retStr, "0x%02X (%d - %d bytes)",fsize, usize, lsize);
else
sprintf(retStr, "0x%02X (%d bytes)", fsize, lsize);
return buf;
}
char * GetProtocolStr(uint8_t id){
static char buf[30];
char *retStr = buf;
if ( id == 0x05)
sprintf(retStr,"0x%02X (ISO 14443-3, 14443-4)", id);
else
sprintf(retStr,"0x%02X", id);
return buf;
}
void GetKeySettings( uint8_t *aid){
char messStr[512] = {0x00};
char *str = messStr;
uint8_t isOK = 0;
uint32_t options = NONE;
UsbCommand c;
UsbCommand resp;
//memset(messStr, 0x00, 512);
c.cmd = CMD_MIFARE_DESFIRE;
if ( aid == NULL ){
PrintAndLog(" CMK - PICC, Card Master Key settings ");
PrintAndLog("");
c.arg[CMDPOS] = (INIT | DISCONNECT);
c.arg[LENPOS] = 0x01;
c.d.asBytes[0] = GET_KEY_SETTINGS; // 0x45
SendCommand(&c);
if ( !WaitForResponseTimeout(CMD_ACK,&resp,1000) ) {return;}
isOK = resp.arg[0] & 0xff;
if ( !isOK ){
PrintAndLog(" Can't select master application");
return;
}
str = (resp.d.asBytes[3] & (1 << 3 )) ? "YES":"NO";
PrintAndLog(" [0x08] Configuration changeable : %s", str);
str = (resp.d.asBytes[3] & (1 << 2 )) ? "NO":"YES";
PrintAndLog(" [0x04] CMK required for create/delete : %s",str);
str = (resp.d.asBytes[3] & (1 << 1 )) ? "NO":"YES";
PrintAndLog(" [0x02] Directory list access with CMK : %s",str);
str = (resp.d.asBytes[3] & (1 << 0 )) ? "YES" : "NO";
PrintAndLog(" [0x01] CMK is changeable : %s", str);
c.arg[LENPOS] = 0x02; //LEN
c.d.asBytes[0] = GET_KEY_VERSION; //0x64
c.d.asBytes[1] = 0x00;
SendCommand(&c);
if ( !WaitForResponseTimeout(CMD_ACK,&resp,1000) ) {
return;
}
isOK = resp.arg[0] & 0xff;
if ( !isOK ){
PrintAndLog(" Can't read key-version");
return;
}
PrintAndLog("");
PrintAndLog(" Max number of keys : %d", resp.d.asBytes[4]);
PrintAndLog(" Master key Version : %d (0x%02x)", resp.d.asBytes[3], resp.d.asBytes[3]);
PrintAndLog(" ----------------------------------------------------------");
c.arg[LENPOS] = 0x02; //LEN
c.d.asBytes[0] = AUTHENTICATE; //0x0A
c.d.asBytes[1] = 0x00; // KEY 0
SendCommand(&c);
if ( !WaitForResponseTimeout(CMD_ACK,&resp,1000) ) {return;}
isOK = resp.d.asBytes[2] & 0xff;
PrintAndLog(" [0x0A] Authenticate : %s", ( isOK==0xAE ) ? "NO":"YES");
c.d.asBytes[0] = AUTHENTICATE_ISO; //0x1A
SendCommand(&c);
if ( !WaitForResponseTimeout(CMD_ACK,&resp,1000) ) {return;}
isOK = resp.d.asBytes[2] & 0xff;
PrintAndLog(" [0x1A] Authenticate ISO : %s", ( isOK==0xAE ) ? "NO":"YES");
c.d.asBytes[0] = AUTHENTICATE_AES; //0xAA
SendCommand(&c);
if ( !WaitForResponseTimeout(CMD_ACK,&resp,1000) ) {return;}
isOK = resp.d.asBytes[2] & 0xff;
PrintAndLog(" [0xAA] Authenticate AES : %s", ( isOK==0xAE ) ? "NO":"YES");
PrintAndLog("");
PrintAndLog(" ----------------------------------------------------------");
} else {
PrintAndLog(" AMK - Application Master Key settings");
// SELECT AID
c.arg[0] = (INIT | CLEARTRACE);
c.arg[LENPOS] = 0x04;
c.d.asBytes[0] = SELECT_APPLICATION; // 0x5a
memcpy(c.d.asBytes+1, aid, 3);
SendCommand(&c);
if (!WaitForResponseTimeout(CMD_ACK,&resp,1500) ) {
PrintAndLog(" Timed-out");
return;
}
isOK = resp.arg[0] & 0xff;
if ( !isOK ){
PrintAndLog(" Can't select AID: %s",sprint_hex(aid,3));
return;
}
// KEY SETTINGS
options = NONE;
c.arg[0] = options;
c.arg[LENPOS] = 0x01;
c.d.asBytes[0] = GET_KEY_SETTINGS; // 0x45
SendCommand(&c);
if ( !WaitForResponseTimeout(CMD_ACK,&resp,1500) ) {
return;
}
isOK = resp.arg[0] & 0xff;
if ( !isOK ){
PrintAndLog(" Can't read Application Master key settings");
} else {
// Access rights.
uint8_t rights = (resp.d.asBytes[3] >> 4 && 0xff);
switch (rights){
case 0x00:
str = "AMK authentication is necessary to change any key (default)";
break;
case 0x0e:
str = "Authentication with the key to be changed (same KeyNo) is necessary to change a key";
break;
case 0x0f:
str = "All keys (except AMK,see Bit0) within this application are frozen";
break;
default:
str = "Authentication with the specified key is necessary to change any ley. A change key and a PICC master key (CMK) can only be changed after authentication with the master key. For keys other then the master or change key, an authentication with the same key is needed.";
break;
}
PrintAndLog("Changekey Access rights");
PrintAndLog("-- %s",str);
PrintAndLog("");
// same as CMK
str = (resp.d.asBytes[3] & (1 << 3 )) ? "YES":"NO";
PrintAndLog(" 0x08 Configuration changeable : %s", str);
str = (resp.d.asBytes[3] & (1 << 2 )) ? "NO":"YES";
PrintAndLog(" 0x04 AMK required for create/delete : %s",str);
str = (resp.d.asBytes[3] & (1 << 1 )) ? "NO":"YES";
PrintAndLog(" 0x02 Directory list access with AMK : %s",str);
str = (resp.d.asBytes[3] & (1 << 0 )) ? "YES" : "NO";
PrintAndLog(" 0x01 AMK is changeable : %s", str);
}
// KEY VERSION - AMK
c.arg[0] = NONE;
c.arg[LENPOS] = 0x02;
c.d.asBytes[0] = GET_KEY_VERSION; //0x64
c.d.asBytes[1] = 0x00;
SendCommand(&c);
if ( !WaitForResponseTimeout(CMD_ACK,&resp,1500) ) {
PrintAndLog(" Timed-out");
return;
}
int numOfKeys;
isOK = resp.arg[0] & 0xff;
if ( !isOK ){
PrintAndLog(" Can't read Application Master key version. Trying all keys");
numOfKeys = MAX_NUM_KEYS;
}
else{
numOfKeys = resp.d.asBytes[4];
PrintAndLog("");
PrintAndLog(" Max number of keys : %d", numOfKeys );
PrintAndLog(" Application Master key Version : %d (0x%02x)", resp.d.asBytes[3], resp.d.asBytes[3]);
PrintAndLog("-------------------------------------------------------------");
}
// LOOP over numOfKeys that we got before.
// From 0x01 to numOfKeys. We already got 0x00. (AMK)
for(int i=0x01; i<=0x0f; ++i){
}
}
}
int CmdHF14ADesEnumApplications(const char *Cmd){
uint8_t isOK = 0x00;
uint8_t aid[3];
uint32_t options = (INIT | DISCONNECT);
UsbCommand c = {CMD_MIFARE_DESFIRE, {options , 0x01 }};
c.d.asBytes[0] = GET_APPLICATION_IDS; //0x6a
SendCommand(&c);
UsbCommand resp;
if ( !WaitForResponseTimeout(CMD_ACK,&resp,1500) ) {
return 0;
}
isOK = resp.arg[0] & 0xff;
if ( !isOK ){
PrintAndLog("Command unsuccessful");
return 0;
}
PrintAndLog("");
PrintAndLog("-- Desfire Enumerate Applications ---------------------------");
PrintAndLog("-------------------------------------------------------------");
UsbCommand respAid;
UsbCommand respFiles;
uint8_t num = 0;
int max = resp.arg[1] -3 -2;
for(int i=3; i<=max; i+=3){
PrintAndLog(" Aid %d : %02X %02X %02X ",num ,resp.d.asBytes[i],resp.d.asBytes[i+1],resp.d.asBytes[i+2]);
num++;
aid[0] = resp.d.asBytes[i];
aid[1] = resp.d.asBytes[i+1];
aid[2] = resp.d.asBytes[i+2];
GetKeySettings(aid);
// Select Application
c.arg[CMDPOS] = INIT;
c.arg[LENPOS] = 0x04;
c.d.asBytes[0] = SELECT_APPLICATION; // 0x5a
c.d.asBytes[1] = resp.d.asBytes[i];
c.d.asBytes[2] = resp.d.asBytes[i+1];
c.d.asBytes[3] = resp.d.asBytes[i+2];
SendCommand(&c);
if (!WaitForResponseTimeout(CMD_ACK,&respAid,1500) ) {
PrintAndLog(" Timed-out");
continue;
}
isOK = respAid.d.asBytes[2] & 0xff;
if ( isOK != 0x00 ){
PrintAndLog(" Can't select AID: %s",sprint_hex(resp.d.asBytes+i,3));
continue;
}
// Get File IDs
c.arg[CMDPOS] = NONE;
c.arg[LENPOS] = 0x01;
c.d.asBytes[0] = GET_FILE_IDS; // 0x6f
SendCommand(&c);
if ( !WaitForResponseTimeout(CMD_ACK,&respFiles,1500) ) {
PrintAndLog(" Timed-out");
continue;
} else {
isOK = respFiles.d.asBytes[2] & 0xff;
if ( !isOK ){
PrintAndLog(" Can't get file ids ");
} else {
int respfileLen = resp.arg[1]-3-2;
for (int j=0; j< respfileLen; ++j){
PrintAndLog(" Fileid %d :", resp.d.asBytes[j+3]);
}
}
}
// Get ISO File IDs
c.arg[CMDPOS] = DISCONNECT;
c.arg[LENPOS] = 0x01;
c.d.asBytes[0] = GET_ISOFILE_IDS; // 0x61
SendCommand(&c);
if ( !WaitForResponseTimeout(CMD_ACK,&respFiles,1500) ) {
PrintAndLog(" Timed-out");
continue;
} else {
isOK = respFiles.d.asBytes[2] & 0xff;
if ( !isOK ){
PrintAndLog(" Can't get ISO file ids ");
} else {
int respfileLen = resp.arg[1]-3-2;
for (int j=0; j< respfileLen; ++j){
PrintAndLog(" ISO Fileid %d :", resp.d.asBytes[j+3]);
}
}
}
}
PrintAndLog("-------------------------------------------------------------");
return 1;
}
// MIAFRE DesFire Authentication
//
#define BUFSIZE 256
int CmdHF14ADesAuth(const char *Cmd){
// NR DESC KEYLENGHT
// ------------------------
// 1 = DES 8
// 2 = 3DES 16
// 3 = 3K 3DES 24
// 4 = AES 16
uint8_t keylength = 8;
unsigned char key[24];
if (strlen(Cmd)<3) {
PrintAndLog("Usage: hf mfdes auth <1|2|3> <1|2|3|4> <keyno> <key> ");
PrintAndLog(" Auth modes");
PrintAndLog(" 1 = normal, 2 = iso, 3 = aes");
PrintAndLog(" Crypto");
PrintAndLog(" 1 = DES 2 = 3DES 3 = 3K3DES 4 = AES");
PrintAndLog("");
PrintAndLog(" sample: hf mfdes auth 1 1 0 11223344");
PrintAndLog(" sample: hf mfdes auth 3 4 0 404142434445464748494a4b4c4d4e4f");
return 0;
}
uint8_t cmdAuthMode = param_get8(Cmd,0);
uint8_t cmdAuthAlgo = param_get8(Cmd,1);
uint8_t cmdKeyNo = param_get8(Cmd,2);
switch (cmdAuthMode)
{
case 1:
if ( cmdAuthAlgo != 1 && cmdAuthAlgo != 2) {
PrintAndLog("Crypto algo not valid for the auth mode");
return 1;
}
break;
case 2:
if ( cmdAuthAlgo != 1 && cmdAuthAlgo != 2 && cmdAuthAlgo != 3) {
PrintAndLog("Crypto algo not valid for the auth mode");
return 1;
}
break;
case 3:
if ( cmdAuthAlgo != 4) {
PrintAndLog("Crypto algo not valid for the auth mode");
return 1;
}
break;
default:
PrintAndLog("Wrong Auth mode");
return 1;
break;
}
switch (cmdAuthAlgo){
case 2:
keylength = 16;
PrintAndLog("3DES selected");
break;
case 3:
keylength = 24;
PrintAndLog("3 key 3DES selected");
break;
case 4:
keylength = 16;
PrintAndLog("AES selected");
break;
default:
cmdAuthAlgo = 1;
keylength = 8;
PrintAndLog("DES selected");
break;
}
// key
if (param_gethex(Cmd, 3, key, keylength*2)) {
PrintAndLog("Key must include %d HEX symbols", keylength);
return 1;
}
// algo, nyckellängd,
UsbCommand c = {CMD_MIFARE_DESFIRE_AUTH1, { cmdAuthMode, cmdAuthAlgo, cmdKeyNo }};
c.d.asBytes[0] = keylength;
memcpy(c.d.asBytes+1, key, keylength);
SendCommand(&c);
UsbCommand resp;
if (!WaitForResponseTimeout(CMD_ACK,&resp,3000)) {
PrintAndLog("Client command execute timeout");
return 0;
}
uint8_t isOK = resp.arg[0] & 0xff;
if ( isOK) {
uint8_t * data= resp.d.asBytes;
PrintAndLog(" Key :%s",sprint_hex(key, keylength));
PrintAndLog(" SESSION :%s",sprint_hex(data, keylength));
PrintAndLog("-------------------------------------------------------------");
//PrintAndLog(" Expected :B5 21 9E E8 1A A7 49 9D 21 96 68 7E 13 97 38 56");
} else{
PrintAndLog("Client command failed.");
}
PrintAndLog("-------------------------------------------------------------");
return 1;
}
static void xor(unsigned char * dst, unsigned char * src, size_t len) {
for( ; len > 0; len--,dst++,src++)
*dst ^= *src;
}
static int32_t le24toh (uint8_t data[3]) {
return (data[2] << 16) | (data[1] << 8) | data[0];
}
static command_t CommandTable[] =
{
{"help", CmdHelp, 1, "This help"},
{"auth", CmdHF14ADesAuth, 0, "Tries a MIFARE DesFire Authentication"},
{"rb", CmdHF14ADesRb, 0, "Read MIFARE DesFire block"},
{"wb", CmdHF14ADesWb, 0, "write MIFARE DesFire block"},
{"info", CmdHF14ADesInfo, 0, "Get MIFARE DesFire information"},
{"enum", CmdHF14ADesEnumApplications,0, "Tries enumerate all applications"},
{NULL, NULL, 0, NULL}
};
int CmdHFMFDes(const char *Cmd)
{
// flush
WaitForResponseTimeout(CMD_ACK,NULL,100);
CmdsParse(CommandTable, Cmd);
return 0;
}
int CmdHelp(const char *Cmd)
{
CmdsHelp(CommandTable);
return 0;
}

View file

@ -1,75 +0,0 @@
//-----------------------------------------------------------------------------
// Copyright (C) 2014 Iceman
//
// 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.
//-----------------------------------------------------------------------------
// High frequency MIFARE Desfire commands
//-----------------------------------------------------------------------------
int CmdHFMFDes(const char *Cmd);
int CmdHF14ADesAuth(const char* cmd);
int CmdHF14ADesRb(const char* cmd);
int CmdHF14ADesWb(const char* cmd);
int CmdHF14ADesInfo(const char *Cmd);
int CmdHF14ADesEnumApplications(const char *Cmd);
char * GetCardSizeStr( uint8_t fsize );
char * GetVendorStr( uint8_t id);
char * GetProtocolStr(uint8_t id);
void GetKeySettings( uint8_t * aid);
// Command options for Desfire behavior.
enum {
NONE = 0x00,
INIT = 0x01,
DISCONNECT = 0x02,
CLEARTRACE = 0x04,
BAR = 0x08,
} CmdOptions ;
#define CREATE_APPLICATION 0xca
#define DELETE_APPLICATION 0xda
#define GET_APPLICATION_IDS 0x6a
#define SELECT_APPLICATION 0x5a
#define FORMAT_PICC 0xfc
#define GET_VERSION 0x60
#define READ_DATA 0xbd
#define WRITE_DATA 0x3d
#define GET_VALUE 0x6c
#define CREDIT 0x0c
#define DEBIT 0xdc
#define LIMITED_CREDIT 0x1c
#define WRITE_RECORD 0x3b
#define READ_RECORDS 0xbb
#define CLEAR_RECORD_FILE 0xeb
#define COMMIT_TRANSACTION 0xc7
#define ABORT_TRANSACTION 0xa7
#define GET_FREE_MEMORY 0x6e
#define GET_FILE_IDS 0x6f
#define GET_ISOFILE_IDS 0x61
#define GET_FILE_SETTINGS 0xf5
#define CHANGE_FILE_SETTINGS 0x5f
#define CREATE_STD_DATA_FILE 0xcd
#define CREATE_BACKUP_DATA_FILE 0xcb
#define CREATE_VALUE_FILE 0xcc
#define CREATE_LINEAR_RECORD_FILE 0xc1
#define CREATE_CYCLIC_RECORD_FILE 0xc0
#define DELETE_FILE 0xdf
#define AUTHENTICATE 0x0a // AUTHENTICATE_NATIVE
#define AUTHENTICATE_ISO 0x1a // AUTHENTICATE_STANDARD
#define AUTHENTICATE_AES 0xaa
#define CHANGE_KEY_SETTINGS 0x54
#define GET_KEY_SETTINGS 0x45
#define CHANGE_KEY 0xc4
#define GET_KEY_VERSION 0x64
#define AUTHENTICATION_FRAME 0xAF
#define MAX_NUM_KEYS 0x0F
#define MAX_APPLICATION_COUNT 28
#define MAX_FILE_COUNT 32
#define MAX_FRAME_SIZE 60
#define NOT_YET_AUTHENTICATED 255
#define FRAME_PAYLOAD_SIZE (MAX_FRAME_SIZE - 5)

View file

@ -1,250 +0,0 @@
//-----------------------------------------------------------------------------
// Copyright (C) 2014 Andy Davies
//
// 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.
//-----------------------------------------------------------------------------
// High frequency MIFARE commands
//-----------------------------------------------------------------------------
#include "cmdhfmf.h"
#include "util.h"
#include <openssl/des.h>
#include <openssl/aes.h>
static int CmdHelp(const char *Cmd);
//DESFIRE
// Reader 2 Card : 020A, key (1 byte), CRC1 CRC2 ; auth (020a00)
// Card 2 Reader : 02AF, 8 Bytes(b0), CRC1 CRC2
// Reader 2 Card : 03AF, 8 Bytes(b1),8 bytes(b2), CRC1 CRC2
// Card 2 Reader : 0300, 8 bytes(b3), CRC1 CRC2 ; success
//send 020A00, receive enc(nc)
//02AE = error
//receive b3=enc(r4)
//r5=dec(b3)
//n'r=rol(r5)
//verify n'r=nr
int CmdHF14AMfDESAuth(const char *Cmd){
uint8_t blockNo = 0;
//keyNo=0;
uint32_t cuid=0;
uint8_t reply[16];
//DES_cblock r1_b1;
uint8_t b1[8]={ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
uint8_t b2[8]={ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
DES_cblock nr, b0, r1, r0;
uint8_t key[8]={ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
//DES_cblock iv={0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
DES_key_schedule ks1;
DES_cblock key1;
if (strlen(Cmd)<1) {
PrintAndLog("Usage: hf desfire des-auth k <key number>");
PrintAndLog(" sample: hf desfire des-auth k 0");
return 0;
}
//Change key to user defined one
memcpy(key1,key,8);
//memcpy(key2,key+8,8);
DES_set_key((DES_cblock *)key1,&ks1);
//DES_set_key((DES_cblock *)key2,&ks2);
//Auth1
UsbCommand c = {CMD_MIFARE_DES_AUTH1, {blockNo}};
SendCommand(&c);
UsbCommand resp;
if (WaitForResponseTimeout(CMD_ACK,&resp,1500)) {
uint8_t isOK = resp.arg[0] & 0xff;
cuid = resp.arg[1];
uint8_t * data= resp.d.asBytes;
if (isOK){
PrintAndLog("enc(nc)/b0:%s", sprint_hex(data+2,8));
memcpy(b0,data+2,8);
}
} else {
PrintAndLog("Command execute timeout");
}
//Do crypto magic
DES_random_key(&nr);
//b1=dec(nr)
//r0=dec(b0)
DES_ecb_encrypt(&nr,&b1,&ks1,0);
DES_ecb_encrypt(&b0,&r0,&ks1,0);
//PrintAndLog("b1:%s",sprint_hex(b1, 8));
PrintAndLog("r0:%s",sprint_hex(r0, 8));
//r1=rol(r0)
memcpy(r1,r0,8);
rol(r1,8);
PrintAndLog("r1:%s",sprint_hex(r1, 8));
for(int i=0;i<8;i++){
b2[i]=(r1[i] ^ b1[i]);
}
DES_ecb_encrypt(&b2,&b2,&ks1,0);
//PrintAndLog("b1:%s",sprint_hex(b1, 8));
PrintAndLog("b2:%s",sprint_hex(b2, 8));
//Auth2
UsbCommand d = {CMD_MIFARE_DES_AUTH2, {cuid}};
memcpy(reply,b1,8);
memcpy(reply+8,b2,8);
memcpy(d.d.asBytes,reply, 16);
SendCommand(&d);
UsbCommand respb;
if (WaitForResponseTimeout(CMD_ACK,&respb,1500)) {
uint8_t isOK = respb.arg[0] & 0xff;
uint8_t * data2= respb.d.asBytes;
if (isOK){
PrintAndLog("b3:%s", sprint_hex(data2+2, 8));
}
} else {
PrintAndLog("Command execute timeout");
}
return 1;
}
//EV1
// Reader 2 Card : 02AA, key (1 byte), CRC1 CRC2 ; auth
// Card 2 Reader : 02AF, 16 Bytes(b0), CRC1 CRC2
// Reader 2 Card : 03AF, 16 Bytes(b1),16Bytes(b2) CRC1 CRC2
// Card 2 Reader : 0300, 16 bytes(b3), CRC1 CRC2 ; success
int CmdHF14AMfAESAuth(const char *Cmd){
uint8_t blockNo = 0;
//keyNo=0;
uint32_t cuid=0;
uint8_t reply[32];
//DES_cblock r1_b1;
//unsigned char * b1, b2, nr, b0, r0, r1;
uint8_t b1[16]={ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
uint8_t b2[16]={ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
uint8_t nr[16]={ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
uint8_t b0[16]={ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
uint8_t r0[16]={ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
uint8_t r1[16]={ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
//
uint8_t key[16]={ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
uint8_t iv[16]={ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
AES_KEY key_e;
AES_KEY key_d;
if (strlen(Cmd)<1) {
PrintAndLog("Usage: hf desfire aes-auth k <key number>");
PrintAndLog(" sample: hf desfire aes-auth k 0");
return 0;
}
//Change key to user defined one
//
// int private_AES_set_encrypt_key(const unsigned char *userKey, const int bits,AES_KEY *key);
//int private_AES_set_decrypt_key(const unsigned char *userKey, const int bits,AES_KEY *key);
//
//memcpy(key1,key,16);
//memcpy(key2,key+8,8);
AES_set_encrypt_key(key,128,&key_e);
AES_set_decrypt_key(key,128,&key_d);
//Auth1
UsbCommand c = {CMD_MIFARE_DES_AUTH1, {blockNo}};
SendCommand(&c);
UsbCommand resp;
if (WaitForResponseTimeout(CMD_ACK,&resp,1500)) {
uint8_t isOK = resp.arg[0] & 0xff;
cuid = resp.arg[1];
uint8_t * data= resp.d.asBytes;
if (isOK){
PrintAndLog("enc(nc)/b0:%s", sprint_hex(data+2,16));
memcpy(b0,data+2,16);
}
} else {
PrintAndLog("Command execute timeout");
}
//
// void AES_cbc_encrypt(const unsigned char *in, unsigned char *out,
//size_t length, const AES_KEY *key,
//unsigned char *ivec, const int enc);
//Do crypto magic
//DES_random_key(&nr);
//b1=dec(nr)
//r0=dec(b0)
//AES_cbc_encrypt(&nr,&b1,16,&key,0);
AES_cbc_encrypt(&b0,&r0,16,&key_d,iv,0);
//PrintAndLog("b1:%s",sprint_hex(b1, 8));
PrintAndLog("r0:%s",sprint_hex(r0, 16));
//r1=rol(r0)
memcpy(r1,r0,16);
rol(r1,8);
PrintAndLog("r1:%s",sprint_hex(r1, 16));
for(int i=0;i<16;i++){
b1[i]=(nr[i] ^ b0[i]);
b2[i]=(r1[i] ^ b1[i]);
}
PrintAndLog("nr:%s",sprint_hex(nr, 16));
AES_cbc_encrypt(&b1,&b1,16,&key_e,iv,1);
AES_cbc_encrypt(&b2,&b2,16,&key_e,iv,1);
PrintAndLog("b1:%s",sprint_hex(b1, 16));
PrintAndLog("b2:%s",sprint_hex(b2, 16));
//Auth2
UsbCommand d = {CMD_MIFARE_DES_AUTH2, {cuid}};
memcpy(reply,b1,16);
memcpy(reply+16,b2,16);
memcpy(d.d.asBytes,reply, 32);
SendCommand(&d);
UsbCommand respb;
if (WaitForResponseTimeout(CMD_ACK,&respb,1500)) {
uint8_t isOK = respb.arg[0] & 0xff;
uint8_t * data2= respb.d.asBytes;
if (isOK){
PrintAndLog("b3:%s", sprint_hex(data2+2, 16));
}
} else {
PrintAndLog("Command execute timeout");
}
return 1;
}
//------------------------------------
// Menu Stuff
//------------------------------------
static command_t CommandTable[] =
{
{"help", CmdHelp, 1,"This help"},
{"dbg", CmdHF14AMfDbg, 0,"Set default debug mode"},
{"des-auth",CmdHF14AMfDESAuth, 0,"Desfire Authentication"},
{"ev1-auth",CmdHF14AMfAESAuth, 0,"EV1 Authentication"},
{NULL, NULL, 0, NULL}
};
int CmdHFMFDesfire(const char *Cmd){
// flush
WaitForResponseTimeout(CMD_ACK,NULL,100);
CmdsParse(CommandTable, Cmd);
return 0;
}
int CmdHelp(const char *Cmd){
CmdsHelp(CommandTable);
return 0;
}

View file

@ -1,5 +0,0 @@
static int CmdHelp(const char *Cmd);
int CmdHF14AMfDESAuth(const char *Cmd);
int CmdHFMFDesfire(const char *Cmd);
int CmdHelp(const char *Cmd);

File diff suppressed because it is too large Load diff

View file

@ -1,16 +0,0 @@
#include "cmdhfmf.h"
//standard ultralight
int CmdHF14AMfUWrBl(const char *Cmd);
int CmdHF14AMfURdBl(const char *Cmd);
int CmdHF14AMfURdCard(const char *Cmd);
int CmdHF14AMfUDump(const char *Cmd);
//Crypto Cards
int CmdHF14AMfUCRdBl(const char *Cmd);
int CmdHF14AMfUCRdCard(const char *Cmd);
int CmdHF14AMfUCDump(const char *Cmd);
int CmdHF14AMfucAuth(const char *Cmd);
void rol (uint8_t *data, const size_t len);
//general stuff
int CmdHFMFUltra(const char *Cmd);

View file

@ -13,11 +13,12 @@
#include <string.h> #include <string.h>
#include <limits.h> #include <limits.h>
#include "ui.h" #include "ui.h"
//#include "proxusb.h"
#include "proxmark3.h" #include "proxmark3.h"
#include "cmdparser.h" #include "cmdparser.h"
#include "cmddata.h"
#include "cmdhw.h" #include "cmdhw.h"
#include "cmdmain.h" #include "cmdmain.h"
#include "cmddata.h"
/* low-level hardware control */ /* low-level hardware control */
@ -417,7 +418,7 @@ static command_t CommandTable[] =
{"setlfdivisor", CmdSetDivisor, 0, "<19 - 255> -- Drive LF antenna at 12Mhz/(divisor+1)"}, {"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"}, {"setmux", CmdSetMux, 0, "<loraw|hiraw|lopkd|hipkd> -- Set the ADC mux to a specific value"},
{"tune", CmdTune, 0, "Measure antenna tuning"}, {"tune", CmdTune, 0, "Measure antenna tuning"},
{"version", CmdVersion, 0, "Show version information about the connected Proxmark"}, {"version", CmdVersion, 0, "Show version inforation about the connected Proxmark"},
{NULL, NULL, 0, NULL} {NULL, NULL, 0, NULL}
}; };

View file

@ -20,7 +20,6 @@
#include "cmdmain.h" #include "cmdmain.h"
#include "cmddata.h" #include "cmddata.h"
#include "cmdlf.h" #include "cmdlf.h"
#include "cmdlfawid26.h"
#include "cmdlfhid.h" #include "cmdlfhid.h"
#include "cmdlfti.h" #include "cmdlfti.h"
#include "cmdlfem4x.h" #include "cmdlfem4x.h"
@ -48,377 +47,374 @@ int CmdLFCommandRead(const char *Cmd)
int CmdFlexdemod(const char *Cmd) int CmdFlexdemod(const char *Cmd)
{ {
int i; int i;
for (i = 0; i < GraphTraceLen; ++i) { for (i = 0; i < GraphTraceLen; ++i) {
if (GraphBuffer[i] < 0) { if (GraphBuffer[i] < 0) {
GraphBuffer[i] = -1; GraphBuffer[i] = -1;
} else { } else {
GraphBuffer[i] = 1; GraphBuffer[i] = 1;
} }
} }
#define LONG_WAIT 100 #define LONG_WAIT 100
int start; int start;
for (start = 0; start < GraphTraceLen - LONG_WAIT; start++) { for (start = 0; start < GraphTraceLen - LONG_WAIT; start++) {
int first = GraphBuffer[start]; int first = GraphBuffer[start];
for (i = start; i < start + LONG_WAIT; i++) { for (i = start; i < start + LONG_WAIT; i++) {
if (GraphBuffer[i] != first) { if (GraphBuffer[i] != first) {
break; break;
} }
} }
if (i == (start + LONG_WAIT)) { if (i == (start + LONG_WAIT)) {
break; break;
} }
} }
if (start == GraphTraceLen - LONG_WAIT) { if (start == GraphTraceLen - LONG_WAIT) {
//PrintAndLog("nothing to wait for"); PrintAndLog("nothing to wait for");
return 0; return 0;
} }
GraphBuffer[start] = 2; GraphBuffer[start] = 2;
GraphBuffer[start+1] = -2; GraphBuffer[start+1] = -2;
uint8_t bits[64] = {0x00}; uint8_t bits[64] = {0x00};
int bit, sum; int bit, sum;
i = start; i = start;
for (bit = 0; bit < 64; bit++) { for (bit = 0; bit < 64; bit++) {
sum = 0; sum = 0;
for (int j = 0; j < 16; j++) { for (int j = 0; j < 16; j++) {
sum += GraphBuffer[i++]; sum += GraphBuffer[i++];
} }
bits[bit] = (sum > 0) ? 1 : 0; bits[bit] = (sum > 0) ? 1 : 0;
PrintAndLog("bit %d sum %d", bit, sum); PrintAndLog("bit %d sum %d", bit, sum);
} }
for (bit = 0; bit < 64; bit++) { for (bit = 0; bit < 64; bit++) {
int j; int j;
int sum = 0; int sum = 0;
for (j = 0; j < 16; j++) { for (j = 0; j < 16; j++) {
sum += GraphBuffer[i++]; sum += GraphBuffer[i++];
} }
if (sum > 0 && bits[bit] != 1) { if (sum > 0 && bits[bit] != 1) {
PrintAndLog("oops1 at %d", bit); PrintAndLog("oops1 at %d", bit);
} }
if (sum < 0 && bits[bit] != 0) { if (sum < 0 && bits[bit] != 0) {
PrintAndLog("oops2 at %d", bit); PrintAndLog("oops2 at %d", bit);
} }
} }
// HACK writing back to graphbuffer. // HACK writing back to graphbuffer.
GraphTraceLen = 32*64; GraphTraceLen = 32*64;
i = 0; i = 0;
int phase = 0; int phase = 0;
for (bit = 0; bit < 64; bit++) { for (bit = 0; bit < 64; bit++) {
phase = (bits[bit] == 0) ? 0 : 1; phase = (bits[bit] == 0) ? 0 : 1;
int j; int j;
for (j = 0; j < 32; j++) { for (j = 0; j < 32; j++) {
GraphBuffer[i++] = phase; GraphBuffer[i++] = phase;
phase = !phase; phase = !phase;
} }
} }
RepaintGraphWindow(); RepaintGraphWindow();
return 0; return 0;
} }
int CmdIndalaDemod(const char *Cmd) int CmdIndalaDemod(const char *Cmd)
{ {
// Usage: recover 64bit UID by default, specify "224" as arg to recover a 224bit UID // Usage: recover 64bit UID by default, specify "224" as arg to recover a 224bit UID
int state = -1; int state = -1;
int count = 0; int count = 0;
int i, j; int i, j;
// worst case with GraphTraceLen=64000 is < 4096 // worst case with GraphTraceLen=64000 is < 4096
// under normal conditions it's < 2048 // under normal conditions it's < 2048
uint8_t rawbits[4096]; uint8_t rawbits[4096];
int rawbit = 0; int rawbit = 0;
int worst = 0, worstPos = 0; int worst = 0, worstPos = 0;
// PrintAndLog("Expecting a bit less than %d raw bits", GraphTraceLen / 32); // PrintAndLog("Expecting a bit less than %d raw bits", GraphTraceLen / 32);
for (i = 0; i < GraphTraceLen-1; i += 2) { for (i = 0; i < GraphTraceLen-1; i += 2) {
count += 1; count += 1;
if ((GraphBuffer[i] > GraphBuffer[i + 1]) && (state != 1)) { if ((GraphBuffer[i] > GraphBuffer[i + 1]) && (state != 1)) {
if (state == 0) { if (state == 0) {
for (j = 0; j < count - 8; j += 16) { for (j = 0; j < count - 8; j += 16) {
rawbits[rawbit++] = 0; rawbits[rawbit++] = 0;
} }
if ((abs(count - j)) > worst) { if ((abs(count - j)) > worst) {
worst = abs(count - j); worst = abs(count - j);
worstPos = i; worstPos = i;
} }
} }
state = 1; state = 1;
count = 0; count = 0;
} else if ((GraphBuffer[i] < GraphBuffer[i + 1]) && (state != 0)) { } else if ((GraphBuffer[i] < GraphBuffer[i + 1]) && (state != 0)) {
if (state == 1) { if (state == 1) {
for (j = 0; j < count - 8; j += 16) { for (j = 0; j < count - 8; j += 16) {
rawbits[rawbit++] = 1; rawbits[rawbit++] = 1;
} }
if ((abs(count - j)) > worst) { if ((abs(count - j)) > worst) {
worst = abs(count - j); worst = abs(count - j);
worstPos = i; worstPos = i;
} }
} }
state = 0; state = 0;
count = 0; count = 0;
} }
} }
if (rawbit>0){ if (rawbit>0){
PrintAndLog("Recovered %d raw bits, expected: %d", rawbit, GraphTraceLen/32); PrintAndLog("Recovered %d raw bits, expected: %d", rawbit, GraphTraceLen/32);
PrintAndLog("worst metric (0=best..7=worst): %d at pos %d", worst, worstPos); PrintAndLog("worst metric (0=best..7=worst): %d at pos %d", worst, worstPos);
} else { } else {
return 0; return 0;
} }
// Finding the start of a UID // Finding the start of a UID
int uidlen, long_wait; int uidlen, long_wait;
if (strcmp(Cmd, "224") == 0) { if (strcmp(Cmd, "224") == 0) {
uidlen = 224; uidlen = 224;
long_wait = 30; long_wait = 30;
} else { } else {
uidlen = 64; uidlen = 64;
long_wait = 29; long_wait = 29;
} }
int start; int start;
int first = 0; int first = 0;
for (start = 0; start <= rawbit - uidlen; start++) { for (start = 0; start <= rawbit - uidlen; start++) {
first = rawbits[start]; first = rawbits[start];
for (i = start; i < start + long_wait; i++) { for (i = start; i < start + long_wait; i++) {
if (rawbits[i] != first) { if (rawbits[i] != first) {
break; break;
} }
} }
if (i == (start + long_wait)) { if (i == (start + long_wait)) {
break; break;
} }
} }
if (start == rawbit - uidlen + 1) { if (start == rawbit - uidlen + 1) {
//PrintAndLog("nothing to wait for"); PrintAndLog("nothing to wait for");
return 0; return 0;
} }
// Inverting signal if needed // Inverting signal if needed
if (first == 1) { if (first == 1) {
for (i = start; i < rawbit; i++) { for (i = start; i < rawbit; i++) {
rawbits[i] = !rawbits[i]; rawbits[i] = !rawbits[i];
} }
} }
// Dumping UID // Dumping UID
uint8_t bits[224] = {0x00}; uint8_t bits[224] = {0x00};
char showbits[225] = {0x00}; char showbits[225] = {0x00};
int bit; int bit;
i = start; i = start;
int times = 0; int times = 0;
if (uidlen > rawbit) { if (uidlen > rawbit) {
PrintAndLog("Warning: not enough raw bits to get a full UID"); PrintAndLog("Warning: not enough raw bits to get a full UID");
for (bit = 0; bit < rawbit; bit++) { for (bit = 0; bit < rawbit; bit++) {
bits[bit] = rawbits[i++]; bits[bit] = rawbits[i++];
// As we cannot know the parity, let's use "." and "/" // As we cannot know the parity, let's use "." and "/"
showbits[bit] = '.' + bits[bit]; showbits[bit] = '.' + bits[bit];
} }
showbits[bit+1]='\0'; showbits[bit+1]='\0';
PrintAndLog("Partial UID=%s", showbits); PrintAndLog("Partial UID=%s", showbits);
return 0; return 0;
} else { } else {
for (bit = 0; bit < uidlen; bit++) { for (bit = 0; bit < uidlen; bit++) {
bits[bit] = rawbits[i++]; bits[bit] = rawbits[i++];
showbits[bit] = '0' + bits[bit]; showbits[bit] = '0' + bits[bit];
} }
times = 1; times = 1;
} }
//convert UID to HEX //convert UID to HEX
uint32_t uid1, uid2, uid3, uid4, uid5, uid6, uid7; uint32_t uid1, uid2, uid3, uid4, uid5, uid6, uid7;
int idx; int idx;
uid1 = uid2 = 0; uid1 = uid2 = 0;
if (uidlen == 64){ if (uidlen==64){
for( idx=0; idx<64; idx++) { for( idx=0; idx<64; idx++) {
if (showbits[idx] == '0') { if (showbits[idx] == '0') {
uid1 = (uid1<<1) | (uid2>>31); uid1=(uid1<<1)|(uid2>>31);
uid2 = (uid2<<1) | 0; uid2=(uid2<<1)|0;
} else { } else {
uid1 = (uid1<<1) | (uid2>>31); uid1=(uid1<<1)|(uid2>>31);
uid2 = (uid2<<1) | 1; uid2=(uid2<<1)|1;
} }
} }
PrintAndLog("UID=%s (%x%08x)", showbits, uid1, uid2); PrintAndLog("UID=%s (%x%08x)", showbits, uid1, uid2);
} }
else { else {
uid3 = uid4 = uid5 = uid6 = uid7 = 0; uid3 = uid4 = uid5 = uid6 = uid7 = 0;
for( idx=0; idx<224; idx++) { for( idx=0; idx<224; idx++) {
uid1 = (uid1<<1) | (uid2>>31); uid1=(uid1<<1)|(uid2>>31);
uid2 = (uid2<<1) | (uid3>>31); uid2=(uid2<<1)|(uid3>>31);
uid3 = (uid3<<1) | (uid4>>31); uid3=(uid3<<1)|(uid4>>31);
uid4 = (uid4<<1) | (uid5>>31); uid4=(uid4<<1)|(uid5>>31);
uid5 = (uid5<<1) | (uid6>>31); uid5=(uid5<<1)|(uid6>>31);
uid6 = (uid6<<1) | (uid7>>31); uid6=(uid6<<1)|(uid7>>31);
if (showbits[idx] == '0') if (showbits[idx] == '0')
uid7 = (uid7<<1) | 0; uid7 = (uid7<<1) | 0;
else else
uid7 = (uid7<<1) | 1; uid7 = (uid7<<1) | 1;
} }
PrintAndLog("UID=%s (%x%08x%08x%08x%08x%08x%08x)", showbits, uid1, uid2, uid3, uid4, uid5, uid6, uid7); PrintAndLog("UID=%s (%x%08x%08x%08x%08x%08x%08x)", showbits, uid1, uid2, uid3, uid4, uid5, uid6, uid7);
} }
// Checking UID against next occurrences // Checking UID against next occurrences
int failed = 0; int failed = 0;
for (; i + uidlen <= rawbit;) { for (; i + uidlen <= rawbit;) {
failed = 0; failed = 0;
for (bit = 0; bit < uidlen; bit++) { for (bit = 0; bit < uidlen; bit++) {
if (bits[bit] != rawbits[i++]) { if (bits[bit] != rawbits[i++]) {
failed = 1; failed = 1;
break; break;
} }
} }
if (failed == 1) { if (failed == 1) {
break; break;
} }
times += 1; times += 1;
} }
PrintAndLog("Occurrences: %d (expected %d)", times, (rawbit - start) / uidlen); PrintAndLog("Occurrences: %d (expected %d)", times, (rawbit - start) / uidlen);
// Remodulating for tag cloning // Remodulating for tag cloning
// HACK: 2015-01-04 this will have an impact on our new way of seening lf commands (demod) // HACK: 2015-01-04 this will have an impact on our new way of seening lf commands (demod)
// since this changes graphbuffer data. // since this changes graphbuffer data.
GraphTraceLen = 32 * uidlen; GraphTraceLen = 32*uidlen;
i = 0; i = 0;
int phase = 0; int phase = 0;
for (bit = 0; bit < uidlen; bit++) { for (bit = 0; bit < uidlen; bit++) {
if (bits[bit] == 0) { if (bits[bit] == 0) {
phase = 0; phase = 0;
} else { } else {
phase = 1; phase = 1;
} }
int j; int j;
for (j = 0; j < 32; j++) { for (j = 0; j < 32; j++) {
GraphBuffer[i++] = phase; GraphBuffer[i++] = phase;
phase = !phase; phase = !phase;
} }
} }
RepaintGraphWindow(); RepaintGraphWindow();
return 1; return 1;
} }
int CmdIndalaClone(const char *Cmd) int CmdIndalaClone(const char *Cmd)
{ {
UsbCommand c; UsbCommand c;
unsigned int uid1, uid2, uid3, uid4, uid5, uid6, uid7; unsigned int uid1, uid2, uid3, uid4, uid5, uid6, uid7;
uid1 = uid2 = uid3 = uid4 = uid5 = uid6 = uid7 = 0; uid1 = uid2 = uid3 = uid4 = uid5 = uid6 = uid7 = 0;
int n = 0, i = 0; int n = 0, i = 0;
if (strchr(Cmd,'l') != 0) { if (strchr(Cmd,'l') != 0) {
while (sscanf(&Cmd[i++], "%1x", &n ) == 1) { while (sscanf(&Cmd[i++], "%1x", &n ) == 1) {
uid1 = (uid1 << 4) | (uid2 >> 28); uid1 = (uid1 << 4) | (uid2 >> 28);
uid2 = (uid2 << 4) | (uid3 >> 28); uid2 = (uid2 << 4) | (uid3 >> 28);
uid3 = (uid3 << 4) | (uid4 >> 28); uid3 = (uid3 << 4) | (uid4 >> 28);
uid4 = (uid4 << 4) | (uid5 >> 28); uid4 = (uid4 << 4) | (uid5 >> 28);
uid5 = (uid5 << 4) | (uid6 >> 28); uid5 = (uid5 << 4) | (uid6 >> 28);
uid6 = (uid6 << 4) | (uid7 >> 28); uid6 = (uid6 << 4) | (uid7 >> 28);
uid7 = (uid7 << 4) | (n & 0xf); uid7 = (uid7 << 4) | (n & 0xf);
} }
PrintAndLog("Cloning 224bit tag with UID %x%08x%08x%08x%08x%08x%08x", uid1, uid2, uid3, uid4, uid5, uid6, uid7); PrintAndLog("Cloning 224bit tag with UID %x%08x%08x%08x%08x%08x%08x", uid1, uid2, uid3, uid4, uid5, uid6, uid7);
c.cmd = CMD_INDALA_CLONE_TAG_L; c.cmd = CMD_INDALA_CLONE_TAG_L;
c.d.asDwords[0] = uid1; c.d.asDwords[0] = uid1;
c.d.asDwords[1] = uid2; c.d.asDwords[1] = uid2;
c.d.asDwords[2] = uid3; c.d.asDwords[2] = uid3;
c.d.asDwords[3] = uid4; c.d.asDwords[3] = uid4;
c.d.asDwords[4] = uid5; c.d.asDwords[4] = uid5;
c.d.asDwords[5] = uid6; c.d.asDwords[5] = uid6;
c.d.asDwords[6] = uid7; c.d.asDwords[6] = uid7;
} else { } else {
while (sscanf(&Cmd[i++], "%1x", &n ) == 1) { while (sscanf(&Cmd[i++], "%1x", &n ) == 1) {
uid1 = (uid1 << 4) | (uid2 >> 28); uid1 = (uid1 << 4) | (uid2 >> 28);
uid2 = (uid2 << 4) | (n & 0xf); uid2 = (uid2 << 4) | (n & 0xf);
} }
PrintAndLog("Cloning 64bit tag with UID %x%08x", uid1, uid2); PrintAndLog("Cloning 64bit tag with UID %x%08x", uid1, uid2);
c.cmd = CMD_INDALA_CLONE_TAG; c.cmd = CMD_INDALA_CLONE_TAG;
c.arg[0] = uid1; c.arg[0] = uid1;
c.arg[1] = uid2; c.arg[1] = uid2;
} }
SendCommand(&c); SendCommand(&c);
return 0; return 0;
} }
int CmdLFRead(const char *Cmd) int CmdLFRead(const char *Cmd)
{ {
UsbCommand c = {CMD_ACQUIRE_RAW_ADC_SAMPLES_125K}; UsbCommand c = {CMD_ACQUIRE_RAW_ADC_SAMPLES_125K};
// 'h' means higher-low-frequency, 134 kHz // 'h' means higher-low-frequency, 134 kHz
if(*Cmd == 'h') { if(*Cmd == 'h') {
c.arg[0] = 1; c.arg[0] = 1;
} else if (*Cmd == '\0') { } else if (*Cmd == '\0') {
c.arg[0] = 0; c.arg[0] = 0;
} else if (sscanf(Cmd, "%"lli, &c.arg[0]) != 1) { } else if (sscanf(Cmd, "%"lli, &c.arg[0]) != 1) {
PrintAndLog("Samples 1: 'lf read'"); PrintAndLog("Samples 1: 'lf read'");
PrintAndLog(" 2: 'lf read h'"); PrintAndLog(" 2: 'lf read h'");
PrintAndLog(" 3: 'lf read <divisor>'"); PrintAndLog(" 3: 'lf read <divisor>'");
return 0; return 0;
} }
SendCommand(&c); SendCommand(&c);
WaitForResponse(CMD_ACK,NULL); WaitForResponse(CMD_ACK,NULL);
return 0;
CmdSamples("");
ShowGraphWindow();
return 0;
} }
static void ChkBitstream(const char *str) static void ChkBitstream(const char *str)
{ {
int i; int i;
/* convert to bitstream if necessary */ /* convert to bitstream if necessary */
for (i = 0; i < (int)(GraphTraceLen / 2); i++){ for (i = 0; i < (int)(GraphTraceLen / 2); i++)
if (GraphBuffer[i] > 1 || GraphBuffer[i] < 0) { {
CmdBitstream(str); if (GraphBuffer[i] > 1 || GraphBuffer[i] < 0)
break; {
} CmdBitstream(str);
} break;
}
}
} }
int CmdLFSim(const char *Cmd) int CmdLFSim(const char *Cmd)
{ {
int i,j; int i;
static int gap; static int gap;
sscanf(Cmd, "%i", &gap); sscanf(Cmd, "%i", &gap);
/* convert to bitstream if necessary */ /* convert to bitstream if necessary */
ChkBitstream(Cmd); ChkBitstream(Cmd);
printf("Sending [%d bytes]", GraphTraceLen); PrintAndLog("Sending data, please wait...");
for (i = 0; i < GraphTraceLen; i += USB_CMD_DATA_SIZE) { for (i = 0; i < GraphTraceLen; i += 48) {
UsbCommand c={CMD_DOWNLOADED_SIM_SAMPLES_125K, {i, 0, 0}}; UsbCommand c={CMD_DOWNLOADED_SIM_SAMPLES_125K, {i, 0, 0}};
int j;
for (j = 0; j < 48; j++) {
c.d.asBytes[j] = GraphBuffer[i+j];
}
SendCommand(&c);
WaitForResponse(CMD_ACK,NULL);
}
for (j = 0; j < USB_CMD_DATA_SIZE; j++) { PrintAndLog("Starting simulator...");
c.d.asBytes[j] = GraphBuffer[i+j]; UsbCommand c = {CMD_SIMULATE_TAG_125K, {GraphTraceLen, gap, 0}};
} SendCommand(&c);
SendCommand(&c); return 0;
WaitForResponse(CMD_ACK,NULL);
printf(".");
}
printf("\n");
PrintAndLog("Starting to simulate");
UsbCommand c = {CMD_SIMULATE_TAG_125K, {GraphTraceLen, gap, 0}};
SendCommand(&c);
return 0;
} }
int CmdLFSimBidir(const char *Cmd) int CmdLFSimBidir(const char *Cmd)
@ -434,57 +430,48 @@ int CmdLFSimBidir(const char *Cmd)
/* simulate an LF Manchester encoded tag with specified bitstream, clock rate and inter-id gap */ /* simulate an LF Manchester encoded tag with specified bitstream, clock rate and inter-id gap */
int CmdLFSimManchester(const char *Cmd) int CmdLFSimManchester(const char *Cmd)
{ {
static int clock, gap; static int clock, gap;
static char data[1024], gapstring[8]; static char data[1024], gapstring[8];
sscanf(Cmd, "%i %s %i", &clock, &data[0], &gap); sscanf(Cmd, "%i %s %i", &clock, &data[0], &gap);
ClearGraph(0); ClearGraph(0);
for (int i = 0; i < strlen(data) ; ++i) for (int i = 0; i < strlen(data) ; ++i)
AppendGraph(0, clock, data[i]- '0'); AppendGraph(0, clock, data[i]- '0');
CmdManchesterMod(""); CmdManchesterMod("");
RepaintGraphWindow(); RepaintGraphWindow();
sprintf(&gapstring[0], "%i", gap); sprintf(&gapstring[0], "%i", gap);
CmdLFSim(gapstring); CmdLFSim(gapstring);
return 0; return 0;
} }
int CmdLFSnoop(const char *Cmd) int CmdLFSnoop(const char *Cmd)
{ {
UsbCommand c = {CMD_LF_SNOOP_RAW_ADC_SAMPLES}; UsbCommand c = {CMD_LF_SNOOP_RAW_ADC_SAMPLES};
// 'h' means higher-low-frequency, 134 kHz // 'h' means higher-low-frequency, 134 kHz
c.arg[0] = 0; c.arg[0] = 0;
c.arg[1] = -1; c.arg[1] = -1;
if (*Cmd == 'l') { if (*Cmd == 'l') {
sscanf(Cmd, "l %"lli, &c.arg[1]); sscanf(Cmd, "l %"lli, &c.arg[1]);
} else if (*Cmd == 'h') { } else if(*Cmd == 'h') {
c.arg[0] = 1; c.arg[0] = 1;
sscanf(Cmd, "h %"lli, &c.arg[1]); sscanf(Cmd, "h %"lli, &c.arg[1]);
} else if (sscanf(Cmd, "%"lli" %"lli, &c.arg[0], &c.arg[1]) < 1) { } else if (sscanf(Cmd, "%"lli" %"lli, &c.arg[0], &c.arg[1]) < 1) {
PrintAndLog("usage 1: snoop"); PrintAndLog("usage 1: snoop");
PrintAndLog(" 2: snoop {l,h} [trigger threshold]"); PrintAndLog(" 2: snoop {l,h} [trigger threshold]");
PrintAndLog(" 3: snoop <divisor> [trigger threshold]"); PrintAndLog(" 3: snoop <divisor> [trigger threshold]");
return 0; return 0;
} }
SendCommand(&c); SendCommand(&c);
WaitForResponse(CMD_ACK,NULL); WaitForResponse(CMD_ACK,NULL);
return 0;
#define BUFF_SIZE 8000
uint8_t data[BUFF_SIZE] = {0x00};
GetFromBigBuf(data,BUFF_SIZE,0);
WaitForResponseTimeout(CMD_ACK,NULL, 1500);
SetGraphBuf(data, BUFF_SIZE);
return 0;
} }
int CmdVchDemod(const char *Cmd) int CmdVchDemod(const char *Cmd)
@ -566,81 +553,49 @@ int CmdVchDemod(const char *Cmd)
//by marshmellow //by marshmellow
int CmdLFfind(const char *Cmd) int CmdLFfind(const char *Cmd)
{ {
int ans = 0; int ans=0;
char cmdp = param_getchar(Cmd, 0); if (!offline){
ans=CmdLFRead("");
if (strlen(Cmd) > 1 || cmdp == 'h' || cmdp == 'H') { ans=CmdSamples("20000");
PrintAndLog("Usage: lf search <0|1>"); }
PrintAndLog(" <use data from Graphbuffer>, if not set, try reading data from tag."); if (GraphTraceLen<1000) return 0;
PrintAndLog(""); PrintAndLog("Checking for known tags:");
PrintAndLog(" sample: lf search"); ans=Cmdaskmandemod("");
PrintAndLog(" : lf search 1"); if (ans>0) return 1;
return 0; ans=CmdFSKdemodHID("");
} if (ans>0) return 1;
ans=CmdFSKdemodIO("");
if (!offline || (cmdp != '1') ){ if (ans>0) return 1;
ans = CmdLFRead(""); //add psk and indala
} else if (GraphTraceLen < 1000) { ans=CmdIndalaDemod("");
PrintAndLog("Data in Graphbuffer was too small."); if (ans>0) return 1;
return 0; ans=CmdIndalaDemod("224");
} if (ans>0) return 1;
PrintAndLog("No Known Tags Found!\n");
PrintAndLog("Checking for known tags:"); return 0;
ans = Cmdaskmandemod("");
PrintAndLog("ASK_MAN: %s", (ans) ? "YES":"NO" );
ans = CmdFSKdemodHID("");
PrintAndLog("HID: %s", (ans) ? "YES":"NO" );
ans = CmdFSKdemodIO("");
PrintAndLog("IO prox: %s", (ans) ? "YES":"NO" );
ans = CmdIndalaDemod("");
PrintAndLog("Indala (64): %s", (ans) ? "YES":"NO" );
ans = CmdIndalaDemod("224");
PrintAndLog("Indala (224): %s", (ans) ? "YES":"NO" );
// ans = CmdVchDemod("");
// PrintAndLog("VeriChip: %s", (ans) ? "YES":"NO" );
// ans = CmdFlexdemod("");
// PrintAndLog("FlexPass: %s", (ans) ? "YES":"NO" );
if (!ans)
PrintAndLog("No Known Tags Found!\n");
return 0;
} }
static command_t CommandTable[] = static command_t CommandTable[] =
{ {
{"help", CmdHelp, 1, "This help"}, {"help", CmdHelp, 1, "This help"},
{"cmdread", CmdLFCommandRead, 0, "<off period> <'0' period> <'1' period> <command> ['h'] -- Modulate LF reader field to send command before read (all periods in microseconds) (option 'h' for 134)"}, {"cmdread", CmdLFCommandRead, 0, "<off period> <'0' period> <'1' period> <command> ['h'] -- Modulate LF reader field to send command before read (all periods in microseconds) (option 'h' for 134)"},
{"em4x", CmdLFEM4X, 1, "{ EM4X RFIDs... }"},
{"flexdemod", CmdFlexdemod, 1, "Demodulate samples for FlexPass"}, {"flexdemod", CmdFlexdemod, 1, "Demodulate samples for FlexPass"},
{"hid", CmdLFHID, 1, "{ HID RFIDs... }"},
{"io", CmdLFIO, 1, "{ ioProx tags... }"},
{"indalademod", CmdIndalaDemod, 1, "['224'] -- Demodulate samples for Indala 64 bit UID (option '224' for 224 bit)"}, {"indalademod", CmdIndalaDemod, 1, "['224'] -- Demodulate samples for Indala 64 bit UID (option '224' for 224 bit)"},
{"indalaclone", CmdIndalaClone, 0, "<UID> ['l']-- Clone Indala to T55x7 (UID in HEX)(option 'l' for 224 UID"}, {"indalaclone", CmdIndalaClone, 0, "<UID> ['l']-- Clone Indala to T55x7 (tag must be in antenna)(UID in HEX)(option 'l' for 224 UID"},
{"vchdemod", CmdVchDemod, 1, "['clone'] -- Demodulate samples for VeriChip"},
{"read", CmdLFRead, 0, "['h' or <divisor>] -- Read 125/134 kHz LF ID-only tag (option 'h' for 134, alternatively: f=12MHz/(divisor+1))"}, {"read", CmdLFRead, 0, "['h' or <divisor>] -- Read 125/134 kHz LF ID-only tag (option 'h' for 134, alternatively: f=12MHz/(divisor+1))"},
{"search", CmdLFfind, 1, "Read and Search for valid known tag (in offline mode it you can load first then search)"}, {"search", CmdLFfind, 1, "Read and Search for valid known tag (in offline mode it you can load first then search)"},
{"sim", CmdLFSim, 0, "[GAP] -- Simulate LF tag from buffer with optional GAP (in microseconds)"}, {"sim", CmdLFSim, 0, "[GAP] -- Simulate LF tag from buffer with optional GAP (in microseconds)"},
{"simbidir", CmdLFSimBidir, 0, "Simulate LF tag (with bidirectional data transmission between reader and tag)"}, {"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"}, {"simman", CmdLFSimManchester, 0, "<Clock> <Bitstream> [GAP] Simulate arbitrary Manchester LF tag"},
{"snoop", CmdLFSnoop, 0, "['l'|'h'|<divisor>] [trigger threshold]-- Snoop LF (l:125khz, h:134khz)"}, {"snoop", CmdLFSnoop, 0, "['l'|'h'|<divisor>] [trigger threshold]-- Snoop LF (l:125khz, h:134khz)"},
{"ti", CmdLFTI, 1, "{ TI RFIDs... }"},
{"awid26", CmdLFAWID26, 1, "{ AWID26 tags }"}, {"hitag", CmdLFHitag, 1, "{ Hitag tags and transponders... }"},
{"em4x", CmdLFEM4X, 1, "{ EM4X tags }"}, {"vchdemod", CmdVchDemod, 1, "['clone'] -- Demodulate samples for VeriChip"},
{"hid", CmdLFHID, 1, "{ HID tags }"}, {"t55xx", CmdLFT55XX, 1, "{ T55xx RFIDs... }"},
{"hitag", CmdLFHitag, 1, "{ Hitag tags and transponders }"}, {"pcf7931", CmdLFPCF7931, 1, "{PCF7931 RFIDs...}"},
{"io", CmdLFIO, 1, "{ ioProx tags }"},
{"pcf7931", CmdLFPCF7931, 1, "{ PCF7931 tags }"},
{"ti", CmdLFTI, 1, "{ TI tags }"},
{"t55xx", CmdLFT55XX, 1, "{ T55xx tags }"},
{NULL, NULL, 0, NULL} {NULL, NULL, 0, NULL}
}; };

View file

@ -1,208 +0,0 @@
//-----------------------------------------------------------------------------
//
// 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 AWID26 commands
//-----------------------------------------------------------------------------
#include <stdio.h>
#include <string.h>
#include <inttypes.h>
#include <stdbool.h>
#include "proxmark3.h"
#include "ui.h"
//#include "graph.h"
#include "cmdmain.h"
#include "cmdparser.h"
//#include "cmddata.h"
#include "cmdlf.h"
#include "cmdlfawid26.h"
#include "util.h"
//#include "data.h"
static int CmdHelp(const char *Cmd);
int CmdClone(const char *Cmd)
{
char cmdp = param_getchar(Cmd, 0);
if (strlen(Cmd) < 1 || cmdp == 'h' || cmdp == 'H') {
PrintAndLog("Usage: lf awid26 clone <facility> <id>");
PrintAndLog(" [], ");
PrintAndLog("");
PrintAndLog(" sample: lf awid26 clone 15 2233");
return 0;
}
//sscanf(Cmd, "%d %d", &facilitycode, &cardno);
// char block0 = "00107060";
// char block1 = "00107060";
// char block2 = "00107060";
// char block3 = "00107060";
unsigned char buf[10] = {0x00};
unsigned char *resp = buf;
awid26_hex_to_uid(resp, "");
// PrintAndLog("Writing block %d with data %08X", Block, Data);
return 0;
}
// convert 96 bit AWID FSK data to 8 digit BCD UID
bool awid26_hex_to_uid(unsigned char *response, char *awid26)
{
//uint8_t i, tmp[96], tmp1[7];
//uint8_t tmp[96] = {0x00};
//int site;
//int id;
//if(!hextobinarray(tmp, awid26))
return false;
// // data is in blocks of 4 bits - every 4th bit is parity, except the first
// // block which is all zeros
// for(i= 0 ; i < 4 ; ++i)
// if(tmp[i] != 0x00)
// return false;
// // discard 1st block
// memcpy(tmp, tmp + 4, 92);
// // check and strip parity on the rest
// for(i= 1 ; i < 23 ; ++i)
// if(tmp[(i * 4) - 1] != GetParity(tmp + (i - 1) * 4, ODD, 3))
// return false;
// else
// memcpy((tmp + (i - 1) * 3), tmp + (i - 1) * 4, 3);
// // discard the rest of the header - 1 more 3 bit block
// memcpy(tmp, tmp + 3, 66);
// // next 8 bits is data length - should be 26: 0x1A
// binarraytohex(tmp1, tmp, 8);
// if(strcmp(tmp1, "1A") != 0)
// return false;
// memcpy(tmp, tmp +8, 58);
// // standard wiegand parity check - even for 1st 12 bits, odd for 2nd 12
// if(tmp[0] != GetParity(tmp + 1, EVEN, 12))
// return false;
// if(tmp[25] != GetParity(tmp + 13, ODD, 12))
// return false;
// // convert to hex, ignoring parity bits
// if(!binarraytohex(tmp1, tmp + 1, 24))
// return false;
// // convert hex to site/id
// sscanf(tmp1,"%2X%4X", &site, &id);
// // final output 8 byte BCD
// sprintf(response,"%03d%05d", site, id);
return true;
}
// convert null-terminated BCD UID (8 digits) to 96 bit awid26 encoded binary array
bool bcd_to_awid26_bin(unsigned char *awid26, unsigned char *bcd)
{
// char i, p, tmp1[8], tmp2[26];
// int tmpint;
// if(strlen(bcd) != 8)
// return false;
// // convert BCD site code to HEX
// sscanf(bcd, "%03d", &tmpint);
// sprintf(tmp2, "%02x", tmpint);
// memcpy(tmp1, tmp2, 2);
// // convert BCD ID to HEX
// sscanf(bcd + 3, "%05d", &tmpint);;
// sprintf(tmp2, "%04x", tmpint);
// // copy with trailing NULL
// memcpy(tmp1 + 2, tmp2, 5);
// // convert full HEX to binary, leaving room for parity prefix
// hextobinarray(tmp2 + 1, tmp1);
// wiegand_add_parity(tmp2, tmp2 + 1, 24);
// memset(awid26, '\x0', 96);
// // magic 18 bit awid26 header (we will overwrite the last two bits)
// hextobinarray(awid26, "011D8");
// // copy to target leaving space for parity bits
// for(i= 0, p= 18 ; i < 26 ; ++i, ++p)
// {
// // skip target bit if this is a parity location
// if(!((p + 1) % 4))
// p += 1;
// awid26[p]= tmp2[i];
// }
// // add parity bits
// for(i= 1 ; i < 24 ; ++i)
// awid26[((i + 1) * 4) - 1]= GetParity(&awid26[i * 4], ODD, 3);
return false;
}
// int CmdReadTrace(const char *Cmd)
// {
// uint8_t bits[LF_BITSSTREAM_LEN] = {0x00};
// uint8_t * bitstream = bits;
// uint8_t si = 5;
// uint32_t bl0 = PackBits(si, 32, bitstream);
// uint32_t bl1 = PackBits(si+32, 32, bitstream);
// uint32_t acl = PackBits(si, 8, bitstream); si += 8;
// uint32_t mfc = PackBits(si, 8, bitstream); si += 8;
// uint32_t cid = PackBits(si, 5, bitstream); si += 5;
// uint32_t icr = PackBits(si, 3, bitstream); si += 3;
// uint32_t year = PackBits(si, 4, bitstream); si += 4;
// uint32_t quarter = PackBits(si, 2, bitstream); si += 2;
// uint32_t lotid = PackBits(si, 12, bitstream); si += 12;
// uint32_t wafer = PackBits(si, 5, bitstream); si += 5;
// uint32_t dw = PackBits(si, 15, bitstream);
// PrintAndLog("");
// PrintAndLog("-- T55xx Trace Information ----------------------------------");
// PrintAndLog("-------------------------------------------------------------");
// PrintAndLog(" ACL Allocation class (ISO/IEC 15963-1) : 0x%02X (%d)", acl, acl);
// PrintAndLog(" MFC Manufacturer ID (ISO/IEC 7816-6) : 0x%02X (%d)", mfc, mfc);
// PrintAndLog(" CID : 0x%02X (%d)", cid, cid);
// PrintAndLog(" ICR IC Revision : %d",icr );
// return 0;
// }
static command_t CommandTable[] =
{
{"help", CmdHelp, 1, "This help"},
{"clone", CmdClone, 1, "<facility> <id> -- clone AWID26 to t55xx tag"},
{NULL, NULL, 0, NULL}
};
int CmdLFAWID26(const char *Cmd)
{
CmdsParse(CommandTable, Cmd);
return 0;
}
int CmdHelp(const char *Cmd)
{
CmdsHelp(CommandTable);
return 0;
}

View file

@ -1,18 +0,0 @@
//-----------------------------------------------------------------------------
//
// 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 AWID 26 commands
//-----------------------------------------------------------------------------
#ifndef CMDLFAWID26_H__
#define CMDLFAWID26_H__
int CmdLFAWID26(const char *Cmd);
int CmdClone(const char *Cmd);
bool awid26_hex_to_uid(unsigned char *response, char *awid26);
bool bcd_to_awid26_bin(unsigned char *awid26, unsigned char *bcd);
#endif

View file

@ -1,4 +1,4 @@
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
// Copyright (C) 2010 iZsh <izsh at fail0verflow.com> // Copyright (C) 2010 iZsh <izsh at fail0verflow.com>
// //
// This code is licensed to you under the terms of the GNU GPL, version 2 or, // This code is licensed to you under the terms of the GNU GPL, version 2 or,
@ -13,18 +13,12 @@
#include <inttypes.h> #include <inttypes.h>
#include "proxmark3.h" #include "proxmark3.h"
#include "ui.h" #include "ui.h"
#include "util.h"
#include "graph.h" #include "graph.h"
#include "cmdmain.h"
#include "cmdparser.h" #include "cmdparser.h"
#include "cmddata.h" #include "cmddata.h"
#include "cmdlf.h" #include "cmdlf.h"
#include "cmdlfem4x.h" #include "cmdlfem4x.h"
#include "util.h"
#include "data.h"
#define LF_TRACE_BUFF_SIZE 12000
#define LF_BITSSTREAM_LEN 1000
char *global_em410xId;
static int CmdHelp(const char *Cmd); static int CmdHelp(const char *Cmd);
@ -32,10 +26,10 @@ int CmdEMdemodASK(const char *Cmd)
{ {
char cmdp = param_getchar(Cmd, 0); char cmdp = param_getchar(Cmd, 0);
int findone = (cmdp == '1') ? 1 : 0; int findone = (cmdp == '1') ? 1 : 0;
UsbCommand c = { CMD_EM410X_DEMOD }; UsbCommand c={CMD_EM410X_DEMOD};
c.arg[0] = findone; c.arg[0]=findone;
SendCommand(&c); SendCommand(&c);
return 0; return 0;
} }
/* Read the ID of an EM410x tag. /* Read the ID of an EM410x tag.
@ -56,19 +50,23 @@ int CmdEM410xRead(const char *Cmd)
uint8_t BitStream[MAX_GRAPH_TRACE_LEN]; uint8_t BitStream[MAX_GRAPH_TRACE_LEN];
high = low = 0; high = low = 0;
// get clock /* Detect high and lows and clock */
clock = GetClock(Cmd, 0); for (i = 0; i < GraphTraceLen; i++)
{
if (GraphBuffer[i] > high)
high = GraphBuffer[i];
else if (GraphBuffer[i] < low)
low = GraphBuffer[i];
}
// Detect high and lows and clock /* get clock */
DetectHighLowInGraph( &high, &low, TRUE); clock = GetClock(Cmd, high, 0);
PrintAndLog("NUMNUM"); /* parity for our 4 columns */
// parity for our 4 columns
parity[0] = parity[1] = parity[2] = parity[3] = 0; parity[0] = parity[1] = parity[2] = parity[3] = 0;
header = rows = 0; header = rows = 0;
// manchester demodulate /* manchester demodulate */
bit = bit2idx = 0; bit = bit2idx = 0;
for (i = 0; i < (int)(GraphTraceLen / clock); i++) for (i = 0; i < (int)(GraphTraceLen / clock); i++)
{ {
@ -79,9 +77,9 @@ int CmdEM410xRead(const char *Cmd)
/* Find out if we hit both high and low peaks */ /* Find out if we hit both high and low peaks */
for (j = 0; j < clock; j++) for (j = 0; j < clock; j++)
{ {
if (GraphBuffer[(i * clock) + j] >= high) if (GraphBuffer[(i * clock) + j] == high)
hithigh = 1; hithigh = 1;
else if (GraphBuffer[(i * clock) + j] <= low) else if (GraphBuffer[(i * clock) + j] == low)
hitlow = 1; hitlow = 1;
/* it doesn't count if it's the first part of our read /* it doesn't count if it's the first part of our read
@ -104,7 +102,7 @@ int CmdEM410xRead(const char *Cmd)
retest: retest:
/* We go till 5 before the graph ends because we'll get that far below */ /* We go till 5 before the graph ends because we'll get that far below */
for (i = 0; i < bit2idx - 5; i++) for (i = 1; i < bit2idx - 5; i++)
{ {
/* Step 2: We have our header but need our tag ID */ /* Step 2: We have our header but need our tag ID */
if (header == 9 && rows < 10) if (header == 9 && rows < 10)
@ -133,7 +131,7 @@ retest:
PrintAndLog("Thought we had a valid tag but failed at word %d (i=%d)", rows + 1, i); PrintAndLog("Thought we had a valid tag but failed at word %d (i=%d)", rows + 1, i);
/* Start back rows * 5 + 9 header bits, -1 to not start at same place */ /* Start back rows * 5 + 9 header bits, -1 to not start at same place */
i -= 9 + (5 * rows) -5; i -= 9 + (5 * rows) - 5;
rows = header = 0; rows = header = 0;
} }
@ -151,8 +149,6 @@ retest:
PrintAndLog("EM410x Tag ID: %s", id); PrintAndLog("EM410x Tag ID: %s", id);
PrintAndLog("Unique Tag ID: %s", id2); PrintAndLog("Unique Tag ID: %s", id2);
global_em410xId = id;
/* Stop any loops */ /* Stop any loops */
return 1; return 1;
} }
@ -181,14 +177,12 @@ retest:
} }
/* if we've already retested after flipping bits, return */ /* if we've already retested after flipping bits, return */
if (retested++){ if (retested++)
PrintAndLog("Failed to decode"); return 0;
return 0;
}
/* if this didn't work, try flipping bits */ /* if this didn't work, try flipping bits */
for (i = 0; i < bit2idx; i++) for (i = 0; i < bit2idx; i++)
BitStream[i] ^= 1; BitStream[i] ^= 1;
goto retest; goto retest;
} }
@ -264,7 +258,7 @@ int CmdEM410xSim(const char *Cmd)
AppendGraph(0, clock, parity[2]); AppendGraph(0, clock, parity[2]);
AppendGraph(0, clock, parity[3]); AppendGraph(0, clock, parity[3]);
/* stop bit */ /* stop bit */
AppendGraph(1, clock, 0); AppendGraph(1, clock, 0);
CmdLFSim("240"); //240 start_gap. CmdLFSim("240"); //240 start_gap.
@ -285,8 +279,7 @@ int CmdEM410xWatch(const char *Cmd)
{ {
char cmdp = param_getchar(Cmd, 0); char cmdp = param_getchar(Cmd, 0);
int read_h = (cmdp == 'h'); int read_h = (cmdp == 'h');
do do {
{
if (ukbhit()) { if (ukbhit()) {
printf("\naborted via keyboard!\n"); printf("\naborted via keyboard!\n");
break; break;
@ -294,21 +287,12 @@ int CmdEM410xWatch(const char *Cmd)
CmdLFRead(read_h ? "h" : ""); CmdLFRead(read_h ? "h" : "");
CmdSamples("6000"); CmdSamples("6000");
} while ( } while (
!CmdEM410xRead("") !CmdEM410xRead("")
); );
return 0; return 0;
} }
int CmdEM410xWatchnSpoof(const char *Cmd)
{
CmdEM410xWatch(Cmd);
PrintAndLog("# Replaying : %s",global_em410xId);
CmdEM410xSim(global_em410xId);
return 0;
}
/* Read the transmitted data of an EM4x50 tag /* Read the transmitted data of an EM4x50 tag
* Format: * Format:
* *
@ -523,80 +507,48 @@ int CmdEM410xWrite(const char *Cmd)
int CmdReadWord(const char *Cmd) int CmdReadWord(const char *Cmd)
{ {
int Word = -1; //default to invalid word int Word = 16; //default to invalid word
UsbCommand c; UsbCommand c;
sscanf(Cmd, "%d", &Word); sscanf(Cmd, "%d", &Word);
if ( (Word > 15) | (Word < 0) ) { if (Word > 15) {
PrintAndLog("Word must be between 0 and 15"); PrintAndLog("Word must be between 0 and 15");
return 1; return 1;
} }
PrintAndLog("Reading word %d", Word); PrintAndLog("Reading word %d", Word);
c.cmd = CMD_EM4X_READ_WORD; c.cmd = CMD_EM4X_READ_WORD;
c.d.asBytes[0] = 0x0; //Normal mode c.d.asBytes[0] = 0x0; //Normal mode
c.arg[0] = 0; c.arg[0] = 0;
c.arg[1] = Word; c.arg[1] = Word;
c.arg[2] = 0; c.arg[2] = 0;
SendCommand(&c); SendCommand(&c);
WaitForResponse(CMD_ACK, NULL);
uint8_t data[LF_TRACE_BUFF_SIZE] = {0x00};
GetFromBigBuf(data,LF_TRACE_BUFF_SIZE,0); //3560 -- should be offset..
WaitForResponseTimeout(CMD_ACK,NULL, 1500);
for (int j = 0; j < LF_TRACE_BUFF_SIZE; j++) {
GraphBuffer[j] = ((int)data[j]);
}
GraphTraceLen = LF_TRACE_BUFF_SIZE;
uint8_t bits[LF_BITSSTREAM_LEN] = {0x00};
uint8_t * bitstream = bits;
manchester_decode(GraphBuffer, LF_TRACE_BUFF_SIZE, bitstream,LF_BITSSTREAM_LEN);
RepaintGraphWindow();
return 0; return 0;
} }
int CmdReadWordPWD(const char *Cmd) int CmdReadWordPWD(const char *Cmd)
{ {
int Word = -1; //default to invalid word int Word = 16; //default to invalid word
int Password = 0xFFFFFFFF; //default to blank password int Password = 0xFFFFFFFF; //default to blank password
UsbCommand c; UsbCommand c;
sscanf(Cmd, "%d %x", &Word, &Password); sscanf(Cmd, "%d %x", &Word, &Password);
if ( (Word > 15) | (Word < 0) ) { if (Word > 15) {
PrintAndLog("Word must be between 0 and 15"); PrintAndLog("Word must be between 0 and 15");
return 1; return 1;
} }
PrintAndLog("Reading word %d with password %08X", Word, Password); PrintAndLog("Reading word %d with password %08X", Word, Password);
c.cmd = CMD_EM4X_READ_WORD; c.cmd = CMD_EM4X_READ_WORD;
c.d.asBytes[0] = 0x1; //Password mode c.d.asBytes[0] = 0x1; //Password mode
c.arg[0] = 0; c.arg[0] = 0;
c.arg[1] = Word; c.arg[1] = Word;
c.arg[2] = Password; c.arg[2] = Password;
SendCommand(&c); SendCommand(&c);
WaitForResponse(CMD_ACK, NULL);
uint8_t data[LF_TRACE_BUFF_SIZE] = {0x00};
GetFromBigBuf(data,LF_TRACE_BUFF_SIZE,0); //3560 -- should be offset..
WaitForResponseTimeout(CMD_ACK,NULL, 1500);
for (int j = 0; j < LF_TRACE_BUFF_SIZE; j++) {
GraphBuffer[j] = ((int)data[j]);
}
GraphTraceLen = LF_TRACE_BUFF_SIZE;
uint8_t bits[LF_BITSSTREAM_LEN] = {0x00};
uint8_t * bitstream = bits;
manchester_decode(GraphBuffer, LF_TRACE_BUFF_SIZE, bitstream, LF_BITSSTREAM_LEN);
RepaintGraphWindow();
return 0; return 0;
} }
@ -613,7 +565,7 @@ int CmdWriteWord(const char *Cmd)
return 1; return 1;
} }
PrintAndLog("Writing word %d with data %08X", Word, Data); PrintAndLog("Writting word %d with data %08X", Word, Data);
c.cmd = CMD_EM4X_WRITE_WORD; c.cmd = CMD_EM4X_WRITE_WORD;
c.d.asBytes[0] = 0x0; //Normal mode c.d.asBytes[0] = 0x0; //Normal mode
@ -626,7 +578,7 @@ int CmdWriteWord(const char *Cmd)
int CmdWriteWordPWD(const char *Cmd) int CmdWriteWordPWD(const char *Cmd)
{ {
int Word = 16; //default to invalid word int Word = 8; //default to invalid word
int Data = 0xFFFFFFFF; //default to blank data int Data = 0xFFFFFFFF; //default to blank data
int Password = 0xFFFFFFFF; //default to blank password int Password = 0xFFFFFFFF; //default to blank password
UsbCommand c; UsbCommand c;
@ -638,7 +590,7 @@ int CmdWriteWordPWD(const char *Cmd)
return 1; return 1;
} }
PrintAndLog("Writing word %d with data %08X and password %08X", Word, Data, Password); PrintAndLog("Writting word %d with data %08X and password %08X", Word, Data, Password);
c.cmd = CMD_EM4X_WRITE_WORD; c.cmd = CMD_EM4X_WRITE_WORD;
c.d.asBytes[0] = 0x1; //Password mode c.d.asBytes[0] = 0x1; //Password mode
@ -649,283 +601,24 @@ int CmdWriteWordPWD(const char *Cmd)
return 0; return 0;
} }
static command_t CommandTable[] = static command_t CommandTable[] =
{ {
{"help", CmdHelp, 1, "This help"}, {"help", CmdHelp, 1, "This help"},
{"410xdemod", CmdEMdemodASK, 0, "[clock rate] -- Extract ID from EM410x tag"}, {"em410xdemod", CmdEMdemodASK, 0, "[clock rate] -- Extract ID from EM410x tag"},
{"410xread", CmdEM410xRead, 1, "[clock rate] -- Extract ID from EM410x tag"}, {"em410xread", CmdEM410xRead, 1, "[clock rate] -- Extract ID from EM410x tag"},
{"410xsim", CmdEM410xSim, 0, "<UID> -- Simulate EM410x tag"}, {"em410xsim", CmdEM410xSim, 0, "<UID> -- Simulate EM410x tag"},
{"replay", MWRem4xReplay, 0, "Watches for tag and simulates manchester encoded em4x tag"}, {"em410xwatch", CmdEM410xWatch, 0, "['h'] -- Watches for EM410x 125/134 kHz tags (option 'h' for 134)"},
{"410xwatch", CmdEM410xWatch, 0, "['h'] -- Watches for EM410x 125/134 kHz tags (option 'h' for 134)"}, {"em410xwrite", CmdEM410xWrite, 1, "<UID> <'0' T5555> <'1' T55x7> [clock rate] -- Write EM410x UID to T5555(Q5) or T55x7 tag, optionally setting clock rate"},
{"410xspoof", CmdEM410xWatchnSpoof, 0, "['h'] --- Watches for EM410x 125/134 kHz tags, and replays them. (option 'h' for 134)" }, {"em4x50read", CmdEM4x50Read, 1, "Extract data from EM4x50 tag"},
{"410xwrite", CmdEM410xWrite, 1, "<UID> <'0' T5555> <'1' T55x7> [clock rate] -- Write EM410x UID to T5555(Q5) or T55x7 tag, optionally setting clock rate"}, {"readword", CmdReadWord, 1, "<Word> -- Read EM4xxx word data"},
{"4x50read", CmdEM4x50Read, 1, "Extract data from EM4x50 tag"}, {"readwordPWD", CmdReadWordPWD, 1, "<Word> <Password> -- Read EM4xxx word data in password mode"},
{"rd", CmdReadWord, 1, "<Word 1-15> -- Read EM4xxx word data"}, {"writeword", CmdWriteWord, 1, "<Data> <Word> -- Write EM4xxx word data"},
{"rdpwd", CmdReadWordPWD, 1, "<Word 1-15> <Password> -- Read EM4xxx word data in password mode "}, {"writewordPWD", CmdWriteWordPWD, 1, "<Data> <Word> <Password> -- Write EM4xxx word data in password mode"},
{"wr", CmdWriteWord, 1, "<Data> <Word 1-15> -- Write EM4xxx word data"},
{"wrpwd", CmdWriteWordPWD, 1, "<Data> <Word 1-15> <Password> -- Write EM4xxx word data in password mode"},
{NULL, NULL, 0, NULL} {NULL, NULL, 0, NULL}
}; };
//Confirms the parity of a bitstream as well as obtaining the data (TagID) from within the appropriate memory space.
//Arguments:
// Pointer to a string containing the desired bitsream
// Pointer to a string that will receive the decoded tag ID
// Length of the bitsream pointed at in the first argument, char* _strBitStream
//Retuns:
//1 Parity confirmed
//0 Parity not confirmed
int ConfirmEm410xTagParity( char* _strBitStream, char* pID, int LengthOfBitstream )
{
int i = 0;
int rows = 0;
int Parity[4] = {0x00};
char ID[11] = {0x00};
int k = 0;
int BitStream[70] = {0x00};
int counter = 0;
//prepare variables
for ( i = 0; i <= LengthOfBitstream; i++)
{
if (_strBitStream[i] == '1')
{
k =1;
memcpy(&BitStream[i], &k,4);
}
else if (_strBitStream[i] == '0')
{
k = 0;
memcpy(&BitStream[i], &k,4);
}
}
while ( counter < 2 )
{
//set/reset variables and counters
memset(ID,0x00,sizeof(ID));
memset(Parity,0x00,sizeof(Parity));
rows = 0;
for ( i = 9; i <= LengthOfBitstream; i++)
{
if ( rows < 10 )
{
if ((BitStream[i] ^ BitStream[i+1] ^ BitStream[i+2] ^ BitStream[i+3]) == BitStream[i+4])
{
sprintf(ID+rows, "%x", (8 * BitStream[i]) + (4 * BitStream[i+1]) + (2 * BitStream[i+2]) + (1 * BitStream[i+3]));
rows++;
/* Keep parity info and move four bits ahead*/
Parity[0] ^= BitStream[i];
Parity[1] ^= BitStream[i+1];
Parity[2] ^= BitStream[i+2];
Parity[3] ^= BitStream[i+3];
i += 4;
}
}
if ( rows == 10 )
{
if ( BitStream[i] == Parity[0] && BitStream[i+1] == Parity[1] &&
BitStream[i+2] == Parity[2] && BitStream[i+3] == Parity[3] &&
BitStream[i+4] == 0)
{
memcpy(pID,ID,strlen(ID));
return 1;
}
}
}
printf("[PARITY ->]Failed. Flipping Bits, and rechecking parity for bitstream:\n[PARITY ->]");
for (k = 0; k < LengthOfBitstream; k++)
{
BitStream[k] ^= 1;
printf("%i", BitStream[k]);
}
puts(" ");
counter++;
}
return 0;
}
//Reads and demodulates an em410x RFID tag. It further allows slight modification to the decoded bitstream
//Once a suitable bitstream has been identified, and if needed, modified, it is replayed. Allowing emulation of the
//"stolen" rfid tag.
//No meaningful returns or arguments.
int MWRem4xReplay(const char* Cmd)
{
// //header traces
// static char ArrayTraceZero[] = { '0','0','0','0','0','0','0','0','0' };
// static char ArrayTraceOne[] = { '1','1','1','1','1','1','1','1','1' };
// //local string variables
// char strClockRate[10] = {0x00};
// char strAnswer[4] = {0x00};
// char strTempBufferMini[2] = {0x00};
// //our outbound bit-stream
// char strSimulateBitStream[65] = {0x00};
// //integers
// int iClockRate = 0;
// int needle = 0;
// int j = 0;
// int iFirstHeaderOffset = 0x00000000;
// int numManchesterDemodBits=0;
// //boolean values
// bool bInverted = false;
// //pointers to strings. memory will be allocated.
// char* pstrInvertBitStream = 0x00000000;
// char* pTempBuffer = 0x00000000;
// char* pID = 0x00000000;
// char* strBitStreamBuffer = 0x00000000;
// puts("###################################");
// puts("#### Em4x Replay ##");
// puts("#### R.A.M. June 2013 ##");
// puts("###################################");
// //initialize
// CmdLFRead("");
// //Collect ourselves 10,000 samples
// CmdSamples("10000");
// puts("[->]preforming ASK demodulation\n");
// //demodulate ask
// Cmdaskdemod("0");
// iClockRate = DetectClock(0);
// sprintf(strClockRate, "%i\n",iClockRate);
// printf("[->]Detected ClockRate: %s\n", strClockRate);
// //If detected clock rate is something completely unreasonable, dont go ahead
// if ( iClockRate < 0xFFFE )
// {
// pTempBuffer = (char*)malloc(MAX_GRAPH_TRACE_LEN);
// if (pTempBuffer == 0x00000000)
// return 0;
// memset(pTempBuffer,0x00,MAX_GRAPH_TRACE_LEN);
// //Preform manchester de-modulation and display in a single line.
// numManchesterDemodBits = CmdManchesterDemod( strClockRate );
// //note: numManchesterDemodBits is set above in CmdManchesterDemod()
// if ( numManchesterDemodBits == 0 )
// return 0;
// strBitStreamBuffer = malloc(numManchesterDemodBits+1);
// if ( strBitStreamBuffer == 0x00000000 )
// return 0;
// memset(strBitStreamBuffer, 0x00, (numManchesterDemodBits+1));
// //fill strBitStreamBuffer with demodulated, string formatted bits.
// for ( j = 0; j <= numManchesterDemodBits; j++ )
// {
// sprintf(strTempBufferMini, "%i",BitStream[j]);
// strcat(strBitStreamBuffer,strTempBufferMini);
// }
// printf("[->]Demodulated Bitstream: \n%s\n", strBitStreamBuffer);
// //Reset counter and select most probable bit stream
// j = 0;
// while ( j < numManchesterDemodBits )
// {
// memset(strSimulateBitStream,0x00,64);
// //search for header of nine (9) 0's : 000000000 or nine (9) 1's : 1111 1111 1
// if ( ( strncmp(strBitStreamBuffer+j, ArrayTraceZero, sizeof(ArrayTraceZero)) == 0 ) ||
// ( strncmp(strBitStreamBuffer+j, ArrayTraceOne, sizeof(ArrayTraceOne)) == 0 ) )
// {
// iFirstHeaderOffset = j;
// memcpy(strSimulateBitStream, strBitStreamBuffer+j,64);
// printf("[->]Offset of Header");
// if ( strncmp(strBitStreamBuffer+iFirstHeaderOffset, "0", 1) == 0 )
// printf("'%s'", ArrayTraceZero );
// else
// printf("'%s'", ArrayTraceOne );
// printf(": %i\nHighlighted string : %s\n",iFirstHeaderOffset,strSimulateBitStream);
// //allow us to escape loop or choose another frame
// puts("[<-]Are we happy with this sample? [Y]es/[N]o");
// gets(strAnswer);
// if ( ( strncmp(strAnswer,"y",1) == 0 ) || ( strncmp(strAnswer,"Y",1) == 0 ) )
// {
// j = numManchesterDemodBits+1;
// break;
// }
// }
// j++;
// }
// }
// else return 0;
// //Do we want the buffer inverted?
// memset(strAnswer, 0x00, sizeof(strAnswer));
// printf("[<-]Do you wish to invert the highlighted bitstream? [Y]es/[N]o\n");
// gets(strAnswer);
// if ( ( strncmp("y", strAnswer,1) == 0 ) || ( strncmp("Y", strAnswer, 1 ) == 0 ) )
// {
// //allocate heap memory
// pstrInvertBitStream = (char*)malloc(numManchesterDemodBits);
// if ( pstrInvertBitStream != 0x00000000 )
// {
// memset(pstrInvertBitStream,0x00,numManchesterDemodBits);
// bInverted = true;
// //Invert Bitstream
// for ( needle = 0; needle <= numManchesterDemodBits; needle++ )
// {
// if (strSimulateBitStream[needle] == '0')
// strcat(pstrInvertBitStream,"1");
// else if (strSimulateBitStream[needle] == '1')
// strcat(pstrInvertBitStream,"0");
// }
// printf("[->]Inverted bitstream: %s\n", pstrInvertBitStream);
// }
// }
// //Confirm parity of selected string
// pID = (char*)malloc(11);
// if (pID != 0x00000000)
// {
// memset(pID, 0x00, 11);
// if (ConfirmEm410xTagParity(strSimulateBitStream,pID, 64) == 1)
// {
// printf("[->]Parity confirmed for selected bitstream!\n");
// printf("[->]Tag ID was detected as: [hex]:%s\n",pID );
// }
// else
// printf("[->]Parity check failed for the selected bitstream!\n");
// }
// //Spoof
// memset(strAnswer, 0x00, sizeof(strAnswer));
// printf("[<-]Do you wish to continue with the EM4x simulation? [Y]es/[N]o\n");
// gets(strAnswer);
// if ( ( strncmp(strAnswer,"y",1) == 0 ) || ( strncmp(strAnswer,"Y",1) == 0 ) )
// {
// strcat(pTempBuffer, strClockRate);
// strcat(pTempBuffer, " ");
// if (bInverted == true)
// strcat(pTempBuffer,pstrInvertBitStream);
// if (bInverted == false)
// strcat(pTempBuffer,strSimulateBitStream);
// //inform the user
// puts("[->]Starting simulation now: \n");
// //Simulate tag with prepared buffer.
// CmdLFSimManchester(pTempBuffer);
// }
// else if ( ( strcmp("n", strAnswer) == 0 ) || ( strcmp("N", strAnswer ) == 0 ) )
// printf("[->]Exiting procedure now...\n");
// else
// printf("[->]Erroneous selection\nExiting procedure now....\n");
// //Clean up -- Exit function
// //clear memory, then release pointer.
// if ( pstrInvertBitStream != 0x00000000 )
// {
// memset(pstrInvertBitStream,0x00,numManchesterDemodBits);
// free(pstrInvertBitStream);
// }
// if ( pTempBuffer != 0x00000000 )
// {
// memset(pTempBuffer,0x00,MAX_GRAPH_TRACE_LEN);
// free(pTempBuffer);
// }
// if ( pID != 0x00000000 )
// {
// memset(pID,0x00,11);
// free(pID);
// }
// if ( strBitStreamBuffer != 0x00000000 )
// {
// memset(strBitStreamBuffer,0x00,numManchesterDemodBits);
// free(strBitStreamBuffer);
// }
return 0;
}
int CmdLFEM4X(const char *Cmd) int CmdLFEM4X(const char *Cmd)
{ {
CmdsParse(CommandTable, Cmd); CmdsParse(CommandTable, Cmd);

View file

@ -22,6 +22,5 @@ int CmdReadWord(const char *Cmd);
int CmdReadWordPWD(const char *Cmd); int CmdReadWordPWD(const char *Cmd);
int CmdWriteWord(const char *Cmd); int CmdWriteWord(const char *Cmd);
int CmdWriteWordPWD(const char *Cmd); int CmdWriteWordPWD(const char *Cmd);
int MWRem4xReplay(const char* Cmd);
#endif #endif

View file

@ -39,12 +39,12 @@ int CmdHIDDemod(const char *Cmd)
int CmdHIDDemodFSK(const char *Cmd) int CmdHIDDemodFSK(const char *Cmd)
{ {
int findone = 0; int findone=0;
if(Cmd[0]=='1') findone=1; if(Cmd[0]=='1') findone=1;
UsbCommand c = {CMD_HID_DEMOD_FSK}; UsbCommand c={CMD_HID_DEMOD_FSK};
c.arg[0]=findone; c.arg[0]=findone;
SendCommand(&c); SendCommand(&c);
return 0; return 0;
} }
int CmdHIDSim(const char *Cmd) int CmdHIDSim(const char *Cmd)

View file

@ -15,9 +15,9 @@
#include "proxmark3.h" #include "proxmark3.h"
#include "ui.h" #include "ui.h"
#include "cmdparser.h" #include "cmdparser.h"
#include "../include/common.h" #include "common.h"
#include "util.h" #include "util.h"
#include "../include/hitag2.h" #include "hitag2.h"
#include "sleep.h" #include "sleep.h"
#include "cmdmain.h" #include "cmdmain.h"
@ -29,7 +29,7 @@ size_t nbytes(size_t nbits) {
int CmdLFHitagList(const char *Cmd) int CmdLFHitagList(const char *Cmd)
{ {
uint8_t got[TRACE_BUFFER_SIZE]; uint8_t got[3000];
GetFromBigBuf(got,sizeof(got),0); GetFromBigBuf(got,sizeof(got),0);
WaitForResponse(CMD_ACK,NULL); WaitForResponse(CMD_ACK,NULL);
@ -39,25 +39,11 @@ int CmdLFHitagList(const char *Cmd)
int i = 0; int i = 0;
int prev = -1; int prev = -1;
int len = strlen(Cmd);
char filename[FILE_PATH_SIZE] = { 0x00 };
FILE* pf = NULL;
if (len > FILE_PATH_SIZE)
len = FILE_PATH_SIZE;
memcpy(filename, Cmd, len);
if (strlen(filename) > 0) {
if ((pf = fopen(filename,"wb")) == NULL) {
PrintAndLog("Error: Could not open file [%s]",filename);
return 1;
}
}
for (;;) { for (;;) {
if(i >= 1900) {
if(i >= TRACE_BUFFER_SIZE) { break; } break;
}
bool isResponse; bool isResponse;
int timestamp = *((uint32_t *)(got+i)); int timestamp = *((uint32_t *)(got+i));
@ -82,7 +68,9 @@ int CmdLFHitagList(const char *Cmd)
if (len > 100) { if (len > 100) {
break; break;
} }
if (i + len >= TRACE_BUFFER_SIZE) { break;} if (i + len >= 1900) {
break;
}
uint8_t *frame = (got+i+9); uint8_t *frame = (got+i+9);
@ -115,22 +103,18 @@ int CmdLFHitagList(const char *Cmd)
line); line);
if (pf) { // if (pf) {
fprintf(pf," +%7d: %3d: %s %s\n", // fprintf(pf," +%7d: %3d: %s %s\n",
(prev < 0 ? 0 : (timestamp - prev)), // (prev < 0 ? 0 : (timestamp - prev)),
bits, // bits,
(isResponse ? "TAG" : " "), // (isResponse ? "TAG" : " "),
line); // line);
} // }
prev = timestamp; prev = timestamp;
i += (len + 9); i += (len + 9);
} }
if (pf) {
fclose(pf);
PrintAndLog("Recorded activity succesfully written to file: %s", filename);
}
return 0; return 0;
} }
@ -142,14 +126,12 @@ int CmdLFHitagSnoop(const char *Cmd) {
} }
int CmdLFHitagSim(const char *Cmd) { int CmdLFHitagSim(const char *Cmd) {
UsbCommand c = {CMD_SIMULATE_HITAG};
UsbCommand c = {CMD_SIMULATE_HITAG}; char filename[256] = { 0x00 };
char filename[FILE_PATH_SIZE] = { 0x00 };
FILE* pf; FILE* pf;
bool tag_mem_supplied; bool tag_mem_supplied;
int len = strlen(Cmd);
if (len > FILE_PATH_SIZE) len = FILE_PATH_SIZE; param_getstr(Cmd,0,filename);
memcpy(filename, Cmd, len);
if (strlen(filename) > 0) { if (strlen(filename) > 0) {
if ((pf = fopen(filename,"rb+")) == NULL) { if ((pf = fopen(filename,"rb+")) == NULL) {
@ -158,10 +140,10 @@ int CmdLFHitagSim(const char *Cmd) {
} }
tag_mem_supplied = true; tag_mem_supplied = true;
if (fread(c.d.asBytes,48,1,pf) == 0) { if (fread(c.d.asBytes,48,1,pf) == 0) {
PrintAndLog("Error: File reading error"); PrintAndLog("Error: File reading error");
fclose(pf); fclose(pf);
return 1; return 1;
} }
fclose(pf); fclose(pf);
} else { } else {
tag_mem_supplied = false; tag_mem_supplied = false;
@ -245,11 +227,11 @@ int CmdLFHitagReader(const char *Cmd) {
static command_t CommandTable[] = static command_t CommandTable[] =
{ {
{"help", CmdHelp, 1, "This help"}, {"help", CmdHelp, 1, "This help"},
{"list", CmdLFHitagList, 1, "<outfile> List Hitag trace history"}, {"list", CmdLFHitagList, 1, "List Hitag trace history"},
{"reader", CmdLFHitagReader, 1, "Act like a Hitag Reader"}, {"reader", CmdLFHitagReader, 1, "Act like a Hitag Reader"},
{"sim", CmdLFHitagSim, 1, "<infile> Simulate Hitag transponder"}, {"sim", CmdLFHitagSim, 1, "Simulate Hitag transponder"},
{"snoop", CmdLFHitagSnoop, 1, "Eavesdrop Hitag communication"}, {"snoop", CmdLFHitagSnoop, 1, "Eavesdrop Hitag communication"},
{NULL, NULL, 0, NULL} {NULL, NULL, 0, NULL}
}; };
int CmdLFHitag(const char *Cmd) int CmdLFHitag(const char *Cmd)

View file

@ -16,13 +16,13 @@ static int CmdHelp(const char *Cmd);
int CmdIODemodFSK(const char *Cmd) int CmdIODemodFSK(const char *Cmd)
{ {
int findone = 0; int findone=0;
if (Cmd[0] =='1') findone = 1; if(Cmd[0]=='1') findone=1;
UsbCommand c={CMD_IO_DEMOD_FSK}; UsbCommand c={CMD_IO_DEMOD_FSK};
c.arg[0] = findone; c.arg[0]=findone;
SendCommand(&c); SendCommand(&c);
return 0; return 0;
} }
int CmdIOProxDemod(const char *Cmd){ int CmdIOProxDemod(const char *Cmd){
@ -66,10 +66,10 @@ int CmdIOClone(const char *Cmd)
static command_t CommandTable[] = static command_t CommandTable[] =
{ {
{"help", CmdHelp, 1, "This help"}, {"help", CmdHelp, 1, "This help"},
{"demod", CmdIOProxDemod, 1, "Demodulate Stream"}, {"demod", CmdIOProxDemod, 1, "Demodulate Stream"},
{"fskdemod", CmdIODemodFSK, 0, "['1'] Realtime IO FSK demodulator (option '1' for one tag only)"}, {"fskdemod", CmdIODemodFSK, 0, "['1'] Realtime IO FSK demodulator (option '1' for one tag only)"},
{"clone", CmdIOClone, 0, "Clone ioProx Tag"}, {"clone", CmdIOClone, 0, "Clone ioProx Tag"},
{NULL, NULL, 0, NULL} {NULL, NULL, 0, NULL}
}; };

View file

@ -13,86 +13,58 @@
#include "proxmark3.h" #include "proxmark3.h"
#include "ui.h" #include "ui.h"
#include "graph.h" #include "graph.h"
#include "cmdmain.h"
#include "cmdparser.h" #include "cmdparser.h"
#include "cmddata.h" #include "cmddata.h"
#include "cmdlf.h" #include "cmdlf.h"
#include "cmdlft55xx.h" #include "cmdlft55xx.h"
#include "util.h"
#include "data.h"
#define LF_TRACE_BUFF_SIZE 20000 // 32 x 32 x 10 (32 bit times numofblock (7), times clock skip..)
#define LF_BITSSTREAM_LEN 1000 // more then 1000 bits shouldn't happend.. 8block * 4 bytes * 8bits =
static int CmdHelp(const char *Cmd); static int CmdHelp(const char *Cmd);
int CmdReadBlk(const char *Cmd) int CmdReadBlk(const char *Cmd)
{ {
int block = -1; int Block = 8; //default to invalid block
sscanf(Cmd, "%d", &block); UsbCommand c;
if ((block > 7) | (block < 0)) { sscanf(Cmd, "%d", &Block);
PrintAndLog("Block must be between 0 and 7");
return 1;
}
UsbCommand c; if (Block > 7) {
c.cmd = CMD_T55XX_READ_BLOCK; PrintAndLog("Block must be between 0 and 7");
c.d.asBytes[0] = 0x00; return 1;
c.arg[0] = 0; }
c.arg[1] = block;
c.arg[2] = 0;
SendCommand(&c);
WaitForResponse(CMD_ACK, NULL);
uint8_t data[LF_TRACE_BUFF_SIZE] = {0x00}; PrintAndLog("Reading block %d", Block);
GetFromBigBuf(data,LF_TRACE_BUFF_SIZE,0); //3560 -- should be offset.. c.cmd = CMD_T55XX_READ_BLOCK;
WaitForResponseTimeout(CMD_ACK,NULL, 1500); c.d.asBytes[0] = 0x0; //Normal mode
c.arg[0] = 0;
for (int j = 0; j < LF_TRACE_BUFF_SIZE; j++) { c.arg[1] = Block;
GraphBuffer[j] = (int)data[j]; c.arg[2] = 0;
} SendCommand(&c);
GraphTraceLen = LF_TRACE_BUFF_SIZE;
ManchesterDemod(block);
RepaintGraphWindow();
return 0; return 0;
} }
int CmdReadBlkPWD(const char *Cmd) int CmdReadBlkPWD(const char *Cmd)
{ {
int Block = -1; //default to invalid block int Block = 8; //default to invalid block
int Password = 0xFFFFFFFF; //default to blank Block 7 int Password = 0xFFFFFFFF; //default to blank Block 7
UsbCommand c; UsbCommand c;
sscanf(Cmd, "%d %x", &Block, &Password); sscanf(Cmd, "%d %x", &Block, &Password);
if ((Block > 7) | (Block < 0)) { if (Block > 7) {
PrintAndLog("Block must be between 0 and 7"); PrintAndLog("Block must be between 0 and 7");
return 1; return 1;
} }
PrintAndLog("Reading page 0 block %d pwd %08X", Block, Password); PrintAndLog("Reading block %d with password %08X", Block, Password);
c.cmd = CMD_T55XX_READ_BLOCK; c.cmd = CMD_T55XX_READ_BLOCK;
c.d.asBytes[0] = 0x1; //Password mode c.d.asBytes[0] = 0x1; //Password mode
c.arg[0] = 0; c.arg[0] = 0;
c.arg[1] = Block; c.arg[1] = Block;
c.arg[2] = Password; c.arg[2] = Password;
SendCommand(&c); SendCommand(&c);
WaitForResponse(CMD_ACK, NULL);
uint8_t data[LF_TRACE_BUFF_SIZE] = {0x00};
GetFromBigBuf(data,LF_TRACE_BUFF_SIZE,0); //3560 -- should be offset..
WaitForResponseTimeout(CMD_ACK,NULL, 1500);
for (int j = 0; j < LF_TRACE_BUFF_SIZE; j++) {
GraphBuffer[j] = ((int)data[j]);
}
GraphTraceLen = LF_TRACE_BUFF_SIZE;
ManchesterDemod(Block);
RepaintGraphWindow();
return 0; return 0;
} }
@ -147,349 +119,22 @@ int CmdWriteBlkPWD(const char *Cmd)
int CmdReadTrace(const char *Cmd) int CmdReadTrace(const char *Cmd)
{ {
char cmdp = param_getchar(Cmd, 0);
if (strlen(Cmd) > 1 || cmdp == 'h' || cmdp == 'H') { PrintAndLog("Reading traceability data");
PrintAndLog("Usage: lf t55xx trace [use data from Graphbuffer]");
PrintAndLog(" [use data from Graphbuffer], if not set, try reading data from tag.");
PrintAndLog("");
PrintAndLog(" sample: lf t55xx trace");
PrintAndLog(" sample: lf t55xx trace 1");
return 0;
}
if ( strlen(Cmd)==0){
UsbCommand c = {CMD_T55XX_READ_TRACE, {0, 0, 0}};
SendCommand(&c);
WaitForResponse(CMD_ACK, NULL);
uint8_t data[LF_TRACE_BUFF_SIZE] = {0x00};
GetFromBigBuf(data,LF_TRACE_BUFF_SIZE,0); //3560 -- should be offset..
WaitForResponseTimeout(CMD_ACK,NULL, 1500);
for (int j = 0; j < LF_TRACE_BUFF_SIZE; j++) {
GraphBuffer[j] = ((int)data[j]);
}
GraphTraceLen = LF_TRACE_BUFF_SIZE;
}
uint8_t bits[LF_BITSSTREAM_LEN] = {0x00};
uint8_t * bitstream = bits;
manchester_decode(GraphBuffer, LF_TRACE_BUFF_SIZE, bitstream, LF_BITSSTREAM_LEN);
RepaintGraphWindow();
uint8_t si = 5;
uint32_t bl0 = PackBits(si, 32, bitstream);
uint32_t bl1 = PackBits(si+32, 32, bitstream);
uint32_t acl = PackBits(si, 8, bitstream); si += 8;
uint32_t mfc = PackBits(si, 8, bitstream); si += 8;
uint32_t cid = PackBits(si, 5, bitstream); si += 5;
uint32_t icr = PackBits(si, 3, bitstream); si += 3;
uint32_t year = PackBits(si, 4, bitstream); si += 4;
uint32_t quarter = PackBits(si, 2, bitstream); si += 2;
uint32_t lotid = PackBits(si, 12, bitstream); si += 12;
uint32_t wafer = PackBits(si, 5, bitstream); si += 5;
uint32_t dw = PackBits(si, 15, bitstream);
PrintAndLog("");
PrintAndLog("-- T55xx Trace Information ----------------------------------");
PrintAndLog("-------------------------------------------------------------");
PrintAndLog(" ACL Allocation class (ISO/IEC 15963-1) : 0x%02X (%d)", acl, acl);
PrintAndLog(" MFC Manufacturer ID (ISO/IEC 7816-6) : 0x%02X (%d)", mfc, mfc);
PrintAndLog(" CID : 0x%02X (%d)", cid, cid);
PrintAndLog(" ICR IC Revision : %d",icr );
PrintAndLog(" Manufactured");
PrintAndLog(" Year/Quarter : %d/%d",2000+year, quarter );
PrintAndLog(" Lot ID : %d", lotid );
PrintAndLog(" Wafer number : %d", wafer);
PrintAndLog(" Die Number : %d", dw);
PrintAndLog("-------------------------------------------------------------");
PrintAndLog(" Raw Data - Page 1");
PrintAndLog(" Block 0 : 0x%08X %s", bl0, sprint_bin(bitstream+5,32) );
PrintAndLog(" Block 0 : 0x%08X %s", bl1, sprint_bin(bitstream+37,32) );
PrintAndLog("-------------------------------------------------------------");
/*
TRACE - BLOCK O
Bits Definition HEX
1-8 ACL Allocation class (ISO/IEC 15963-1) 0xE0
9-16 MFC Manufacturer ID (ISO/IEC 7816-6) 0x15 Atmel Corporation
17-21 CID 0x1 = Atmel ATA5577M1 0x2 = Atmel ATA5577M2
22-24 ICR IC revision
25-28 YEAR (BCD encoded) 9 (= 2009)
29-30 QUARTER 1,2,3,4
31-32 LOT ID
TRACE - BLOCK 1
1-12 LOT ID
13-17 Wafer number
18-32 DW, die number sequential
*/
UsbCommand c = {CMD_T55XX_READ_TRACE, {0, 0, 0}};
SendCommand(&c);
return 0; return 0;
} }
int CmdInfo(const char *Cmd){
/*
Page 0 Block 0 Configuration data.
Normal mode
Extended mode
*/
char cmdp = param_getchar(Cmd, 0);
if (strlen(Cmd) > 1 || cmdp == 'h' || cmdp == 'H') {
PrintAndLog("Usage: lf t55xx info [use data from Graphbuffer]");
PrintAndLog(" [use data from Graphbuffer], if not set, try reading data from tag.");
PrintAndLog("");
PrintAndLog(" sample: lf t55xx info");
PrintAndLog(" sample: lf t55xx info 1");
return 0;
}
if ( strlen(Cmd) == 0 ){
CmdReadBlk("0");
}
uint8_t bits[LF_BITSSTREAM_LEN] = {0x00};
manchester_decode(GraphBuffer, LF_TRACE_BUFF_SIZE, bits, LF_BITSSTREAM_LEN);
uint8_t si = 5;
uint32_t bl0 = PackBits(si, 32, bits);
uint32_t safer = PackBits(si, 4, bits); si += 4;
uint32_t resv = PackBits(si, 7, bits); si += 7;
uint32_t dbr = PackBits(si, 3, bits); si += 3;
uint32_t extend = PackBits(si, 1, bits); si += 1;
uint32_t datamodulation = PackBits(si, 5, bits); si += 5;
uint32_t pskcf = PackBits(si, 2, bits); si += 2;
uint32_t aor = PackBits(si, 1, bits); si += 1;
uint32_t otp = PackBits(si, 1, bits); si += 1;
uint32_t maxblk = PackBits(si, 3, bits); si += 3;
uint32_t pwd = PackBits(si, 1, bits); si += 1;
uint32_t sst = PackBits(si, 1, bits); si += 1;
uint32_t fw = PackBits(si, 1, bits); si += 1;
uint32_t inv = PackBits(si, 1, bits); si += 1;
uint32_t por = PackBits(si, 1, bits); si += 1;
PrintAndLog("");
PrintAndLog("-- T55xx Configuration --------------------------------------");
PrintAndLog("-------------------------------------------------------------");
PrintAndLog(" Safer key : %s", GetSaferStr(safer));
PrintAndLog(" reserved : %d", resv);
PrintAndLog(" Data bit rate : %s", GetBitRateStr(dbr));
PrintAndLog(" eXtended mode : %s", (extend) ? "Yes - Warning":"No");
PrintAndLog(" Modulation : %s", GetModulationStr(datamodulation) );
PrintAndLog(" PSK clock freq : %d", pskcf);
PrintAndLog(" AOR - Answer on Request : %s", (aor) ? "Yes":"No");
PrintAndLog(" OTP - One Time Pad : %s", (otp) ? "Yes - Warning":"No" );
PrintAndLog(" Max block : %d", maxblk);
PrintAndLog(" Password mode : %s", (pwd) ? "Yes":"No");
PrintAndLog(" Sequence Start Terminator : %s", (sst) ? "Yes":"No");
PrintAndLog(" Fast Write : %s", (fw) ? "Yes":"No");
PrintAndLog(" Inverse data : %s", (inv) ? "Yes":"No");
PrintAndLog(" POR-Delay : %s", (por) ? "Yes":"No");
PrintAndLog("-------------------------------------------------------------");
PrintAndLog(" Raw Data - Page 0");
PrintAndLog(" Block 0 : 0x%08X %s", bl0, sprint_bin(bits+5,32) );
PrintAndLog("-------------------------------------------------------------");
return 0;
}
int CmdDump(const char *Cmd){
char cmdp = param_getchar(Cmd, 0);
char s[20];
uint8_t pwd[4] = {0x00};
bool hasPwd = ( strlen(Cmd) > 0);
if ( cmdp == 'h' || cmdp == 'H') {
PrintAndLog("Usage: lf t55xx dump <password>");
PrintAndLog(" sample: lf t55xx dump FFFFFFFF");
return 0;
}
if ( hasPwd ){
if (param_gethex(Cmd, 0, pwd, 8)) {
PrintAndLog("password must include 8 HEX symbols");
return 0;
}
}
for ( int i = 0; i <8; ++i){
memset(s,0,sizeof(s));
if ( hasPwd ) {
sprintf(s,"%d %02x%02x%02x%02x", i, pwd[0],pwd[1],pwd[2],pwd[3]);
CmdReadBlkPWD(s);
} else {
sprintf(s,"%d", i);
CmdReadBlk(s);
}
}
return 0;
}
int CmdIceFsk(const char *Cmd){
if (!HasGraphData()) return 0;
iceFsk3(GraphBuffer, LF_TRACE_BUFF_SIZE);
RepaintGraphWindow();
return 0;
}
int CmdIceManchester(const char *Cmd){
ManchesterDemod( -1);
return 0;
}
int ManchesterDemod(int blockNum){
if (!HasGraphData()) return 0;
uint8_t sizebyte = 32;
// the value 5 was selected during empirical studies of the decoded data. Some signal noise to skip.
uint8_t offset = 5;
uint32_t blockData;
uint8_t bits[LF_BITSSTREAM_LEN] = {0x00};
uint8_t * bitstream = bits;
//manchester_decode(GraphBuffer, LF_TRACE_BUFF_SIZE, bitstream, LF_BITSSTREAM_LEN);
manchester_decode(GraphBuffer, LF_TRACE_BUFF_SIZE, bits, LF_BITSSTREAM_LEN);
//blockData = PackBits(offset, sizebyte, bitstream);
blockData = PackBits(offset, sizebyte, bits);
if ( blockNum < 0)
PrintAndLog(" Decoded : 0x%08X %s", blockData, sprint_bin(bitstream+offset,sizebyte) );
else
PrintAndLog(" Block %d : 0x%08X %s", blockNum, blockData, sprint_bin(bitstream+offset,sizebyte) );
return 0;
}
char * GetBitRateStr(uint32_t id){
static char buf[40];
char *retStr = buf;
switch (id){
case 0:
sprintf(retStr,"%d - RF/8",id);
break;
case 1:
sprintf(retStr,"%d - RF/16",id);
break;
case 2:
sprintf(retStr,"%d - RF/32",id);
break;
case 3:
sprintf(retStr,"%d - RF/40",id);
break;
case 4:
sprintf(retStr,"%d - RF/50",id);
break;
case 5:
sprintf(retStr,"%d - RF/64",id);
break;
case 6:
sprintf(retStr,"%d - RF/100",id);
break;
case 7:
sprintf(retStr,"%d - RF/128",id);
break;
default:
sprintf(retStr,"%d - (Unknown)",id);
break;
}
return buf;
}
char * GetSaferStr(uint32_t id){
static char buf[40];
char *retStr = buf;
sprintf(retStr,"%d",id);
if (id == 6) {
sprintf(retStr,"%d - pasdwd",id);
}
if (id == 9 ){
sprintf(retStr,"%d - testmode ",id);
}
return buf;
}
char * GetModulationStr( uint32_t id){
static char buf[40];
char *retStr = buf;
switch (id){
case 0:
sprintf(retStr,"%d - DIRECT (ASK/NRZ)",id);
break;
case 1:
sprintf(retStr,"%d - PSK 1 phase change when input changes",id);
break;
case 2:
sprintf(retStr,"%d - PSK 2 phase change on bitclk if input high",id);
break;
case 3:
sprintf(retStr,"%d - PSK 3 phase change on rising edge of input",id);
break;
case 4:
sprintf(retStr,"%d - FSK 1 RF/8 RF/5",id);
break;
case 5:
sprintf(retStr,"%d - FSK 2 RF/8 RF/10",id);
break;
case 6:
sprintf(retStr,"%d - FSK 1a RF/5 RF/8",id);
break;
case 7:
sprintf(retStr,"%d - FSK 2a RF/10 RF/8",id);
break;
case 8:
sprintf(retStr,"%d - Manschester",id);
break;
case 16:
sprintf(retStr,"%d - Biphase",id);
break;
case 17:
sprintf(retStr,"%d - Reserved",id);
break;
default:
sprintf(retStr,"0x%02X (Unknown)",id);
break;
}
return buf;
}
uint32_t PackBits(uint8_t start, uint8_t len, uint8_t* bits){
int i = start;
int j = len-1;
if (len > 32) {
return 0;
}
uint32_t tmp = 0;
for (; j >= 0; --j, ++i){
tmp |= bits[i] << j;
}
return tmp;
}
static command_t CommandTable[] = static command_t CommandTable[] =
{ {
{"help", CmdHelp, 1, "This help"}, {"help", CmdHelp, 1, "This help"},
{"rd", CmdReadBlk, 0, "<block> -- Read T55xx block data (page 0)"}, {"readblock", CmdReadBlk, 1, "<Block> -- Read T55xx block data (page 0)"},
{"rdpwd", CmdReadBlkPWD, 0, "<block> <password> -- Read T55xx block data with password mode"}, {"readblockPWD", CmdReadBlkPWD, 1, "<Block> <Password> -- Read T55xx block data in password mode(page 0)"},
{"wr", CmdWriteBlk, 0, "<data> <block> -- Write T55xx block data (page 0)"}, {"writeblock", CmdWriteBlk, 1, "<Data> <Block> -- Write T55xx block data (page 0)"},
{"wrpwd", CmdWriteBlkPWD, 0, "<data> <block> <password> -- Write T55xx block data with password"}, {"writeblockPWD", CmdWriteBlkPWD, 1, "<Data> <Block> <Password> -- Write T55xx block data in password mode(page 0)"},
{"trace", CmdReadTrace, 0, "[1] Read T55xx traceability data (page 1/ blk 0-1)"}, {"readtrace", CmdReadTrace, 1, "Read T55xx traceability data (page 1)"},
{"info", CmdInfo, 0, "[1] Read T55xx configuration data (page 0/ blk 0)"},
{"dump", CmdDump, 0, "[password] Dump T55xx card block 0-7. optional with password"},
{"fsk", CmdIceFsk, 0, "FSK demod"},
{"man", CmdIceManchester, 0, "Manchester demod (with SST)"},
{NULL, NULL, 0, NULL} {NULL, NULL, 0, NULL}
}; };

View file

@ -17,12 +17,5 @@ int CmdReadBlkPWD(const char *Cmd);
int CmdWriteBlk(const char *Cmd); int CmdWriteBlk(const char *Cmd);
int CmdWriteBLkPWD(const char *Cmd); int CmdWriteBLkPWD(const char *Cmd);
int CmdReadTrace(const char *Cmd); int CmdReadTrace(const char *Cmd);
int CmdInfo(const char *Cmd);
int CmdIceFsk(const char *Cmd);
int CmdIceManchester(const char *Cmd);
int ManchesterDemod(int block);
char * GetBitRateStr(uint32_t id);
char * GetSaferStr(uint32_t id);
char * GetModulationStr( uint32_t id);
uint32_t PackBits(uint8_t start, uint8_t len, uint8_t* bitstream);
#endif #endif

View file

@ -16,7 +16,7 @@
#include "cmdparser.h" #include "cmdparser.h"
#include "proxmark3.h" #include "proxmark3.h"
#include "data.h" #include "data.h"
#include "../include/usb_cmd.h" #include "usb_cmd.h"
#include "ui.h" #include "ui.h"
#include "cmdhf.h" #include "cmdhf.h"
#include "cmddata.h" #include "cmddata.h"
@ -42,14 +42,14 @@ static int cmd_tail;//Starts as 0
static command_t CommandTable[] = static command_t CommandTable[] =
{ {
{"help", CmdHelp, 1, "This help. Use '<command> help' for details of a particular command."}, {"help", CmdHelp, 1, "This help. Use '<command> help' for details of a particular command."},
{"data", CmdData, 1, "{ Plot window / data buffer manipulation... }"}, {"data", CmdData, 1, "{ Plot window / data buffer manipulation... }"},
{"hf", CmdHF, 1, "{ High Frequency commands... }"}, {"hf", CmdHF, 1, "{ High Frequency commands... }"},
{"hw", CmdHW, 1, "{ Hardware commands... }"}, {"hw", CmdHW, 1, "{ Hardware commands... }"},
{"lf", CmdLF, 1, "{ Low Frequency commands... }"}, {"lf", CmdLF, 1, "{ Low Frequency commands... }"},
{"script", CmdScript, 1,"{ Scripting commands }"}, {"script", CmdScript, 1,"{ Scripting commands }"},
{"quit", CmdQuit, 1, "Exit program"}, {"quit", CmdQuit, 1, "Exit program"},
{"exit", CmdQuit, 1, "Exit program"}, {"exit", CmdQuit, 1, "Exit program"},
{NULL, NULL, 0, NULL} {NULL, NULL, 0, NULL}
}; };
@ -131,25 +131,26 @@ int getCommand(UsbCommand* response)
*/ */
bool WaitForResponseTimeout(uint32_t cmd, UsbCommand* response, size_t ms_timeout) { bool WaitForResponseTimeout(uint32_t cmd, UsbCommand* response, size_t ms_timeout) {
UsbCommand resp; UsbCommand resp;
if (response == NULL) if (response == NULL) {
response = &resp; response = &resp;
}
// Wait until the command is received
for(size_t dm_seconds=0; dm_seconds < ms_timeout/10; dm_seconds++) {
// Wait until the command is received while(getCommand(response))
for(size_t dm_seconds=0; dm_seconds < ms_timeout/10; dm_seconds++) { {
if(response->cmd == cmd){
while(getCommand(response)) { return true;
if(response->cmd == cmd){ }
return true; }
} msleep(10); // XXX ugh
} if (dm_seconds == 200) { // Two seconds elapsed
msleep(10); // XXX ugh PrintAndLog("Waiting for a response from the proxmark...");
if (dm_seconds == 200) { // Two seconds elapsed PrintAndLog("Don't forget to cancel its operation first by pressing on the button");
PrintAndLog("Waiting for a response from the proxmark..."); }
PrintAndLog("Don't forget to cancel its operation first by pressing on the button");
}
} }
return false; return false;
} }
@ -172,29 +173,29 @@ void CommandReceived(char *Cmd) {
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
void UsbCommandReceived(UsbCommand *UC) void UsbCommandReceived(UsbCommand *UC)
{ {
switch(UC->cmd) { switch(UC->cmd) {
// First check if we are handling a debug message // First check if we are handling a debug message
case CMD_DEBUG_PRINT_STRING: { case CMD_DEBUG_PRINT_STRING: {
char s[USB_CMD_DATA_SIZE+1] = {0x00}; char s[USB_CMD_DATA_SIZE+1] = {0x00};
size_t len = MIN(UC->arg[0],USB_CMD_DATA_SIZE); size_t len = MIN(UC->arg[0],USB_CMD_DATA_SIZE);
memcpy(s,UC->d.asBytes,len); memcpy(s,UC->d.asBytes,len);
PrintAndLog("#db# %s ", s); PrintAndLog("#db# %s ", s);
return; return;
} break; } 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]); PrintAndLog("#db# %08x, %08x, %08x \r\n", UC->arg[0], UC->arg[1], UC->arg[2]);
return; return;
} break; } break;
case CMD_DOWNLOADED_RAW_ADC_SAMPLES_125K: { case CMD_DOWNLOADED_RAW_ADC_SAMPLES_125K: {
sample_buf_len += UC->arg[1]; sample_buf_len += UC->arg[1];
memcpy(sample_buf+(UC->arg[0]),UC->d.asBytes,UC->arg[1]); memcpy(sample_buf+(UC->arg[0]),UC->d.asBytes,UC->arg[1]);
} break; } break;
default: default:
break; break;
} }
storeCommand(UC); storeCommand(UC);
} }

View file

@ -11,7 +11,7 @@
#ifndef CMDMAIN_H__ #ifndef CMDMAIN_H__
#define CMDMAIN_H__ #define CMDMAIN_H__
#include "../include/usb_cmd.h" #include "usb_cmd.h"
#include "cmdparser.h" #include "cmdparser.h"
void UsbCommandReceived(UsbCommand *UC); void UsbCommandReceived(UsbCommand *UC);
void CommandReceived(char *Cmd); void CommandReceived(char *Cmd);

View file

@ -13,9 +13,6 @@
#include <stdint.h> #include <stdint.h>
//trace buffer size as defined in armsrc/apps.h TRACE_SIZE
#define TRACE_BUFFER_SIZE 4096
#define FILE_PATH_SIZE 1000
#define SAMPLE_BUFFER_SIZE 64 #define SAMPLE_BUFFER_SIZE 64
extern uint8_t* sample_buf; extern uint8_t* sample_buf;

View file

@ -16,7 +16,7 @@
#include "flash.h" #include "flash.h"
#include "elf.h" #include "elf.h"
#include "proxendian.h" #include "proxendian.h"
#include "../include/usb_cmd.h" #include "usb_cmd.h"
void SendCommand(UsbCommand* txcmd); void SendCommand(UsbCommand* txcmd);
void ReceiveCommand(UsbCommand* rxcmd); void ReceiveCommand(UsbCommand* rxcmd);
@ -275,7 +275,7 @@ static int get_proxmark_state(uint32_t *state)
{ {
UsbCommand c; UsbCommand c;
c.cmd = CMD_DEVICE_INFO; c.cmd = CMD_DEVICE_INFO;
SendCommand(&c); SendCommand(&c);
UsbCommand resp; UsbCommand resp;
ReceiveCommand(&resp); ReceiveCommand(&resp);
@ -404,11 +404,11 @@ static int write_block(uint32_t address, uint8_t *data, uint32_t length)
memset(block_buf, 0xFF, BLOCK_SIZE); memset(block_buf, 0xFF, BLOCK_SIZE);
memcpy(block_buf, data, length); memcpy(block_buf, data, length);
UsbCommand c; UsbCommand c;
c.cmd = CMD_FINISH_WRITE; c.cmd = CMD_FINISH_WRITE;
c.arg[0] = address; c.arg[0] = address;
memcpy(c.d.asBytes, block_buf, length); memcpy(c.d.asBytes, block_buf, length);
SendCommand(&c); SendCommand(&c);
return wait_for_ack(); return wait_for_ack();
} }
@ -469,7 +469,7 @@ void flash_free(flash_file_t *ctx)
// just reset the unit // just reset the unit
int flash_stop_flashing(void) { int flash_stop_flashing(void) {
UsbCommand c = {CMD_HARDWARE_RESET}; UsbCommand c = {CMD_HARDWARE_RESET};
SendCommand(&c); SendCommand(&c);
msleep(100); msleep(100);
return 0; return 0;
} }

View file

@ -13,7 +13,7 @@
#include "proxmark3.h" #include "proxmark3.h"
#include "flash.h" #include "flash.h"
#include "uart.h" #include "uart.h"
#include "../include/usb_cmd.h" #include "usb_cmd.h"
#ifdef _WIN32 #ifdef _WIN32
# define unlink(x) # define unlink(x)

View file

@ -9,7 +9,6 @@
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
#include <stdio.h> #include <stdio.h>
#include <stdbool.h>
#include <string.h> #include <string.h>
#include "ui.h" #include "ui.h"
#include "graph.h" #include "graph.h"
@ -22,13 +21,11 @@ int GraphTraceLen;
void AppendGraph(int redraw, int clock, int bit) void AppendGraph(int redraw, int clock, int bit)
{ {
int i; int i;
int half = (int)(clock/2);
int firstbit = bit ^ 1;
for (i = 0; i < half; ++i) for (i = 0; i < (int)(clock / 2); ++i)
GraphBuffer[GraphTraceLen++] = firstbit; GraphBuffer[GraphTraceLen++] = bit ^ 1;
for (i = 0; i <= half; ++i) for (i = (int)(clock / 2); i < clock; ++i)
GraphBuffer[GraphTraceLen++] = bit; GraphBuffer[GraphTraceLen++] = bit;
if (redraw) if (redraw)
@ -39,8 +36,6 @@ void AppendGraph(int redraw, int clock, int bit)
int ClearGraph(int redraw) int ClearGraph(int redraw)
{ {
int gtl = GraphTraceLen; int gtl = GraphTraceLen;
memset(GraphBuffer, 0x00, GraphTraceLen);
GraphTraceLen = 0; GraphTraceLen = 0;
if (redraw) if (redraw)
@ -49,96 +44,146 @@ int ClearGraph(int redraw)
return gtl; return gtl;
} }
void SetGraphBuf(uint8_t *buff, int size) /*
* Detect clock rate
*/
//decommissioned - has difficulty detecting rf/32
/*
int DetectClockOld(int peak)
{ {
if ( buff == NULL ) return; int i;
int clock = 0xFFFF;
int lastpeak = 0;
uint16_t i = 0; // Detect peak if we don't have one
if ( size > MAX_GRAPH_TRACE_LEN ) if (!peak)
size = MAX_GRAPH_TRACE_LEN; for (i = 0; i < GraphTraceLen; ++i)
ClearGraph(0); if (GraphBuffer[i] > peak)
for (; i < size; ++i){ peak = GraphBuffer[i];
GraphBuffer[i] = buff[i];
} // peak=(int)(peak*.75);
GraphTraceLen = size; for (i = 1; i < GraphTraceLen; ++i)
RepaintGraphWindow(); {
return; // If this is the beginning of a peak
if (GraphBuffer[i - 1] != GraphBuffer[i] && GraphBuffer[i] >= peak)
{
// Find lowest difference between peaks
if (lastpeak && i - lastpeak < clock)
clock = i - lastpeak;
lastpeak = i;
}
}
return clock;
} }
*/
/*
NOW IN LFDEMOD.C
// Copies grahpbuff to buff. // by marshmellow
// while triming values to the range -127 -- 127. // not perfect especially with lower clocks or VERY good antennas (heavy wave clipping)
int GetFromGraphBuf(uint8_t *buff) // maybe somehow adjust peak trimming value based on samples to fix?
int DetectASKClock(int peak)
{ {
if ( buff == NULL ) return -1; int i=0;
uint32_t i = 0; int low=0;
int clk[]={16,32,40,50,64,100,128,256};
for (; i < GraphTraceLen; ++i){ int loopCnt = 256;
if (GraphTraceLen<loopCnt) loopCnt = GraphTraceLen;
// trim upper and lower values. if (!peak){
if (GraphBuffer[i] > 127) for (i=0;i<loopCnt;++i){
GraphBuffer[i] = 127; if(GraphBuffer[i]>peak){
else if (GraphBuffer[i] < -127) peak = GraphBuffer[i];
GraphBuffer[i] = -127; }
if(GraphBuffer[i]<low){
buff[i] = (uint8_t)(GraphBuffer[i] + 128); low = GraphBuffer[i];
} }
return i; }
peak=(int)(peak*.75);
low= (int)(low*.75);
}
int ii;
int clkCnt;
int tol = 0;
int bestErr=1000;
int errCnt[]={0,0,0,0,0,0,0,0};
for(clkCnt=0; clkCnt<6;++clkCnt){
if (clk[clkCnt]==32){
tol=1;
}else{
tol=0;
}
bestErr=1000;
for (ii=0; ii<loopCnt; ++ii){
if ((GraphBuffer[ii]>=peak) || (GraphBuffer[ii]<=low)){
errCnt[clkCnt]=0;
for (i=0; i<((int)(GraphTraceLen/clk[clkCnt])-1); ++i){
if (GraphBuffer[ii+(i*clk[clkCnt])]>=peak || GraphBuffer[ii+(i*clk[clkCnt])]<=low){
}else if(GraphBuffer[ii+(i*clk[clkCnt])-tol]>=peak || GraphBuffer[ii+(i*clk[clkCnt])-tol]<=low){
}else if(GraphBuffer[ii+(i*clk[clkCnt])+tol]>=peak || GraphBuffer[ii+(i*clk[clkCnt])+tol]<=low){
}else{ //error no peak detected
errCnt[clkCnt]++;
}
}
if(errCnt[clkCnt]==0) return clk[clkCnt];
if(errCnt[clkCnt]<bestErr) bestErr=errCnt[clkCnt];
}
}
}
int iii=0;
int best=0;
for (iii=0; iii<6;++iii){
if (errCnt[iii]<errCnt[best]){
best = iii;
}
}
// PrintAndLog("DEBUG: clkCnt: %d, ii: %d, i: %d peak: %d, low: %d, errcnt: %d, errCnt64: %d",clkCnt,ii,i,peak,low,errCnt[best],errCnt[4]);
return clk[best];
}
*/
void setGraphBuf(uint8_t *buff,int size)
{
int i=0;
ClearGraph(0);
for (; i < size; ++i){
GraphBuffer[i]=buff[i];
}
GraphTraceLen=size;
RepaintGraphWindow();
return;
}
int getFromGraphBuf(uint8_t *buff)
{
uint32_t i;
for (i=0;i<GraphTraceLen;++i){
if (GraphBuffer[i]>127) GraphBuffer[i]=127; //trim
if (GraphBuffer[i]<-127) GraphBuffer[i]=-127; //trim
buff[i]=(uint8_t)(GraphBuffer[i]+128);
}
return i;
} }
/* Get or auto-detect clock rate */ /* Get or auto-detect clock rate */
int GetClock(const char *str, int verbose) int GetClock(const char *str, int peak, int verbose)
{ {
int clock; int clock;
// int clock2;
sscanf(str, "%i", &clock);
if (!strcmp(str, ""))
clock = 0;
sscanf(str, "%i", &clock); /* Auto-detect clock */
if (!strcmp(str, "")) if (!clock)
clock = 0; {
uint8_t grph[MAX_GRAPH_TRACE_LEN]={0};
int size = getFromGraphBuf(grph);
clock = DetectASKClock(grph,size,0);
//clock2 = DetectClock2(peak);
/* Only print this message if we're not looping something */
if (!verbose){
PrintAndLog("Auto-detected clock rate: %d", clock);
//PrintAndLog("clock2: %d",clock2);
}
}
/* Auto-detect clock */ return clock;
if (!clock) {
uint8_t grph[MAX_GRAPH_TRACE_LEN] = {0x00};
int size = GetFromGraphBuf(grph);
if ( size < 0 ) {
PrintAndLog("Failed to copy from graphbuffer");
return -1;
}
clock = DetectASKClock(grph, size, 0);
/* Only print this message if we're not looping something */
if (verbose)
PrintAndLog("Auto-detected clock rate: %d", clock);
}
return clock;
}
// A simple test to see if there is any data inside Graphbuffer.
bool HasGraphData(){
if ( GraphTraceLen <= 0) {
PrintAndLog("No data available, try reading something first");
return false;
}
return true;
}
// Detect high and lows in Grapbuffer.
// Only loops the first 256 values.
void DetectHighLowInGraph(int *high, int *low, bool addFuzz) {
uint8_t loopMax = 255;
if ( loopMax > GraphTraceLen)
loopMax = GraphTraceLen;
for (uint8_t i = 0; i < loopMax; ++i) {
if (GraphBuffer[i] > *high)
*high = GraphBuffer[i];
else if (GraphBuffer[i] < *low)
*low = GraphBuffer[i];
}
//12% fuzz in case highs and lows aren't clipped
if (addFuzz) {
*high = (int)(*high * .88);
*low = (int)(*low * .88);
}
} }

View file

@ -10,16 +10,17 @@
#ifndef GRAPH_H__ #ifndef GRAPH_H__
#define GRAPH_H__ #define GRAPH_H__
#include <stdint.h>
void AppendGraph(int redraw, int clock, int bit); void AppendGraph(int redraw, int clock, int bit);
int ClearGraph(int redraw); int ClearGraph(int redraw);
int GetFromGraphBuf(uint8_t *buff); //int DetectClock(int peak);
int GetClock(const char *str, int verbose); int getFromGraphBuf(uint8_t *buff);
void SetGraphBuf(uint8_t *buff,int size); int GetClock(const char *str, int peak, int verbose);
bool HasGraphData(); void setGraphBuf(uint8_t *buff,int size);
void DetectHighLowInGraph(int *high, int *low, bool addFuzz);
#define MAX_GRAPH_TRACE_LEN (1024*128) #define MAX_GRAPH_TRACE_LEN (1024*128)
extern int GraphBuffer[MAX_GRAPH_TRACE_LEN]; extern int GraphBuffer[MAX_GRAPH_TRACE_LEN];
extern int GraphTraceLen; extern int GraphTraceLen;
#endif #endif

View file

@ -1,17 +1,5 @@
/***************************************************************************** /*****************************************************************************
* WARNING * This file is part of iClassCipher. It is a reconstructon of the cipher engine
*
* THIS CODE IS CREATED FOR EXPERIMENTATION AND EDUCATIONAL USE ONLY.
*
* USAGE OF THIS CODE IN OTHER WAYS MAY INFRINGE UPON THE INTELLECTUAL
* PROPERTY OF OTHER PARTIES, SUCH AS INSIDE SECURE AND HID GLOBAL,
* AND MAY EXPOSE YOU TO AN INFRINGEMENT ACTION FROM THOSE PARTIES.
*
* THIS CODE SHOULD NEVER BE USED TO INFRINGE PATENTS OR INTELLECTUAL PROPERTY RIGHTS.
*
*****************************************************************************
*
* This file is part of loclass. It is a reconstructon of the cipher engine
* used in iClass, and RFID techology. * used in iClass, and RFID techology.
* *
* The implementation is based on the work performed by * The implementation is based on the work performed by
@ -225,16 +213,16 @@ void doMAC(uint8_t *cc_nr_p, int length, uint8_t *div_key_p, uint8_t mac[4])
memcpy(cc_nr,cc_nr_p,length); memcpy(cc_nr,cc_nr_p,length);
memcpy(div_key,div_key_p,8); memcpy(div_key,div_key_p,8);
reverse_arraybytes(cc_nr,length); reverse_arraybytes(cc_nr,length);
BitstreamIn bitstream = {cc_nr,length * 8,0}; BitstreamIn bitstream = {cc_nr,length * 8,0};
uint8_t dest []= {0,0,0,0,0,0,0,0}; uint8_t dest []= {0,0,0,0,0,0,0,0};
BitstreamOut out = { dest, sizeof(dest)*8, 0 }; BitstreamOut out = { dest, sizeof(dest)*8, 0 };
MAC(div_key,bitstream, out); MAC(div_key,bitstream, out);
//The output MAC must also be reversed //The output MAC must also be reversed
reverse_arraybytes(dest, sizeof(dest)); reverse_arraybytes(dest, sizeof(dest));
memcpy(mac,dest,4); memcpy(mac, dest, 4);
//printf("Calculated_MAC\t%02x%02x%02x%02x\n", dest[0],dest[1],dest[2],dest[3]); //printf("Calculated_MAC\t%02x%02x%02x%02x\n", dest[0],dest[1],dest[2],dest[3]);
free(cc_nr); free(cc_nr);
return; return;
} }
@ -260,8 +248,8 @@ int testMAC()
prnlog("[+] FAILED: MAC calculation failed:"); prnlog("[+] FAILED: MAC calculation failed:");
printarr(" Calculated_MAC", calculated_mac, 4); printarr(" Calculated_MAC", calculated_mac, 4);
printarr(" Correct_MAC ", correct_MAC, 4); printarr(" Correct_MAC ", correct_MAC, 4);
return 1; return 1;
} }
return 0; return 0;
} }

View file

@ -1,17 +1,5 @@
/***************************************************************************** /*****************************************************************************
* WARNING * This file is part of iClassCipher. It is a reconstructon of the cipher engine
*
* THIS CODE IS CREATED FOR EXPERIMENTATION AND EDUCATIONAL USE ONLY.
*
* USAGE OF THIS CODE IN OTHER WAYS MAY INFRINGE UPON THE INTELLECTUAL
* PROPERTY OF OTHER PARTIES, SUCH AS INSIDE SECURE AND HID GLOBAL,
* AND MAY EXPOSE YOU TO AN INFRINGEMENT ACTION FROM THOSE PARTIES.
*
* THIS CODE SHOULD NEVER BE USED TO INFRINGE PATENTS OR INTELLECTUAL PROPERTY RIGHTS.
*
*****************************************************************************
*
* This file is part of loclass. It is a reconstructon of the cipher engine
* used in iClass, and RFID techology. * used in iClass, and RFID techology.
* *
* The implementation is based on the work performed by * The implementation is based on the work performed by

View file

@ -1,17 +1,5 @@
/***************************************************************************** /*****************************************************************************
* WARNING * This file is part of iClassCipher. It is a reconstructon of the cipher engine
*
* THIS CODE IS CREATED FOR EXPERIMENTATION AND EDUCATIONAL USE ONLY.
*
* USAGE OF THIS CODE IN OTHER WAYS MAY INFRINGE UPON THE INTELLECTUAL
* PROPERTY OF OTHER PARTIES, SUCH AS INSIDE SECURE AND HID GLOBAL,
* AND MAY EXPOSE YOU TO AN INFRINGEMENT ACTION FROM THOSE PARTIES.
*
* THIS CODE SHOULD NEVER BE USED TO INFRINGE PATENTS OR INTELLECTUAL PROPERTY RIGHTS.
*
*****************************************************************************
*
* This file is part of loclass. It is a reconstructon of the cipher engine
* used in iClass, and RFID techology. * used in iClass, and RFID techology.
* *
* The implementation is based on the work performed by * The implementation is based on the work performed by

View file

@ -1,17 +1,5 @@
/***************************************************************************** /*****************************************************************************
* WARNING * This file is part of iClassCipher. It is a reconstructon of the cipher engine
*
* THIS CODE IS CREATED FOR EXPERIMENTATION AND EDUCATIONAL USE ONLY.
*
* USAGE OF THIS CODE IN OTHER WAYS MAY INFRINGE UPON THE INTELLECTUAL
* PROPERTY OF OTHER PARTIES, SUCH AS INSIDE SECURE AND HID GLOBAL,
* AND MAY EXPOSE YOU TO AN INFRINGEMENT ACTION FROM THOSE PARTIES.
*
* THIS CODE SHOULD NEVER BE USED TO INFRINGE PATENTS OR INTELLECTUAL PROPERTY RIGHTS.
*
*****************************************************************************
*
* This file is part of loclass. It is a reconstructon of the cipher engine
* used in iClass, and RFID techology. * used in iClass, and RFID techology.
* *
* The implementation is based on the work performed by * The implementation is based on the work performed by

View file

@ -1,41 +1,3 @@
/*****************************************************************************
* WARNING
*
* THIS CODE IS CREATED FOR EXPERIMENTATION AND EDUCATIONAL USE ONLY.
*
* USAGE OF THIS CODE IN OTHER WAYS MAY INFRINGE UPON THE INTELLECTUAL
* PROPERTY OF OTHER PARTIES, SUCH AS INSIDE SECURE AND HID GLOBAL,
* AND MAY EXPOSE YOU TO AN INFRINGEMENT ACTION FROM THOSE PARTIES.
*
* THIS CODE SHOULD NEVER BE USED TO INFRINGE PATENTS OR INTELLECTUAL PROPERTY RIGHTS.
*
*****************************************************************************
*
* This file is part of loclass. It is a reconstructon of the cipher engine
* used in iClass, and RFID techology.
*
* The implementation is based on the work performed by
* Flavio D. Garcia, Gerhard de Koning Gans, Roel Verdult and
* Milosch Meriac in the paper "Dismantling IClass".
*
* Copyright (C) 2014 Martin Holst Swende
*
* This is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as published
* by the Free Software Foundation.
*
* This file is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with loclass. If not, see <http://www.gnu.org/licenses/>.
*
*
*
****************************************************************************/
#include <stdint.h> #include <stdint.h>
#include <stdbool.h> #include <stdbool.h>
#include <string.h> #include <string.h>
@ -552,6 +514,7 @@ int bruteforceDump(uint8_t dump[], size_t dumpsize, uint16_t keytable[])
*/ */
int bruteforceFile(const char *filename, uint16_t keytable[]) int bruteforceFile(const char *filename, uint16_t keytable[])
{ {
FILE *f = fopen(filename, "rb"); FILE *f = fopen(filename, "rb");
if(!f) { if(!f) {
prnlog("Failed to read from file '%s'", filename); prnlog("Failed to read from file '%s'", filename);
@ -563,7 +526,7 @@ int bruteforceFile(const char *filename, uint16_t keytable[])
fseek(f, 0, SEEK_SET); fseek(f, 0, SEEK_SET);
uint8_t *dump = malloc(fsize); uint8_t *dump = malloc(fsize);
size_t bytes_read = fread(dump, fsize, 1, f); size_t bytes_read = fread(dump, 1, fsize, f);
fclose(f); fclose(f);
if (bytes_read < fsize) if (bytes_read < fsize)
@ -614,9 +577,18 @@ int _testBruteforce()
**** The 64-bit HS Custom Key Value = 5B7C62C491C11B39 **** **** The 64-bit HS Custom Key Value = 5B7C62C491C11B39 ****
**/ **/
uint16_t keytable[128] = {0}; uint16_t keytable[128] = {0};
//save some time...
startvalue = 0x7B0000; //Test a few variants
errors |= bruteforceFile("iclass_dump.bin",keytable); if(fileExists("iclass_dump.bin"))
{
errors |= bruteforceFile("iclass_dump.bin",keytable);
}else if(fileExists("loclass/iclass_dump.bin")){
errors |= bruteforceFile("loclass/iclass_dump.bin",keytable);
}else if(fileExists("client/loclass/iclass_dump.bin")){
errors |= bruteforceFile("client/loclass/iclass_dump.bin",keytable);
}else{
prnlog("Error: The file iclass_dump.bin was not found!");
}
} }
return errors; return errors;
} }

View file

@ -1,42 +1,3 @@
/*****************************************************************************
* WARNING
*
* THIS CODE IS CREATED FOR EXPERIMENTATION AND EDUCATIONAL USE ONLY.
*
* USAGE OF THIS CODE IN OTHER WAYS MAY INFRINGE UPON THE INTELLECTUAL
* PROPERTY OF OTHER PARTIES, SUCH AS INSIDE SECURE AND HID GLOBAL,
* AND MAY EXPOSE YOU TO AN INFRINGEMENT ACTION FROM THOSE PARTIES.
*
* THIS CODE SHOULD NEVER BE USED TO INFRINGE PATENTS OR INTELLECTUAL PROPERTY RIGHTS.
*
*****************************************************************************
*
* This file is part of loclass. It is a reconstructon of the cipher engine
* used in iClass, and RFID techology.
*
* The implementation is based on the work performed by
* Flavio D. Garcia, Gerhard de Koning Gans, Roel Verdult and
* Milosch Meriac in the paper "Dismantling IClass".
*
* Copyright (C) 2014 Martin Holst Swende
*
* This is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as published
* by the Free Software Foundation.
*
* This file is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with loclass. If not, see <http://www.gnu.org/licenses/>.
*
*
*
****************************************************************************/
#ifndef ELITE_CRACK_H #ifndef ELITE_CRACK_H
#define ELITE_CRACK_H #define ELITE_CRACK_H
void permutekey(uint8_t key[8], uint8_t dest[8]); void permutekey(uint8_t key[8], uint8_t dest[8]);

View file

@ -1,41 +1,3 @@
/*****************************************************************************
* WARNING
*
* THIS CODE IS CREATED FOR EXPERIMENTATION AND EDUCATIONAL USE ONLY.
*
* USAGE OF THIS CODE IN OTHER WAYS MAY INFRINGE UPON THE INTELLECTUAL
* PROPERTY OF OTHER PARTIES, SUCH AS INSIDE SECURE AND HID GLOBAL,
* AND MAY EXPOSE YOU TO AN INFRINGEMENT ACTION FROM THOSE PARTIES.
*
* THIS CODE SHOULD NEVER BE USED TO INFRINGE PATENTS OR INTELLECTUAL PROPERTY RIGHTS.
*
*****************************************************************************
*
* This file is part of loclass. It is a reconstructon of the cipher engine
* used in iClass, and RFID techology.
*
* The implementation is based on the work performed by
* Flavio D. Garcia, Gerhard de Koning Gans, Roel Verdult and
* Milosch Meriac in the paper "Dismantling IClass".
*
* Copyright (C) 2014 Martin Holst Swende
*
* This is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as published
* by the Free Software Foundation.
*
* This file is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with loclass. If not, see <http://www.gnu.org/licenses/>.
*
*
*
****************************************************************************/
#include <stdio.h> #include <stdio.h>
#include <string.h> #include <string.h>
#include <stdlib.h> #include <stdlib.h>
@ -51,11 +13,11 @@
int fileExists(const char *filename) { int fileExists(const char *filename) {
#ifdef _WIN32 #ifdef _WIN32
struct _stat fileStat; struct _stat st;
int result = _stat(filename, &fileStat); int result = _stat(filename, &st);
#else #else
struct stat fileStat; struct stat st;
int result = stat(filename, &fileStat); int result = stat(filename, &st);
#endif #endif
return result == 0; return result == 0;
} }
@ -76,33 +38,21 @@ int saveFile(const char *preferredName, const char *suffix, const void* data, si
/* We should have a valid filename now, e.g. dumpdata-3.bin */ /* We should have a valid filename now, e.g. dumpdata-3.bin */
/*Opening file for writing in binary mode*/ /*Opening file for writing in binary mode*/
FILE *fh=fopen(fileName,"wb"); FILE *fileHandle=fopen(fileName,"wb");
if(!fh) { if(!fileHandle) {
PrintAndLog("Failed to write to file '%s'", fileName); PrintAndLog("Failed to write to file '%s'", fileName);
free(fh); free(fileName);
return 1; return 1;
} }
fwrite(data, 1, datalen, fh); fwrite(data, 1, datalen, fileHandle);
fclose(fh); fclose(fileHandle);
PrintAndLog("Saved data to '%s'", fileName); PrintAndLog(">Saved data to '%s'", fileName);
free(fileName); free(fileName);
return 0; return 0;
} }
int loadFile(const char *fileName, void* data, size_t datalen)
{
FILE *filehandle = fopen(fileName, "rb");
if(!filehandle) {
PrintAndLog("Failed to read from file '%s'", fileName);
free(filehandle);
return 1;
}
fread(data,datalen,1,filehandle);
fclose(filehandle);
free(filehandle);
return 0;
}
/** /**
* Utility function to print to console. This is used consistently within the library instead * Utility function to print to console. This is used consistently within the library instead
* of printf, but it actually only calls printf (and adds a linebreak). * of printf, but it actually only calls printf (and adds a linebreak).
@ -113,11 +63,11 @@ int loadFile(const char *fileName, void* data, size_t datalen)
*/ */
void prnlog(char *fmt, ...) void prnlog(char *fmt, ...)
{ {
char buffer[2048] = {0};
va_list args; va_list args;
va_start(args,fmt); va_start(args,fmt);
PrintAndLog(fmt, args); vsprintf (buffer,fmt, args);
//vprintf(fmt,args);
va_end(args); va_end(args);
//printf("\n"); PrintAndLog(buffer);
} }

View file

@ -1,41 +1,3 @@
/*****************************************************************************
* WARNING
*
* THIS CODE IS CREATED FOR EXPERIMENTATION AND EDUCATIONAL USE ONLY.
*
* USAGE OF THIS CODE IN OTHER WAYS MAY INFRINGE UPON THE INTELLECTUAL
* PROPERTY OF OTHER PARTIES, SUCH AS INSIDE SECURE AND HID GLOBAL,
* AND MAY EXPOSE YOU TO AN INFRINGEMENT ACTION FROM THOSE PARTIES.
*
* THIS CODE SHOULD NEVER BE USED TO INFRINGE PATENTS OR INTELLECTUAL PROPERTY RIGHTS.
*
*****************************************************************************
*
* This file is part of loclass. It is a reconstructon of the cipher engine
* used in iClass, and RFID techology.
*
* The implementation is based on the work performed by
* Flavio D. Garcia, Gerhard de Koning Gans, Roel Verdult and
* Milosch Meriac in the paper "Dismantling IClass".
*
* Copyright (C) 2014 Martin Holst Swende
*
* This is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as published
* by the Free Software Foundation.
*
* This file is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with loclass. If not, see <http://www.gnu.org/licenses/>.
*
*
*
****************************************************************************/
#ifndef FILEUTILS_H #ifndef FILEUTILS_H
#define FILEUTILS_H #define FILEUTILS_H
/** /**
@ -49,16 +11,7 @@
* @return 0 for ok, 1 for failz * @return 0 for ok, 1 for failz
*/ */
int saveFile(const char *preferredName, const char *suffix, const void* data, size_t datalen); int saveFile(const char *preferredName, const char *suffix, const void* data, size_t datalen);
/**
* @brief Utility function to save load binary data from a a file. This method takes a filename,
* Should only be used for fixed-size binary files
* @param fileName the name of the file
* @param data a buffer to place data in
* @param datalen the length of the data/data.
* @return
*/
int loadFile(const char *fileName, void* data, size_t datalen);
/** /**
* Utility function to print to console. This is used consistently within the library instead * Utility function to print to console. This is used consistently within the library instead
@ -68,4 +21,5 @@ int loadFile(const char *fileName, void* data, size_t datalen);
* @param fmt * @param fmt
*/ */
void prnlog(char *fmt, ...); void prnlog(char *fmt, ...);
int fileExists(const char *filename);
#endif // FILEUTILS_H #endif // FILEUTILS_H

View file

@ -1,92 +0,0 @@
#include <stdio.h>
#include "cipherutils.h"
#include <stdint.h>
#include <stdbool.h>
#include <string.h>
#include <unistd.h>
#include <ctype.h>
#include "elite_crack.h"
void calc_score(uint8_t* csn, uint8_t* k)
{
uint8_t score =0 ;
uint8_t i;
uint8_t goodvals[16] = {0};
uint8_t uniq_vals[8] = {0};
memset(goodvals, 0x00, 16);
memset(uniq_vals, 0x00, 8);
uint8_t badval = 0;
int badscore =0;
for(i=0; i < 8 ; i++)
{
if(k[i] == 0x01) continue;
if(k[i] == 0x00) continue;
if(k[i] == 0x45) continue;
if(k[i] < 16){
goodvals[k[i]] = 1;
}
// if(k[i] ==9 || k[i]==2){
// goodvals[k[i]] = 1;
// }
else if(k[i]>=16){
badscore++;
badval = k[i];
}
}
for(i =0; i < 16; i++)
{
if(goodvals[i])
{
uniq_vals[score] = i;
score +=1;
}
}
if(score >=2 && badscore < 2)
{
printf("CSN\t%02x%02x%02x%02x%02x%02x%02x%02x\t%02x %02x %02x %02x %02x %02x %02x %02x\t"
,csn[0],csn[1],csn[2],csn[3],csn[4],csn[5],csn[6],csn[7]
,k[0],k[1],k[2],k[3],k[4],k[5],k[6],k[7]
);
for(i =0 ; i < score; i++)
{
printf("%d,", uniq_vals[i]);
}
printf("\tbadscore: %d (%02x)", badscore, badval);
printf("\r\n");
}
}
void brute_hash1(){
uint8_t csn[8] = {0,0,0,0,0xf7,0xff,0x12,0xe0};
uint8_t k[8]= {0,0,0,0,0,0,0,0};
uint16_t a,b,c,d;
uint8_t testcsn[8] ={0x00,0x0d,0x0f,0xfd,0xf7,0xff,0x12,0xe0} ;
uint8_t testkey[8] ={0x05 ,0x01 ,0x00 ,0x10 ,0x45 ,0x08 ,0x45,0x56} ;
calc_score(testcsn,testkey);
printf("Brute forcing hashones\n");
//exit(1);
for(a=0;a < 256;a++)
{
//if(a > 0)printf("%d/256 done...\n", a);
for(b=0;b < 256 ; b++)
for(c=0;c < 256;c++)
for(d=0;d < 256;d++)
{
csn[0] = a;
csn[1] = b;
csn[2] = c;
csn[3] = d;
csn[4] = 0xf7;
csn[5] = 0xff;
csn[6] = 0x12;
csn[7] = 0xe0;
hash1(csn, k);
calc_score(csn,k);
}
}
}

View file

@ -1,5 +0,0 @@
#ifndef HASH1_BRUTE_H
#define HASH1_BRUTE_H
void brute_hash1();
#endif // HASH1_BRUTE_H

View file

@ -1,17 +1,5 @@
/***************************************************************************** /*****************************************************************************
* WARNING * This file is part of iClassCipher. It is a reconstructon of the cipher engine
*
* THIS CODE IS CREATED FOR EXPERIMENTATION AND EDUCATIONAL USE ONLY.
*
* USAGE OF THIS CODE IN OTHER WAYS MAY INFRINGE UPON THE INTELLECTUAL
* PROPERTY OF OTHER PARTIES, SUCH AS INSIDE SECURE AND HID GLOBAL,
* AND MAY EXPOSE YOU TO AN INFRINGEMENT ACTION FROM THOSE PARTIES.
*
* THIS CODE SHOULD NEVER BE USED TO INFRINGE PATENTS OR INTELLECTUAL PROPERTY RIGHTS.
*
*****************************************************************************
*
* This file is part of loclass. It is a reconstructon of the cipher engine
* used in iClass, and RFID techology. * used in iClass, and RFID techology.
* *
* The implementation is based on the work performed by * The implementation is based on the work performed by
@ -737,6 +725,7 @@ int doTestsWithKnownInputs()
int readKeyFile(uint8_t key[8]) int readKeyFile(uint8_t key[8])
{ {
FILE *f; FILE *f;
int retval = 1; int retval = 1;
f = fopen("iclass_key.bin", "rb"); f = fopen("iclass_key.bin", "rb");
@ -749,6 +738,7 @@ int readKeyFile(uint8_t key[8])
fclose(f); fclose(f);
} }
return retval; return retval;
} }

View file

@ -1,41 +1,3 @@
/*****************************************************************************
* WARNING
*
* THIS CODE IS CREATED FOR EXPERIMENTATION AND EDUCATIONAL USE ONLY.
*
* USAGE OF THIS CODE IN OTHER WAYS MAY INFRINGE UPON THE INTELLECTUAL
* PROPERTY OF OTHER PARTIES, SUCH AS INSIDE SECURE AND HID GLOBAL,
* AND MAY EXPOSE YOU TO AN INFRINGEMENT ACTION FROM THOSE PARTIES.
*
* THIS CODE SHOULD NEVER BE USED TO INFRINGE PATENTS OR INTELLECTUAL PROPERTY RIGHTS.
*
*****************************************************************************
*
* This file is part of loclass. It is a reconstructon of the cipher engine
* used in iClass, and RFID techology.
*
* The implementation is based on the work performed by
* Flavio D. Garcia, Gerhard de Koning Gans, Roel Verdult and
* Milosch Meriac in the paper "Dismantling IClass".
*
* Copyright (C) 2014 Martin Holst Swende
*
* This is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as published
* by the Free Software Foundation.
*
* This file is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with loclass. If not, see <http://www.gnu.org/licenses/>.
*
*
*
****************************************************************************/
#ifndef IKEYS_H #ifndef IKEYS_H
#define IKEYS_H #define IKEYS_H

View file

@ -1,17 +1,5 @@
/***************************************************************************** /*****************************************************************************
* WARNING * This file is part of iClassCipher. It is a reconstructon of the cipher engine
*
* THIS CODE IS CREATED FOR EXPERIMENTATION AND EDUCATIONAL USE ONLY.
*
* USAGE OF THIS CODE IN OTHER WAYS MAY INFRINGE UPON THE INTELLECTUAL
* PROPERTY OF OTHER PARTIES, SUCH AS INSIDE SECURE AND HID GLOBAL,
* AND MAY EXPOSE YOU TO AN INFRINGEMENT ACTION FROM THOSE PARTIES.
*
* THIS CODE SHOULD NEVER BE USED TO INFRINGE PATENTS OR INTELLECTUAL PROPERTY RIGHTS.
*
*****************************************************************************
*
* This file is part of loclass. It is a reconstructon of the cipher engine
* used in iClass, and RFID techology. * used in iClass, and RFID techology.
* *
* The implementation is based on the work performed by * The implementation is based on the work performed by
@ -30,13 +18,9 @@
* GNU General Public License for more details. * GNU General Public License for more details.
* *
* You should have received a copy of the GNU General Public License * You should have received a copy of the GNU General Public License
* along with loclass. If not, see <http://www.gnu.org/licenses/>. * along with IClassCipher. If not, see <http://www.gnu.org/licenses/>.
*
*
*
****************************************************************************/ ****************************************************************************/
#include <stdio.h> #include <stdio.h>
#include <cipherutils.h> #include <cipherutils.h>
#include <stdint.h> #include <stdint.h>
@ -80,18 +64,7 @@ int main (int argc, char **argv)
{ {
prnlog("IClass Cipher version 1.2, Copyright (C) 2014 Martin Holst Swende\n"); prnlog("IClass Cipher version 1.2, Copyright (C) 2014 Martin Holst Swende\n");
prnlog("Comes with ABSOLUTELY NO WARRANTY"); prnlog("Comes with ABSOLUTELY NO WARRANTY");
prnlog("Released as GPLv2\n"); prnlog("This is free software, and you are welcome to use, abuse and repackage, please keep the credits\n");
prnlog("WARNING");
prnlog("");
prnlog("THIS TOOL IS CREATED FOR EXPERIMENTATION AND EDUCATIONAL USE ONLY. ");
prnlog("");
prnlog("USAGE OF THIS TOOL IN OTHER WAYS MAY INFRINGE UPON THE INTELLECTUAL ");
prnlog("PROPERTY OF OTHER PARTIES, SUCH AS INSIDE SECURE AND HID GLOBAL, ");
prnlog("AND MAY EXPOSE YOU TO AN INFRINGEMENT ACTION FROM THOSE PARTIES. ");
prnlog("");
prnlog("THIS TOOL SHOULD NEVER BE USED TO INFRINGE PATENTS OR INTELLECTUAL PROPERTY RIGHTS. ");
char *fileName = NULL; char *fileName = NULL;
int c; int c;
while ((c = getopt (argc, argv, "thf:")) != -1) while ((c = getopt (argc, argv, "thf:")) != -1)

View file

@ -48,8 +48,8 @@ local _commands = {
CMD_EM4X_READ_WORD = 0x0218, CMD_EM4X_READ_WORD = 0x0218,
CMD_EM4X_WRITE_WORD = 0x0219, CMD_EM4X_WRITE_WORD = 0x0219,
CMD_IO_DEMOD_FSK = 0x021A, CMD_IO_DEMOD_FSK = 0x021A,
CMD_IO_CLONE_TAG = 0x021B, CMD_IO_CLONE_TAG = 0x021B,
CMD_EM410X_DEMOD = 0x021c, CMD_EM410X_DEMOD = 0x021C,
--/* CMD_SET_ADC_MUX: ext1 is 0 for lopkd, 1 for loraw, 2 for hipkd, 3 for hiraw */ --/* CMD_SET_ADC_MUX: ext1 is 0 for lopkd, 1 for loraw, 2 for hipkd, 3 for hiraw */
--// For the 13.56 MHz tags --// For the 13.56 MHz tags
@ -64,7 +64,6 @@ local _commands = {
CMD_ISO_15693_COMMAND_DONE = 0x0314, CMD_ISO_15693_COMMAND_DONE = 0x0314,
CMD_ISO_15693_FIND_AFI = 0x0315, CMD_ISO_15693_FIND_AFI = 0x0315,
CMD_ISO_15693_DEBUG = 0x0316, CMD_ISO_15693_DEBUG = 0x0316,
CMD_LF_SNOOP_RAW_ADC_SAMPLES = 0x0317,
--// For Hitag2 transponders --// For Hitag2 transponders
CMD_SNOOP_HITAG = 0x0370, CMD_SNOOP_HITAG = 0x0370,
@ -81,13 +80,10 @@ local _commands = {
CMD_READER_LEGIC_RF = 0x0388, CMD_READER_LEGIC_RF = 0x0388,
CMD_WRITER_LEGIC_RF = 0x0389, CMD_WRITER_LEGIC_RF = 0x0389,
CMD_EPA_PACE_COLLECT_NONCE = 0x038A, CMD_EPA_PACE_COLLECT_NONCE = 0x038A,
--//CMD_EPA_ = 0x038B,
CMD_SNOOP_ICLASS = 0x0392, CMD_SNOOP_ICLASS = 0x0392,
CMD_SIMULATE_TAG_ICLASS = 0x0393, CMD_SIMULATE_TAG_ICLASS = 0x0393,
CMD_READER_ICLASS = 0x0394, CMD_READER_ICLASS = 0x0394,
CMD_READER_ICLASS_REPLAY = 0x0395,
CMD_ICLASS_ISO14443A_WRITE = 0x0397,
--// For measurements of the antenna tuning --// For measurements of the antenna tuning
CMD_MEASURE_ANTENNA_TUNING = 0x0400, CMD_MEASURE_ANTENNA_TUNING = 0x0400,
@ -104,11 +100,8 @@ local _commands = {
CMD_MIFARE_EML_MEMSET = 0x0602, CMD_MIFARE_EML_MEMSET = 0x0602,
CMD_MIFARE_EML_MEMGET = 0x0603, CMD_MIFARE_EML_MEMGET = 0x0603,
CMD_MIFARE_EML_CARDLOAD = 0x0604, CMD_MIFARE_EML_CARDLOAD = 0x0604,
CMD_MIFARE_EML_CSETBLOCK = 0x0605,
--// magic chinese card commands CMD_MIFARE_EML_CGETBLOCK = 0x0606,
CMD_MIFARE_CSETBLOCK = 0x0605,
CMD_MIFARE_CGETBLOCK = 0x0606,
CMD_MIFARE_CIDENT = 0x0607,
CMD_SIMULATE_MIFARE_CARD = 0x0610, CMD_SIMULATE_MIFARE_CARD = 0x0610,
@ -116,42 +109,21 @@ local _commands = {
CMD_MIFARE_NESTED = 0x0612, CMD_MIFARE_NESTED = 0x0612,
CMD_MIFARE_READBL = 0x0620, CMD_MIFARE_READBL = 0x0620,
CMD_MIFAREU_READBL = 0x0720,
CMD_MIFARE_READSC = 0x0621, CMD_MIFARE_READSC = 0x0621,
CMD_MIFAREU_READCARD = 0x0721,
CMD_MIFARE_WRITEBL = 0x0622, CMD_MIFARE_WRITEBL = 0x0622,
CMD_MIFAREU_WRITEBL = 0x0722,
CMD_MIFAREU_WRITEBL_COMPAT = 0x0723,
CMD_MIFARE_CHKKEYS = 0x0623, CMD_MIFARE_CHKKEYS = 0x0623,
CMD_MIFARE_SNIFFER = 0x0630, CMD_MIFARE_SNIFFER = 0x0630,
--//ultralightC
CMD_MIFAREUC_AUTH1 = 0x0724,
CMD_MIFAREUC_AUTH2 = 0x0725,
CMD_MIFAREUC_READCARD = 0x0726,
--// mifare desfire
CMD_MIFARE_DESFIRE_READBL = 0x0728,
CMD_MIFARE_DESFIRE_WRITEBL = 0x0729,
CMD_MIFARE_DESFIRE_AUTH1 = 0x072a,
CMD_MIFARE_DESFIRE_AUTH2 = 0x072b,
CMD_MIFARE_DES_READER = 0x072c,
CMD_MIFARE_DESFIRE_INFO = 0x072d,
CMD_MIFARE_DESFIRE = 0x072e,
CMD_UNKNOWN = 0xFFFF, CMD_UNKNOWN = 0xFFFF,
} }
local _reverse_lookup,k,v = {} local _reverse_lookup,k,v = {}
for k, v in pairs(_commands) do for k, v in pairs(_commands) do
_reverse_lookup[v] = k _reverse_lookup[v] = k
end end
_commands.tostring = function(command) _commands.tostring = function(command)
if(type(command) == 'number') then if(type(command) == 'number') then
return ("%s (%d)"):format(_reverse_lookup[command]or "ERROR UNDEFINED!", command) return ("%s (%d)"):format(_reverse_lookup[command]or "ERROR UNDEFINED!", command)
end end
@ -213,6 +185,7 @@ function Command:getBytes()
local cmd = self.cmd local cmd = self.cmd
local arg1, arg2, arg3 = self.arg1, self.arg2, self.arg3 local arg1, arg2, arg3 = self.arg1, self.arg2, self.arg3
return bin.pack("LLLLH",cmd, arg1, arg2, arg3,data); return bin.pack("LLLLH",cmd, arg1, arg2, arg3,data);
end end
return _commands return _commands

View file

@ -1,63 +0,0 @@
local _names = {
--[[
--]]
["0400"]="BASH",
["1600"]="BOOMER" ,
["1800"]="CAMO",
["3000"]="CHOPCHOP" ,
["2000"]="CYNDER",
["6400"]="JET-VAC",
["6700"]="FLASHWING",
["7000"]="TREE REX",
["7100"]="LIGHTCORE SHROOMBOOM",
["1C00"]="DARK SPYRO",
["0600"]="DINORANG" ,
["1200"]="DOUBLE TROUBLE" ,
["1500"]="DRILLSERGEANT" ,
["1400"]="DROBOT",
["0900"]="LIGHTCORE ERUPTOR" ,
["0B00"]="FLAMESLINGER" ,
["1F00"]="GHOST ROASTER",
["0E00"]="GILL GRUNT" ,
["1D00"]="HEX",
["0A00"]="IGNITOR",
["0300"]="LIGHTNINGROD",
["0700"]="LIGHTCORE PRISM BREAK",
["1500"]="SLAMBAM",
["0100"]="SONIC BOOM",
["1000"]="SPYRO",
["1A00"]="STEALTH ELF",
["1B00"]="STUMP SMASH",
["0800"]="SUNBURN",
["0500"]="TERRAFIN",
["1300"]="TRIGGER HAPPY",
["1100"]="VOODOOD",
["0200"]="WARNADO",
["0D00"]="WHAM SHELL",
["0000"]="WHIRLWIND",
["1700"]="WRECKING BALL",
["0C00"]="ZAP",
["1900"]="ZOOK",
["0300"]="DRAGON",
["012D"]="ICE",
["012E"]="PIRATE",
["0130"]="PVPUNLOCK",
["012F"]="UNDEAD",
["0200"]="ANVIL" ,
["CB00"]="CROSSED SWORDS",
["CC00"]="HOURGLASS",
["CA00"]="REGENERATION",
["C900"]="SECRET STASH",
["CD00"]="SHIELD",
["CF00"]="SPARX",
["CE00"]="SPEED BOOTS",
["0194"]="LEGENDARY BASH",
["0430"]="LEGENDARY CHOPCHOP",
["01A0"]="LEGENDARY SPYRO",
["01A3"]="LEGENDARY TRIGGER HAPPY",
["0202"]="PET GILL GRUNT",
["020E"]="PET STEALTH ELF",
["01F9"]="PET TERRAFIN",
["0207"]="PET TRIGGER HAPPY",
}
return _names

View file

@ -47,18 +47,6 @@ local function save_HTML(javascript, filename)
end end
local function save_TEXT(data,filename)
-- Open the output file
local outfile = io.open(filename, "wb")
if outfile == nil then
return oops(string.format("Could not write to file %s",tostring(filename)))
end
outfile:write(data)
io.close(outfile)
return filename
end
local function save_BIN(data, filename) local function save_BIN(data, filename)
-- Open the output file -- Open the output file
@ -193,6 +181,4 @@ return {
convert_bin_to_html = convert_bin_to_html, convert_bin_to_html = convert_bin_to_html,
convert_eml_to_html = convert_eml_to_html, convert_eml_to_html = convert_eml_to_html,
convert_eml_to_bin = convert_eml_to_bin, convert_eml_to_bin = convert_eml_to_bin,
SaveAsBinary = save_BIN,
SaveAsText = save_TEXT,
} }

View file

@ -55,7 +55,6 @@ local skel_1 = [[
return "UNKNOWN" return "UNKNOWN"
} }
add("04,,,Mifare TNP3xxx Activision 1K,0f01,01");
add("04,,,Mifare Mini,0004,09"); add("04,,,Mifare Mini,0004,09");
add("04,,,Mifare Classic 1k/Mifare Plus(4 byte UID) 2K SL1,0004,08"); add("04,,,Mifare Classic 1k/Mifare Plus(4 byte UID) 2K SL1,0004,08");
add("04,,,Mifare Plus (4 byte UID) 2K SL2,0004,10"); add("04,,,Mifare Plus (4 byte UID) 2K SL2,0004,10");

View file

@ -1,384 +0,0 @@
local md5 = {
_VERSION = "md5.lua 0.5.0",
_DESCRIPTION = "MD5 computation in Lua (5.1)",
_URL = "https://github.com/kikito/md5.lua",
_LICENSE = [[
MIT LICENSE
Copyright (c) 2013 Enrique García Cota + Adam Baldwin + hanzao + Equi 4 Software
Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the
"Software"), to deal in the Software without restriction, including
without limitation the rights to use, copy, modify, merge, publish,
distribute, sublicense, and/or sell copies of the Software, and to
permit persons to whom the Software is furnished to do so, subject to
the following conditions:
The above copyright notice and this permission notice shall be included
in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
]]
}
-- bit lib implementions
local floor, abs, max = math.floor, math.abs, math.max
local char, byte, format, rep, sub =
string.char, string.byte, string.format, string.rep, string.sub
local function check_int(n)
-- checking not float
if(n - floor(n) > 0) then
error("trying to use bitwise operation on non-integer!")
end
end
local function tbl2number(tbl)
local n = #tbl
local rslt = 0
local power = 1
for i = 1, n do
rslt = rslt + tbl[i]*power
power = power*2
end
return rslt
end
local function expand(tbl_m, tbl_n)
local big = {}
local small = {}
if(#tbl_m > #tbl_n) then
big = tbl_m
small = tbl_n
else
big = tbl_n
small = tbl_m
end
-- expand small
for i = #small + 1, #big do
small[i] = 0
end
end
local to_bits -- needs to be declared before bit_not
local function bit_not(n)
local tbl = to_bits(n)
local size = max(#tbl, 32)
for i = 1, size do
if(tbl[i] == 1) then
tbl[i] = 0
else
tbl[i] = 1
end
end
return tbl2number(tbl)
end
-- defined as local above
to_bits = function (n)
check_int(n)
if(n < 0) then
-- negative
return to_bits(bit_not(abs(n)) + 1)
end
-- to bits table
local tbl = {}
local cnt = 1
while (n > 0) do
local last = math.fmod(n,2)
if(last == 1) then
tbl[cnt] = 1
else
tbl[cnt] = 0
end
n = (n-last)/2
cnt = cnt + 1
end
return tbl
end
local function bit_or(m, n)
local tbl_m = to_bits(m)
local tbl_n = to_bits(n)
expand(tbl_m, tbl_n)
local tbl = {}
local rslt = max(#tbl_m, #tbl_n)
for i = 1, rslt do
if(tbl_m[i]== 0 and tbl_n[i] == 0) then
tbl[i] = 0
else
tbl[i] = 1
end
end
return tbl2number(tbl)
end
local function bit_and(m, n)
local tbl_m = to_bits(m)
local tbl_n = to_bits(n)
expand(tbl_m, tbl_n)
local tbl = {}
local rslt = max(#tbl_m, #tbl_n)
for i = 1, rslt do
if(tbl_m[i]== 0 or tbl_n[i] == 0) then
tbl[i] = 0
else
tbl[i] = 1
end
end
return tbl2number(tbl)
end
local function bit_xor(m, n)
local tbl_m = to_bits(m)
local tbl_n = to_bits(n)
expand(tbl_m, tbl_n)
local tbl = {}
local rslt = max(#tbl_m, #tbl_n)
for i = 1, rslt do
if(tbl_m[i] ~= tbl_n[i]) then
tbl[i] = 1
else
tbl[i] = 0
end
end
return tbl2number(tbl)
end
local function bit_rshift(n, bits)
check_int(n)
local high_bit = 0
if(n < 0) then
-- negative
n = bit_not(abs(n)) + 1
high_bit = 2147483648 -- 0x80000000
end
for i=1, bits do
n = n/2
n = bit_or(floor(n), high_bit)
end
return floor(n)
end
local function bit_lshift(n, bits)
check_int(n)
if(n < 0) then
-- negative
n = bit_not(abs(n)) + 1
end
for i=1, bits do
n = n*2
end
return bit_and(n, 4294967295) -- 0xFFFFFFFF
end
-- convert little-endian 32-bit int to a 4-char string
local function lei2str(i)
local f=function (s) return char( bit_and( bit_rshift(i, s), 255)) end
return f(0)..f(8)..f(16)..f(24)
end
-- convert raw string to big-endian int
local function str2bei(s)
local v=0
for i=1, #s do
v = v * 256 + byte(s, i)
end
return v
end
-- convert raw string to little-endian int
local function str2lei(s)
local v=0
for i = #s,1,-1 do
v = v*256 + byte(s, i)
end
return v
end
-- cut up a string in little-endian ints of given size
local function cut_le_str(s,...)
local o, r = 1, {}
local args = {...}
for i=1, #args do
table.insert(r, str2lei(sub(s, o, o + args[i] - 1)))
o = o + args[i]
end
return r
end
local swap = function (w) return str2bei(lei2str(w)) end
local function hex2binaryaux(hexval)
return char(tonumber(hexval, 16))
end
local function hex2binary(hex)
local result, _ = hex:gsub('..', hex2binaryaux)
return result
end
-- An MD5 mplementation in Lua, requires bitlib (hacked to use LuaBit from above, ugh)
-- 10/02/2001 jcw@equi4.com
local FF = 0xffffffff
local CONSTS = {
0xd76aa478, 0xe8c7b756, 0x242070db, 0xc1bdceee,
0xf57c0faf, 0x4787c62a, 0xa8304613, 0xfd469501,
0x698098d8, 0x8b44f7af, 0xffff5bb1, 0x895cd7be,
0x6b901122, 0xfd987193, 0xa679438e, 0x49b40821,
0xf61e2562, 0xc040b340, 0x265e5a51, 0xe9b6c7aa,
0xd62f105d, 0x02441453, 0xd8a1e681, 0xe7d3fbc8,
0x21e1cde6, 0xc33707d6, 0xf4d50d87, 0x455a14ed,
0xa9e3e905, 0xfcefa3f8, 0x676f02d9, 0x8d2a4c8a,
0xfffa3942, 0x8771f681, 0x6d9d6122, 0xfde5380c,
0xa4beea44, 0x4bdecfa9, 0xf6bb4b60, 0xbebfbc70,
0x289b7ec6, 0xeaa127fa, 0xd4ef3085, 0x04881d05,
0xd9d4d039, 0xe6db99e5, 0x1fa27cf8, 0xc4ac5665,
0xf4292244, 0x432aff97, 0xab9423a7, 0xfc93a039,
0x655b59c3, 0x8f0ccc92, 0xffeff47d, 0x85845dd1,
0x6fa87e4f, 0xfe2ce6e0, 0xa3014314, 0x4e0811a1,
0xf7537e82, 0xbd3af235, 0x2ad7d2bb, 0xeb86d391,
0x67452301, 0xefcdab89, 0x98badcfe, 0x10325476
}
local f=function (x,y,z) return bit_or(bit_and(x,y),bit_and(-x-1,z)) end
local g=function (x,y,z) return bit_or(bit_and(x,z),bit_and(y,-z-1)) end
local h=function (x,y,z) return bit_xor(x,bit_xor(y,z)) end
local i=function (x,y,z) return bit_xor(y,bit_or(x,-z-1)) end
local z=function (f,a,b,c,d,x,s,ac)
a=bit_and(a+f(b,c,d)+x+ac,FF)
-- be *very* careful that left shift does not cause rounding!
return bit_or(bit_lshift(bit_and(a,bit_rshift(FF,s)),s),bit_rshift(a,32-s))+b
end
local function transform(A,B,C,D,X)
local a,b,c,d=A,B,C,D
local t=CONSTS
a=z(f,a,b,c,d,X[ 0], 7,t[ 1])
d=z(f,d,a,b,c,X[ 1],12,t[ 2])
c=z(f,c,d,a,b,X[ 2],17,t[ 3])
b=z(f,b,c,d,a,X[ 3],22,t[ 4])
a=z(f,a,b,c,d,X[ 4], 7,t[ 5])
d=z(f,d,a,b,c,X[ 5],12,t[ 6])
c=z(f,c,d,a,b,X[ 6],17,t[ 7])
b=z(f,b,c,d,a,X[ 7],22,t[ 8])
a=z(f,a,b,c,d,X[ 8], 7,t[ 9])
d=z(f,d,a,b,c,X[ 9],12,t[10])
c=z(f,c,d,a,b,X[10],17,t[11])
b=z(f,b,c,d,a,X[11],22,t[12])
a=z(f,a,b,c,d,X[12], 7,t[13])
d=z(f,d,a,b,c,X[13],12,t[14])
c=z(f,c,d,a,b,X[14],17,t[15])
b=z(f,b,c,d,a,X[15],22,t[16])
a=z(g,a,b,c,d,X[ 1], 5,t[17])
d=z(g,d,a,b,c,X[ 6], 9,t[18])
c=z(g,c,d,a,b,X[11],14,t[19])
b=z(g,b,c,d,a,X[ 0],20,t[20])
a=z(g,a,b,c,d,X[ 5], 5,t[21])
d=z(g,d,a,b,c,X[10], 9,t[22])
c=z(g,c,d,a,b,X[15],14,t[23])
b=z(g,b,c,d,a,X[ 4],20,t[24])
a=z(g,a,b,c,d,X[ 9], 5,t[25])
d=z(g,d,a,b,c,X[14], 9,t[26])
c=z(g,c,d,a,b,X[ 3],14,t[27])
b=z(g,b,c,d,a,X[ 8],20,t[28])
a=z(g,a,b,c,d,X[13], 5,t[29])
d=z(g,d,a,b,c,X[ 2], 9,t[30])
c=z(g,c,d,a,b,X[ 7],14,t[31])
b=z(g,b,c,d,a,X[12],20,t[32])
a=z(h,a,b,c,d,X[ 5], 4,t[33])
d=z(h,d,a,b,c,X[ 8],11,t[34])
c=z(h,c,d,a,b,X[11],16,t[35])
b=z(h,b,c,d,a,X[14],23,t[36])
a=z(h,a,b,c,d,X[ 1], 4,t[37])
d=z(h,d,a,b,c,X[ 4],11,t[38])
c=z(h,c,d,a,b,X[ 7],16,t[39])
b=z(h,b,c,d,a,X[10],23,t[40])
a=z(h,a,b,c,d,X[13], 4,t[41])
d=z(h,d,a,b,c,X[ 0],11,t[42])
c=z(h,c,d,a,b,X[ 3],16,t[43])
b=z(h,b,c,d,a,X[ 6],23,t[44])
a=z(h,a,b,c,d,X[ 9], 4,t[45])
d=z(h,d,a,b,c,X[12],11,t[46])
c=z(h,c,d,a,b,X[15],16,t[47])
b=z(h,b,c,d,a,X[ 2],23,t[48])
a=z(i,a,b,c,d,X[ 0], 6,t[49])
d=z(i,d,a,b,c,X[ 7],10,t[50])
c=z(i,c,d,a,b,X[14],15,t[51])
b=z(i,b,c,d,a,X[ 5],21,t[52])
a=z(i,a,b,c,d,X[12], 6,t[53])
d=z(i,d,a,b,c,X[ 3],10,t[54])
c=z(i,c,d,a,b,X[10],15,t[55])
b=z(i,b,c,d,a,X[ 1],21,t[56])
a=z(i,a,b,c,d,X[ 8], 6,t[57])
d=z(i,d,a,b,c,X[15],10,t[58])
c=z(i,c,d,a,b,X[ 6],15,t[59])
b=z(i,b,c,d,a,X[13],21,t[60])
a=z(i,a,b,c,d,X[ 4], 6,t[61])
d=z(i,d,a,b,c,X[11],10,t[62])
c=z(i,c,d,a,b,X[ 2],15,t[63])
b=z(i,b,c,d,a,X[ 9],21,t[64])
return A+a,B+b,C+c,D+d
end
----------------------------------------------------------------
function md5.sumhexa(s)
local msgLen = #s
local padLen = 56 - msgLen % 64
if msgLen % 64 > 56 then padLen = padLen + 64 end
if padLen == 0 then padLen = 64 end
s = s .. char(128) .. rep(char(0),padLen-1) .. lei2str(8*msgLen) .. lei2str(0)
assert(#s % 64 == 0)
local t = CONSTS
local a,b,c,d = t[65],t[66],t[67],t[68]
for i=1,#s,64 do
local X = cut_le_str(sub(s,i,i+63),4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4)
assert(#X == 16)
X[0] = table.remove(X,1) -- zero based!
a,b,c,d = transform(a,b,c,d,X)
end
return format("%08x%08x%08x%08x",swap(a),swap(b),swap(c),swap(d))
end
function md5.sum(s)
return hex2binary(md5.sumhexa(s))
end
return md5

View file

@ -141,25 +141,7 @@ local _keys = {
'200000000000', '200000000000',
'a00000000000', 'a00000000000',
'b00000000000', 'b00000000000',
}
--[[
Should be for Mifare TNP3xxx tags A KEY.
--]]
'4b0b20107ccb',
--[[
Kiev metro cards
--]]
'8fe644038790',
'f14ee7cae863',
'632193be1c3c',
'569369c5a0e5',
'9de89e070277',
'eff603e1efe9',
'644672bd4afe',
'b5ff67cba951',
}
--- ---
-- The keys above have just been pasted in, for completeness sake. They contain duplicates. -- The keys above have just been pasted in, for completeness sake. They contain duplicates.

View file

@ -25,7 +25,6 @@ local ISO14A_COMMAND = {
local ISO14443a_TYPES = {} local ISO14443a_TYPES = {}
ISO14443a_TYPES[0x00] = "NXP MIFARE Ultralight | Ultralight C" ISO14443a_TYPES[0x00] = "NXP MIFARE Ultralight | Ultralight C"
ISO14443a_TYPES[0x01] = "NXP MIFARE TNP3xxx Activision Game Appliance"
ISO14443a_TYPES[0x04] = "NXP MIFARE (various !DESFire !DESFire EV1)" ISO14443a_TYPES[0x04] = "NXP MIFARE (various !DESFire !DESFire EV1)"
ISO14443a_TYPES[0x08] = "NXP MIFARE CLASSIC 1k | Plus 2k" ISO14443a_TYPES[0x08] = "NXP MIFARE CLASSIC 1k | Plus 2k"
ISO14443a_TYPES[0x09] = "NXP MIFARE Mini 0.3k" ISO14443a_TYPES[0x09] = "NXP MIFARE Mini 0.3k"

View file

@ -33,86 +33,9 @@ local Utils =
return answer return answer
end, end,
------------ FILE READING
ReadDumpFile = function (filename)
if filename == nil then
return nil, 'Filename is empty'
end
if #filename == 0 then
return nil, 'Filename length is zero'
end
infile = io.open(filename, "rb")
if infile == nil then
return nil, string.format("Could not read file %s",filename)
end
local t = infile:read("*all")
len = string.len(t)
local _,hex = bin.unpack(("H%d"):format(len),t)
io.close(infile)
return hex
end,
------------ string split function
Split = function( inSplitPattern, outResults )
if not outResults then
outResults = {}
end
local start = 1
local splitStart, splitEnd = string.find( self, inSplitPattern, start )
while splitStart do
table.insert( outResults, string.sub( self, start, splitStart-1 ) )
start = splitEnd + 1
splitStart, splitEnd = string.find( self, inSplitPattern, start )
end
table.insert( outResults, string.sub( self, start ) )
return outResults
end,
------------ CRC-16 ccitt checksums
-- Takes a hex string and calculates a crc16
Crc16 = function(s)
if s == nil then return nil end
if #s == 0 then return nil end
if type(s) == 'string' then
local utils = require('utils')
local asc = utils.ConvertHexToAscii(s)
local hash = core.crc16(asc)
return hash
end
return nil
end,
-- input parameter is a string
-- Swaps the endianess and returns a number,
-- IE: 'cd7a' -> '7acd' -> 0x7acd
SwapEndianness = function(s, len)
if s == nil then return nil end
if #s == 0 then return '' end
if type(s) ~= 'string' then return nil end
local retval = 0
if len == 16 then
local t = s:sub(3,4)..s:sub(1,2)
retval = tonumber(t,16)
elseif len == 24 then
local t = s:sub(5,6)..s:sub(3,4)..s:sub(1,2)
retval = tonumber(t,16)
elseif len == 32 then
local t = s:sub(7,8)..s:sub(5,6)..s:sub(3,4)..s:sub(1,2)
retval = tonumber(t,16)
end
return retval
end,
------------ CONVERSIONS
-- --
-- Converts DECIMAL to HEX -- Converts DECIMAL to HEX
ConvertDecToHex = function(IN) ConvertDec2Hex = function(IN)
local B,K,OUT,I,D=16,"0123456789ABCDEF","",0 local B,K,OUT,I,D=16,"0123456789ABCDEF","",0
while IN>0 do while IN>0 do
I=I+1 I=I+1
@ -123,100 +46,12 @@ local Utils =
end, end,
--- ---
-- Convert Byte array to string of hex -- Convert Byte array to string of hex
ConvertBytesToHex = function(bytes) ConvertBytes2String = function(bytes)
if #bytes == 0 then s = {}
return ''
end
local s={}
for i = 1, #(bytes) do for i = 1, #(bytes) do
s[i] = string.format("%02X",bytes[i]) s[i] = string.format("%02X",bytes[i])
end end
return table.concat(s) return table.concat(s)
end, end,
-- Convert byte array to string with ascii
ConvertBytesToAscii = function(bytes)
if #bytes == 0 then
return ''
end
local s={}
for i = 1, #(bytes) do
s[i] = string.char(bytes[i])
end
return table.concat(s)
end,
ConvertHexToBytes = function(s)
local t={}
if s == nil then return t end
if #s == 0 then return t end
for k in s:gmatch"(%x%x)" do
table.insert(t,tonumber(k,16))
end
return t
end,
ConvertAsciiToBytes = function(s)
local t={}
if s == nil then return t end
if #s == 0 then return t end
for k in s:gmatch"(.)" do
table.insert(t, string.byte(k))
end
return t
end,
ConvertHexToAscii = function(s)
local t={}
if s == nil then return t end
if #s == 0 then return t end
for k in s:gmatch"(%x%x)" do
table.insert(t, string.char(tonumber(k,16)))
end
return table.concat(t)
end,
-- function convertStringToBytes(str)
-- local bytes = {}
-- local strLength = string.len(str)
-- for i=1,strLength do
-- table.insert(bytes, string.byte(str, i))
-- end
-- return bytes
-- end
-- function convertBytesToString(bytes)
-- local bytesLength = table.getn(bytes)
-- local str = ""
-- for i=1,bytesLength do
-- str = str .. string.char(bytes[i])
-- end
-- return str
-- end
-- function convertHexStringToBytes(str)
-- local bytes = {}
-- local strLength = string.len(str)
-- for k=2,strLength,2 do
-- local hexString = "0x" .. string.sub(str, (k - 1), k)
-- table.insert(bytes, hex.to_dec(hexString))
-- end
-- return bytes
-- end
-- function convertBytesToHexString(bytes)
-- local str = ""
-- local bytesLength = table.getn(bytes)
-- for i=1,bytesLength do
-- local hexString = string.sub(hex.to_hex(bytes[i]), 3)
-- if string.len(hexString) == 1 then
-- hexString = "0" .. hexString
-- end
-- str = str .. hexString
-- end
-- return str
-- end
} }
return Utils return Utils

View file

@ -216,7 +216,7 @@ int mfEmlGetMem(uint8_t *data, int blockNum, int blocksCount) {
UsbCommand c = {CMD_MIFARE_EML_MEMGET, {blockNum, blocksCount, 0}}; UsbCommand c = {CMD_MIFARE_EML_MEMGET, {blockNum, blocksCount, 0}};
SendCommand(&c); SendCommand(&c);
UsbCommand resp; UsbCommand resp;
if (!WaitForResponseTimeout(CMD_ACK,&resp,1500)) return 1; if (!WaitForResponseTimeout(CMD_ACK,&resp,1500)) return 1;
memcpy(data, resp.d.asBytes, blocksCount * 16); memcpy(data, resp.d.asBytes, blocksCount * 16);
return 0; return 0;
@ -250,7 +250,7 @@ int mfCSetBlock(uint8_t blockNo, uint8_t *data, uint8_t *uid, bool wantWipe, uin
memcpy(c.d.asBytes, data, 16); memcpy(c.d.asBytes, data, 16);
SendCommand(&c); SendCommand(&c);
UsbCommand resp; UsbCommand resp;
if (WaitForResponseTimeout(CMD_ACK,&resp,1500)) { if (WaitForResponseTimeout(CMD_ACK,&resp,1500)) {
isOK = resp.arg[0] & 0xff; isOK = resp.arg[0] & 0xff;
if (uid != NULL) memcpy(uid, resp.d.asBytes, 4); if (uid != NULL) memcpy(uid, resp.d.asBytes, 4);
@ -339,10 +339,10 @@ int loadTraceCard(uint8_t *tuid) {
while(!feof(f)){ while(!feof(f)){
memset(buf, 0, sizeof(buf)); memset(buf, 0, sizeof(buf));
if (fgets(buf, sizeof(buf), f) == NULL) { if (fgets(buf, sizeof(buf), f) == NULL) {
PrintAndLog("File reading error."); PrintAndLog("File reading error.");
fclose(f); fclose(f);
return 2; return 2;
} }
if (strlen(buf) < 32){ if (strlen(buf) < 32){
if (feof(f)) break; if (feof(f)) break;
@ -440,7 +440,7 @@ int mfTraceDecode(uint8_t *data_src, int len, bool wantSaveToEmlFile) {
} }
// AUTHENTICATION // AUTHENTICATION
if ((len == 4) && ((data[0] == 0x60) || (data[0] == 0x61))) { if ((len ==4) && ((data[0] == 0x60) || (data[0] == 0x61))) {
traceState = TRACE_AUTH1; traceState = TRACE_AUTH1;
traceCurBlock = data[1]; traceCurBlock = data[1];
traceCurKey = data[0] == 60 ? 1:0; traceCurKey = data[0] == 60 ? 1:0;

View file

@ -545,10 +545,11 @@ lfsr_common_prefix(uint32_t pfx, uint32_t rr, uint8_t ks[8], uint8_t par[8][8],
statelist = malloc((sizeof *statelist) << 21); //how large should be? statelist = malloc((sizeof *statelist) << 21); //how large should be?
if(!statelist || !odd || !even) if(!statelist || !odd || !even)
{ {
free(statelist); free(statelist);
free(odd); free(odd);
free(even); free(even);
return 0; return 0;
} }
s = statelist; s = statelist;

View file

@ -280,7 +280,7 @@ void ProxWidget::paintEvent(QPaintEvent *event)
ProxWidget::ProxWidget(QWidget *parent) : QWidget(parent), GraphStart(0), GraphPixelsPerPoint(1) ProxWidget::ProxWidget(QWidget *parent) : QWidget(parent), GraphStart(0), GraphPixelsPerPoint(1)
{ {
resize(600, 300); resize(600, 500);
QPalette palette(QColor(0,0,0,0)); QPalette palette(QColor(0,0,0,0));
palette.setColor(QPalette::WindowText, QColor(255,255,255)); palette.setColor(QPalette::WindowText, QColor(255,255,255));

View file

@ -47,7 +47,7 @@ void SendCommand(UsbCommand *c) {
PrintAndLog("Sending bytes to proxmark failed - offline"); PrintAndLog("Sending bytes to proxmark failed - offline");
return; return;
} }
/** /**
The while-loop below causes hangups at times, when the pm3 unit is unresponsive The while-loop below causes hangups at times, when the pm3 unit is unresponsive
or disconnected. The main console thread is alive, but comm thread just spins here. or disconnected. The main console thread is alive, but comm thread just spins here.
Not good.../holiman Not good.../holiman

View file

@ -20,7 +20,7 @@
#include "usb_cmd.h" #include "usb_cmd.h"
#define PROXPROMPT "pm3 --> " #define PROXPROMPT "proxmark3> "
void SendCommand(UsbCommand *c); void SendCommand(UsbCommand *c);

Some files were not shown because too many files have changed in this diff Show more