From: iceman1001 Date: Sat, 23 May 2015 06:16:40 +0000 (+0200) Subject: Merge branch 'master' of https://github.com/Proxmark/proxmark3 X-Git-Url: http://cvs.zerfleddert.de/cgi-bin/gitweb.cgi/proxmark3-svn/commitdiff_plain/bcf61bd34ab2747580aabf648093e5854b7283ed?ds=inline;hp=-c Merge branch 'master' of https://github.com/Proxmark/proxmark3 Conflicts: README.txt armsrc/appmain.c armsrc/apps.h armsrc/des.c armsrc/iclass.c armsrc/mifarecmd.c armsrc/mifareutil.c armsrc/mifareutil.h client/cmddata.c client/cmdhf.c client/cmdhf14a.c client/cmdhficlass.c client/cmdhfmfu.c client/cmdhfmfu.h client/cmdscript.c client/lualibs/commands.lua client/lualibs/html_dumplib.lua client/scripting.c client/util.c common/protocols.h include/usb_cmd.h --- bcf61bd34ab2747580aabf648093e5854b7283ed diff --combined README.txt index 05829dac,1a4ddb6d..e510e792 --- a/README.txt +++ b/README.txt @@@ -1,68 -1,87 +1,70 @@@ +The iceman fork. + NOTICE: -(2014-03-26) -This is now the official Proxmark repository! -INTRODUCTION: +The official Proxmark repository is found here: https://github.com/Proxmark/proxmark3 -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. -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. +NEWS: -RESOURCES: +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. +Among the stuff is - * This repository! - https://github.com/Proxmark/proxmark3 - - * The Wiki - https://github.com/Proxmark/proxmark3/wiki - - * The GitHub page - http://proxmark.github.io/proxmark3/ - - * The Forum - http://www.proxmark.org/forum - - * The IRC chanel - irc.freenode.org #proxmark3 - -or- - http://webchat.freenode.net/?channels=#proxmark3 - -DEVELOPMENT: + * Jonor's hf 14a raw timing patch + * Piwi's updates. (usually gets into the master) + * 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 tools required to build or run the project will vary depending on -your operating system. Please refer to the Wiki for details. +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. + +PM3 GUI: - * https://github.com/Proxmark/proxmark3/wiki +I do tend to rename and move stuff around, the official PM3-GUI from Gaucho will not work so well. *sorry* + + +DEVELOPMENT: -OBTAINING HARDWARE: +This fork is adjusted to compile on windows/mingw environment with Qt5.3.1 & GCC 4.8 +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. + +Common errors linux/macOS finds +Error: - * loclass/fileutils.c:15:2: warning: implicit declaration of function ‘_stat’ [-Wimplicit-function-declaration] ++ * 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: + * \client\makefile the parameter -lgdi32 +Solution: + * Remove parameter. + +Error: + * Using older Qt4.6 gives compilation errors. +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 + + CXXFLAGS = -I$(QTDIR)/include -I$(QTDIR)/include/QtCore -I$(QTDIR)/include/QtGui + QTLDLIBS = -L$(QTDIR)/lib -lQtCore4 -lQtGui4 + + +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. + The Proxmark 3 is available for purchase (assembled and tested) from the + following locations: - * http://proxmark3.com/ - * http://www.xfpga.com/ - -Most of the ultra-low-volume contract assemblers could put -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. - - -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 -May 2007, Cambridge MA +January 2015, Sweden +iceman at host iuse.se diff --combined armsrc/appmain.c index b19e079b,96644b9a..04503a4f --- a/armsrc/appmain.c +++ b/armsrc/appmain.c @@@ -10,19 -10,21 +10,19 @@@ // executes. //----------------------------------------------------------------------------- -#include "usb_cdc.h" -#include "cmd.h" - -#include "proxmark3.h" +#include "../common/usb_cdc.h" +#include "../common/cmd.h" +#include "../include/proxmark3.h" +#include "../include/hitag2.h" #include "apps.h" #include "util.h" #include "printf.h" #include "string.h" - #include - #include "legicrf.h" -#include #include "lfsampling.h" #include "BigBuf.h" + #ifdef WITH_LCD #include "LCD.h" #endif @@@ -178,7 -180,7 +178,7 @@@ void MeasureAntennaTuning(void int i, adcval = 0, peak = 0, peakv = 0, peakf = 0; //ptr = 0 int vLf125 = 0, vLf134 = 0, vHf = 0; // in mV - LED_B_ON(); + LED_B_ON(); /* * Sweeps the useful LF range of the proxmark from @@@ -210,7 -212,7 +210,7 @@@ 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. FpgaDownloadAndGo(FPGA_BITSTREAM_HF); FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_READER_RX_XCORR); @@@ -219,9 -221,9 +219,9 @@@ cmd_send(CMD_MEASURED_ANTENNA_TUNING, vLf125 | (vLf134<<16), vHf, peakf | (peakv<<16), LF_Results, 256); FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); - LED_A_OFF(); - LED_B_OFF(); - return; + LED_A_OFF(); + LED_B_OFF(); + return; } void MeasureAntennaTuningHf(void) @@@ -368,7 -370,7 +368,7 @@@ void SamyRun( for (;;) { usb_poll(); - WDT_HIT(); + WDT_HIT(); // Was our button held down or pressed? int button_pressed = BUTTON_HELD(1000); @@@ -638,7 -640,7 +638,7 @@@ void UsbPacketReceived(uint8_t *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) { #ifdef WITH_LF @@@ -736,7 -738,7 +736,7 @@@ ReaderHitag((hitag_function)c->arg[0],(hitag_data*)c->d.asBytes); break; #endif - + #ifdef WITH_ISO15693 case CMD_ACQUIRE_RAW_ADC_SAMPLES_ISO_15693: AcquireRawAdcSamplesIso15693(); @@@ -802,7 -804,7 +802,7 @@@ #ifdef WITH_ISO14443a case CMD_SNOOP_ISO_14443a: - SnoopIso14443a(c->arg[0]); + SniffIso14443a(c->arg[0]); break; case CMD_READER_ISO_14443a: ReaderIso14443a(c); @@@ -815,12 -817,8 +815,12 @@@ EPA_PACE_Collect_Nonce(c); break; + // case CMD_EPA_: + // EpaFoo(c); + // break; + case CMD_READER_MIFARE: - ReaderMifare(c->arg[0]); + ReaderMifare(c->arg[0]); break; case CMD_MIFARE_READBL: MifareReadBlock(c->arg[0], c->arg[1], c->arg[2], c->d.asBytes); @@@ -833,7 -831,7 +833,7 @@@ break; case CMD_MIFAREU_READCARD: MifareUReadCard(c->arg[0], c->arg[1], c->arg[2], c->d.asBytes); - break; + break; case CMD_MIFAREUC_SETPWD: MifareUSetPwd(c->arg[0], c->d.asBytes); break; @@@ -845,9 -843,9 +845,10 @@@ break; case CMD_MIFAREU_WRITEBL_COMPAT: MifareUWriteBlock(c->arg[0], c->d.asBytes); - break; + break; case CMD_MIFAREU_WRITEBL: + MifareUWriteBlock_Special(c->arg[0], c->d.asBytes); + MifareUWriteBlock_Special(c->arg[0], c->arg[1], c->d.asBytes); break; case CMD_MIFARE_NESTED: MifareNested(c->arg[0], c->arg[1], c->arg[2], c->d.asBytes); @@@ -892,28 -890,6 +893,28 @@@ SniffMifare(c->arg[0]); 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; + + case CMD_MIFARE_COLLECT_NONCES: + MifareCollectNonces(c->arg[0], c->arg[1]); + break; #endif #ifdef WITH_ICLASS @@@ -928,7 -904,7 +929,7 @@@ ReaderIClass(c->arg[0]); break; case CMD_READER_ICLASS_REPLAY: - ReaderIClass_Replay(c->arg[0], c->d.asBytes); + ReaderIClass_Replay(c->arg[0], c->d.asBytes); break; case CMD_ICLASS_EML_MEMSET: emlSet(c->d.asBytes,c->arg[0], c->arg[1]); @@@ -1061,7 -1037,7 +1062,7 @@@ void __attribute__((noreturn)) AppMain LED_A_OFF(); // Init USB device - usb_enable(); + usb_enable(); // The FPGA gets its clock from us from PCK0 output, so set that up. AT91C_BASE_PIOA->PIO_BSR = GPIO_PCK0; @@@ -1091,12 -1067,12 +1092,12 @@@ size_t rx_len; for(;;) { - if (usb_poll()) { - rx_len = usb_read(rx,sizeof(UsbCommand)); - if (rx_len) { - UsbPacketReceived(rx,rx_len); - } - } + if (usb_poll()) { + rx_len = usb_read(rx,sizeof(UsbCommand)); + if (rx_len) { + UsbPacketReceived(rx,rx_len); + } + } WDT_HIT(); #ifdef WITH_LF diff --combined armsrc/des.h index 880413e9,90f74246..3379463a --- a/armsrc/des.h +++ b/armsrc/des.h @@@ -96,10 -96,10 +96,13 @@@ void tdes_enc(void* out, const void* in * \param key pointer to the key (192 bit = 24 byte) */ void tdes_dec(void* out, const void* in, const void* key); + + void tdes_2key_enc(void* out, const void* in, size_t length, const void* key, unsigned char iv[8]); + void tdes_2key_dec(void* out, const void* in, size_t length, const void* key, unsigned char iv[8]); + void tdes_2key_enc(void* out, const void* in, size_t length, const void* key, unsigned char iv[8]); + void tdes_2key_dec(void* out, const void* in, size_t length, const void* key, unsigned char iv[8]); + #endif /*DES_H_*/ // Copied from des.h in desfire imp. diff --combined armsrc/iso14443a.c index c6628c07,64bbcbf5..e1943b26 --- a/armsrc/iso14443a.c +++ b/armsrc/iso14443a.c @@@ -15,6 -15,7 +15,6 @@@ #include "util.h" #include "string.h" #include "cmd.h" - #include "iso14443crc.h" #include "iso14443a.h" #include "crapto1.h" @@@ -212,12 -213,6 +212,12 @@@ void AppendCrc14443a(uint8_t* data, in ComputeCrc14443(CRC_14443_A,data,len,data+len,data+len+1); } +void AppendCrc14443b(uint8_t* data, int len) +{ + ComputeCrc14443(CRC_14443_B,data,len,data+len,data+len+1); +} + + //============================================================================= // ISO 14443 Type A - Miller decoder //============================================================================= @@@ -237,17 -232,13 +237,17 @@@ static tUart Uart; // Lookup-Table to decide if 4 raw bits are a modulation. -// We accept two or three consecutive "0" in any position with the rest "1" +// We accept the following: +// 0001 - a 3 tick wide pause +// 0011 - a 2 tick wide pause, or a three tick wide pause shifted left +// 0111 - a 2 tick wide pause shifted left +// 1001 - a 2 tick wide pause shifted right const bool Mod_Miller_LUT[] = { - TRUE, TRUE, FALSE, TRUE, FALSE, FALSE, FALSE, FALSE, - TRUE, TRUE, FALSE, FALSE, TRUE, FALSE, FALSE, FALSE + FALSE, TRUE, FALSE, TRUE, FALSE, FALSE, FALSE, TRUE, + FALSE, TRUE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE }; -#define IsMillerModulationNibble1(b) (Mod_Miller_LUT[(b & 0x00F0) >> 4]) -#define IsMillerModulationNibble2(b) (Mod_Miller_LUT[(b & 0x000F)]) +#define IsMillerModulationNibble1(b) (Mod_Miller_LUT[(b & 0x000000F0) >> 4]) +#define IsMillerModulationNibble2(b) (Mod_Miller_LUT[(b & 0x0000000F)]) void UartReset() { @@@ -257,19 -248,16 +257,19 @@@ Uart.parityLen = 0; // number of decoded parity bytes Uart.shiftReg = 0; // shiftreg to hold decoded data bits Uart.parityBits = 0; // holds 8 parity bits - Uart.twoBits = 0x0000; // buffer for 2 Bits - Uart.highCnt = 0; Uart.startTime = 0; Uart.endTime = 0; + + Uart.byteCntMax = 0; + Uart.posCnt = 0; + Uart.syncBit = 9999; } void UartInit(uint8_t *data, uint8_t *parity) { Uart.output = data; Uart.parity = parity; + Uart.fourBits = 0x00000000; // clear the buffer for 4 Bits UartReset(); } @@@ -277,44 -265,40 +277,44 @@@ static RAMFUNC bool MillerDecoding(uint8_t bit, uint32_t non_real_time) { - Uart.twoBits = (Uart.twoBits << 8) | bit; + Uart.fourBits = (Uart.fourBits << 8) | bit; if (Uart.state == STATE_UNSYNCD) { // not yet synced - if (Uart.highCnt < 2) { // wait for a stable unmodulated signal - if (Uart.twoBits == 0xffff) { - Uart.highCnt++; - } else { - Uart.highCnt = 0; - } - } else { - Uart.syncBit = 0xFFFF; // not set - // we look for a ...1111111100x11111xxxxxx pattern (the start bit) - if ((Uart.twoBits & 0xDF00) == 0x1F00) Uart.syncBit = 8; // mask is 11x11111 xxxxxxxx, - // check for 00x11111 xxxxxxxx - else if ((Uart.twoBits & 0xEF80) == 0x8F80) Uart.syncBit = 7; // both masks shifted right one bit, left padded with '1' - else if ((Uart.twoBits & 0xF7C0) == 0xC7C0) Uart.syncBit = 6; // ... - else if ((Uart.twoBits & 0xFBE0) == 0xE3E0) Uart.syncBit = 5; - else if ((Uart.twoBits & 0xFDF0) == 0xF1F0) Uart.syncBit = 4; - else if ((Uart.twoBits & 0xFEF8) == 0xF8F8) Uart.syncBit = 3; - else if ((Uart.twoBits & 0xFF7C) == 0xFC7C) Uart.syncBit = 2; - else if ((Uart.twoBits & 0xFFBE) == 0xFE3E) Uart.syncBit = 1; - if (Uart.syncBit != 0xFFFF) { // found a sync bit + Uart.syncBit = 9999; // not set + + // 00x11111 2|3 ticks pause followed by 6|5 ticks unmodulated Sequence Z (a "0" or "start of communication") + // 11111111 8 ticks unmodulation Sequence Y (a "0" or "end of communication" or "no information") + // 111100x1 4 ticks unmodulated followed by 2|3 ticks pause Sequence X (a "1") + + // The start bit is one ore more Sequence Y followed by a Sequence Z (... 11111111 00x11111). We need to distinguish from + // Sequence X followed by Sequence Y followed by Sequence Z (111100x1 11111111 00x11111) + // we therefore look for a ...xx1111 11111111 00x11111xxxxxx... pattern + // (12 '1's followed by 2 '0's, eventually followed by another '0', followed by 5 '1's) + // +#define ISO14443A_STARTBIT_MASK 0x07FFEF80 // mask is 00001111 11111111 1110 1111 10000000 +#define ISO14443A_STARTBIT_PATTERN 0x07FF8F80 // pattern is 00001111 11111111 1000 1111 10000000 + + if ((Uart.fourBits & (ISO14443A_STARTBIT_MASK >> 0)) == ISO14443A_STARTBIT_PATTERN >> 0) Uart.syncBit = 7; + else if ((Uart.fourBits & (ISO14443A_STARTBIT_MASK >> 1)) == ISO14443A_STARTBIT_PATTERN >> 1) Uart.syncBit = 6; + else if ((Uart.fourBits & (ISO14443A_STARTBIT_MASK >> 2)) == ISO14443A_STARTBIT_PATTERN >> 2) Uart.syncBit = 5; + else if ((Uart.fourBits & (ISO14443A_STARTBIT_MASK >> 3)) == ISO14443A_STARTBIT_PATTERN >> 3) Uart.syncBit = 4; + else if ((Uart.fourBits & (ISO14443A_STARTBIT_MASK >> 4)) == ISO14443A_STARTBIT_PATTERN >> 4) Uart.syncBit = 3; + else if ((Uart.fourBits & (ISO14443A_STARTBIT_MASK >> 5)) == ISO14443A_STARTBIT_PATTERN >> 5) Uart.syncBit = 2; + else if ((Uart.fourBits & (ISO14443A_STARTBIT_MASK >> 6)) == ISO14443A_STARTBIT_PATTERN >> 6) Uart.syncBit = 1; + else if ((Uart.fourBits & (ISO14443A_STARTBIT_MASK >> 7)) == ISO14443A_STARTBIT_PATTERN >> 7) Uart.syncBit = 0; + + if (Uart.syncBit != 9999) { // found a sync bit Uart.startTime = non_real_time?non_real_time:(GetCountSspClk() & 0xfffffff8); Uart.startTime -= Uart.syncBit; Uart.endTime = Uart.startTime; Uart.state = STATE_START_OF_COMMUNICATION; } - } } else { - if (IsMillerModulationNibble1(Uart.twoBits >> Uart.syncBit)) { - if (IsMillerModulationNibble2(Uart.twoBits >> Uart.syncBit)) { // Modulation in both halves - error + if (IsMillerModulationNibble1(Uart.fourBits >> Uart.syncBit)) { + if (IsMillerModulationNibble2(Uart.fourBits >> Uart.syncBit)) { // Modulation in both halves - error UartReset(); } else { // Modulation in first half = Sequence Z = logic "0" if (Uart.state == STATE_MILLER_X) { // error - must not follow after X @@@ -338,7 -322,7 +338,7 @@@ } } } else { - if (IsMillerModulationNibble2(Uart.twoBits >> Uart.syncBit)) { // Modulation second half = Sequence X = logic "1" + if (IsMillerModulationNibble2(Uart.fourBits >> Uart.syncBit)) { // Modulation second half = Sequence X = logic "1" Uart.bitCount++; Uart.shiftReg = (Uart.shiftReg >> 1) | 0x100; // add a 1 to the shiftreg Uart.state = STATE_MILLER_X; @@@ -374,10 -358,12 +374,10 @@@ return TRUE; // we are finished with decoding the raw data sequence } else { UartReset(); // Nothing received - start over - Uart.highCnt = 1; } } if (Uart.state == STATE_START_OF_COMMUNICATION) { // error - must not follow directly after SOC UartReset(); - Uart.highCnt = 1; } else { // a logic "0" Uart.bitCount++; Uart.shiftReg = (Uart.shiftReg >> 1); // add a 0 to the shiftreg @@@ -444,11 -430,6 +444,11 @@@ void DemodReset( Demod.highCnt = 0; Demod.startTime = 0; Demod.endTime = 0; + + // + Demod.bitCount = 0; + Demod.syncBit = 0xFFFF; + Demod.samples = 0; } void DemodInit(uint8_t *data, uint8_t *parity) @@@ -547,7 -528,9 +547,7 @@@ static RAMFUNC int ManchesterDecoding(u } } } - } - return FALSE; // not finished yet, need more data } @@@ -561,7 -544,7 +561,7 @@@ // triggering so that we start recording at the point that the tag is moved // near the reader. //----------------------------------------------------------------------------- -void RAMFUNC SnoopIso14443a(uint8_t param) { +void RAMFUNC SniffIso14443a(uint8_t param) { // param: // bit 0 - trigger from first card answer // bit 1 - trigger from first reader 7-bit request @@@ -697,9 -680,6 +697,9 @@@ // And ready to receive another response. DemodReset(); + // And reset the Miller decoder including itS (now outdated) input buffer + UartInit(receivedCmd, receivedCmdPar); + LED_C_OFF(); } TagIsActive = (Demod.state != DEMOD_UNSYNCD); @@@ -935,15 -915,8 +935,15 @@@ bool prepare_allocated_tag_modulation(t // Main loop of simulated tag: receive commands from reader, decide what // response to send, and send it. //----------------------------------------------------------------------------- -void SimulateIso14443aTag(int tagType, int uid_1st, int uid_2nd, byte_t* data) +void SimulateIso14443aTag(int tagType, int flags, int uid_2nd, byte_t* data) { + + //Here, we collect UID,NT,AR,NR,UID2,NT2,AR2,NR2 + // This can be used in a reader-only attack. + // (it can also be retrieved via 'hf 14a list', but hey... + uint32_t ar_nr_responses[] = {0,0,0,0,0,0,0,0,0,0}; + uint8_t ar_nr_collected = 0; + uint8_t sak; // The first response contains the ATQA (note: bytes are transmitted in reverse order). @@@ -979,13 -952,7 +979,13 @@@ response1[0] = 0x01; response1[1] = 0x0f; sak = 0x01; - } break; + } break; + case 6: { // MIFARE Mini + // Says: I am a Mifare Mini, 320b + response1[0] = 0x44; + response1[1] = 0x00; + sak = 0x09; + } break; default: { Dbprintf("Error: unkown tagtype (%d)",tagType); return; @@@ -998,24 -965,17 +998,24 @@@ // Check if the uid uses the (optional) part uint8_t response2a[5] = {0x00}; - if (uid_2nd) { + if (flags & FLAG_7B_UID_IN_DATA) { response2[0] = 0x88; - num_to_bytes(uid_1st,3,response2+1); - num_to_bytes(uid_2nd,4,response2a); + response2[1] = data[0]; + response2[2] = data[1]; + response2[3] = data[2]; + + response2a[0] = data[3]; + response2a[1] = data[4]; + response2a[2] = data[5]; + response2a[3] = data[7]; response2a[4] = response2a[0] ^ response2a[1] ^ response2a[2] ^ response2a[3]; // Configure the ATQA and SAK accordingly response1[0] |= 0x40; sak |= 0x04; } else { - num_to_bytes(uid_1st,4,response2); + memcpy(response2, data, 4); + //num_to_bytes(uid_1st,4,response2); // Configure the ATQA and SAK accordingly response1[0] &= 0xBF; sak &= 0xFB; @@@ -1149,46 -1109,9 +1149,46 @@@ if (tracing) { LogTrace(receivedCmd, Uart.len, Uart.startTime*16 - DELAY_AIR2ARM_AS_TAG, Uart.endTime*16 - DELAY_AIR2ARM_AS_TAG, Uart.parity, TRUE); } + uint32_t nonce = bytes_to_num(response5,4); uint32_t nr = bytes_to_num(receivedCmd,4); uint32_t ar = bytes_to_num(receivedCmd+4,4); - Dbprintf("Auth attempt {nr}{ar}: %08x %08x",nr,ar); + //Dbprintf("Auth attempt {nonce}{nr}{ar}: %08x %08x %08x", nonce, nr, ar); + + if(flags & FLAG_NR_AR_ATTACK ) + { + if(ar_nr_collected < 2){ + // Avoid duplicates... probably not necessary, nr should vary. + //if(ar_nr_responses[3] != nr){ + ar_nr_responses[ar_nr_collected*5] = 0; + ar_nr_responses[ar_nr_collected*5+1] = 0; + ar_nr_responses[ar_nr_collected*5+2] = nonce; + ar_nr_responses[ar_nr_collected*5+3] = nr; + ar_nr_responses[ar_nr_collected*5+4] = ar; + ar_nr_collected++; + //} + } + + if(ar_nr_collected > 1 ) { + + if (MF_DBGLEVEL >= 2) { + Dbprintf("Collected two pairs of AR/NR which can be used to extract keys from reader:"); + Dbprintf("../tools/mfkey/mfkey32 %07x%08x %08x %08x %08x %08x %08x", + ar_nr_responses[0], // UID1 + ar_nr_responses[1], // UID2 + ar_nr_responses[2], // NT + ar_nr_responses[3], // AR1 + ar_nr_responses[4], // NR1 + ar_nr_responses[8], // AR2 + ar_nr_responses[9] // NR2 + ); + } + uint8_t len = ar_nr_collected*5*4; + cmd_send(CMD_ACK,CMD_SIMULATE_MIFARE_CARD,len,0,&ar_nr_responses,len); + ar_nr_collected = 0; + memset(ar_nr_responses, 0x00, len); + Dbprintf("ICE"); + } + } } else { // Check for ISO 14443A-4 compliant commands, look at left nibble switch (receivedCmd[0]) { @@@ -1292,8 -1215,6 +1292,8 @@@ } } + FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); + Dbprintf("%x %x %x", happened, happened2, cmdsRecvd); LED_A_OFF(); BigBuf_free_keep_EM(); @@@ -1416,7 -1337,7 +1416,7 @@@ void CodeIso14443aBitsAsReaderPar(cons } // Only transmit parity bit if we transmitted a complete byte - if (j == 8) { + if (j == 8 && parity != NULL) { // Get the parity bit if (parity[i>>3] & (0x80 >> (i&0x0007))) { // Sequence X @@@ -1680,7 -1601,7 +1680,7 @@@ bool EmLogTrace(uint8_t *reader_data, u //----------------------------------------------------------------------------- static int GetIso14443aAnswerFromTag(uint8_t *receivedResponse, uint8_t *receivedResponsePar, uint16_t offset) { - uint32_t c; + uint32_t c = 0x00; // Set FPGA mode to "reader listen mode", no modulation (listen // only, since we are receiving, not transmitting). @@@ -1694,6 -1615,7 +1694,6 @@@ // clear RXRDY: uint8_t b = (uint8_t)AT91C_BASE_SSC->SSC_RHR; - c = 0; for(;;) { WDT_HIT(); @@@ -1709,7 -1631,6 +1709,7 @@@ } } + void ReaderTransmitBitsPar(uint8_t* frame, uint16_t bits, uint8_t *par, uint32_t *timing) { CodeIso14443aBitsAsReaderPar(frame, bits, par); @@@ -1725,13 -1646,11 +1725,13 @@@ } } + void ReaderTransmitPar(uint8_t* frame, uint16_t len, uint8_t *par, uint32_t *timing) { ReaderTransmitBitsPar(frame, len*8, par, timing); } + void ReaderTransmitBits(uint8_t* frame, uint16_t len, uint32_t *timing) { // Generate parity and redirect @@@ -1740,7 -1659,6 +1740,7 @@@ ReaderTransmitBitsPar(frame, len, par, timing); } + void ReaderTransmit(uint8_t* frame, uint16_t len, uint32_t *timing) { // Generate parity and redirect @@@ -1801,11 -1719,6 +1801,11 @@@ int iso14443a_select_card(byte_t *uid_p memset(uid_ptr,0,10); } + // check for proprietary anticollision: + if ((resp[0] & 0x1F) == 0) { + return 3; + } + // 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 // While the UID is not complete, the 3nd bit (from the right) is set in the SAK. @@@ -1938,7 -1851,7 +1938,7 @@@ void iso14443a_setup(uint8_t fpga_minor DemodReset(); UartReset(); NextTransferTime = 2*DELAY_ARM2AIR_AS_READER; - iso14a_set_timeout(1050); // 10ms default + iso14a_set_timeout(10*106); // 10ms default } int iso14_apdu(uint8_t *cmd, uint16_t cmd_len, void *data) { @@@ -2014,38 -1927,15 +2014,38 @@@ void ReaderIso14443a(UsbCommand *c if(param & ISO14A_RAW) { if(param & ISO14A_APPEND_CRC) { - AppendCrc14443a(cmd,len); + if(param & ISO14A_TOPAZMODE) { + AppendCrc14443b(cmd,len); + } else { + AppendCrc14443a(cmd,len); + } len += 2; if (lenbits) lenbits += 16; } - if(lenbits>0) { + if(lenbits>0) { // want to send a specific number of bits (e.g. short commands) + if(param & ISO14A_TOPAZMODE) { + int bits_to_send = lenbits; + uint16_t i = 0; + ReaderTransmitBitsPar(&cmd[i++], MIN(bits_to_send, 7), NULL, NULL); // first byte is always short (7bits) and no parity + bits_to_send -= 7; + while (bits_to_send > 0) { + ReaderTransmitBitsPar(&cmd[i++], MIN(bits_to_send, 8), NULL, NULL); // following bytes are 8 bit and no parity + bits_to_send -= 8; + } + } else { GetParity(cmd, lenbits/8, par); - ReaderTransmitBitsPar(cmd, lenbits, par, NULL); + ReaderTransmitBitsPar(cmd, lenbits, par, NULL); // bytes are 8 bit with odd parity + } + } else { // want to send complete bytes only + if(param & ISO14A_TOPAZMODE) { + uint16_t i = 0; + ReaderTransmitBitsPar(&cmd[i++], 7, NULL, NULL); // first byte: 7 bits, no paritiy + while (i < len) { + ReaderTransmitBitsPar(&cmd[i++], 8, NULL, NULL); // following bytes: 8 bits, no paritiy + } } else { - ReaderTransmit(cmd,len, NULL); + ReaderTransmit(cmd,len, NULL); // 8 bits, odd parity + } } arg0 = ReaderReceive(buf, par); cmd_send(CMD_ACK,arg0,0,0,buf,sizeof(buf)); @@@ -2069,11 -1959,13 +2069,11 @@@ // Therefore try in alternating directions. int32_t dist_nt(uint32_t nt1, uint32_t nt2) { - uint16_t i; - uint32_t nttmp1, nttmp2; - if (nt1 == nt2) return 0; - nttmp1 = nt1; - nttmp2 = nt2; + uint16_t i; + uint32_t nttmp1 = nt1; + uint32_t nttmp2 = nt2; for (i = 1; i < 32768; i++) { nttmp1 = prng_successor(nttmp1, 1); @@@ -2092,27 -1984,28 +2092,27 @@@ // Cloning MiFare Classic Rail and Building Passes, Anywhere, Anytime" // (article by Nicolas T. Courtois, 2009) //----------------------------------------------------------------------------- -void ReaderMifare(bool first_try) -{ - // Mifare AUTH - uint8_t mf_auth[] = { 0x60,0x00,0xf5,0x7b }; - uint8_t mf_nr_ar[] = { 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 }; - static uint8_t mf_nr_ar3; - - uint8_t receivedAnswer[MAX_MIFARE_FRAME_SIZE]; - uint8_t receivedAnswerPar[MAX_MIFARE_PARITY_SIZE]; - +void ReaderMifare(bool first_try) { // free eventually allocated BigBuf memory. We want all for tracing. BigBuf_free(); clear_trace(); set_tracing(TRUE); + // Mifare AUTH + uint8_t mf_auth[] = { 0x60,0x00,0xf5,0x7b }; + uint8_t mf_nr_ar[8] = { 0x00 }; //{ 0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01 }; + static uint8_t mf_nr_ar3 = 0; + + uint8_t receivedAnswer[MAX_MIFARE_FRAME_SIZE] = { 0x00 }; + uint8_t receivedAnswerPar[MAX_MIFARE_PARITY_SIZE] = { 0x00 }; + byte_t nt_diff = 0; uint8_t par[1] = {0}; // maximum 8 Bytes to be sent here, 1 byte parity is therefore enough static byte_t par_low = 0; bool led_on = TRUE; - uint8_t uid[10] ={0}; - uint32_t cuid; + uint8_t uid[10] = {0x00}; + //uint32_t cuid = 0x00; uint32_t nt = 0; uint32_t previous_nt = 0; @@@ -2120,15 -2013,13 +2120,15 @@@ byte_t par_list[8] = {0x00}; byte_t ks_list[8] = {0x00}; - static uint32_t sync_time; - static uint32_t sync_cycles; + static uint32_t sync_time = 0; + static uint32_t sync_cycles = 0; int catch_up_cycles = 0; int last_catch_up = 0; uint16_t consecutive_resyncs = 0; int isOK = 0; + int numWrongDistance = 0; + if (first_try) { mf_nr_ar3 = 0; iso14443a_setup(FPGA_HF_ISO14443A_READER_MOD); @@@ -2148,22 -2039,20 +2148,22 @@@ LED_A_ON(); LED_B_OFF(); LED_C_OFF(); - + LED_C_ON(); for(uint16_t i = 0; TRUE; i++) { WDT_HIT(); // Test if the action was cancelled - if(BUTTON_PRESS()) { + if(BUTTON_PRESS()) break; + + if (numWrongDistance > 1000) { + isOK = 0; break; } - LED_C_ON(); - - if(!iso14443a_select_card(uid, NULL, &cuid)) { + //if(!iso14443a_select_card(uid, NULL, &cuid)) { + if(!iso14443a_select_card(uid, NULL, NULL)) { if (MF_DBGLEVEL >= 1) Dbprintf("Mifare: Can't select card"); continue; } @@@ -2197,14 -2086,9 +2197,14 @@@ nt_attacked = nt; } else { - if (nt_distance == -99999) { // invalid nonce received, try again + + // invalid nonce received, try again + if (nt_distance == -99999) { + numWrongDistance++; + if (MF_DBGLEVEL >= 3) Dbprintf("The two nonces has invalid distance, tag could have good PRNG\n"); continue; } + sync_cycles = (sync_cycles - nt_distance); if (MF_DBGLEVEL >= 3) Dbprintf("calibrating in cycle %d. nt_distance=%d, Sync_cycles: %d\n", i, nt_distance, sync_cycles); continue; @@@ -2213,7 -2097,7 +2213,7 @@@ if ((nt != nt_attacked) && nt_attacked) { // we somehow lost sync. Try to catch up again... catch_up_cycles = -dist_nt(nt_attacked, nt); - if (catch_up_cycles == 99999) { // invalid nonce received. Don't resync on that one. + if (catch_up_cycles >= 99999) { // invalid nonce received. Don't resync on that one. catch_up_cycles = 0; continue; } @@@ -2271,10 -2155,10 +2271,10 @@@ } } - mf_nr_ar[3] &= 0x1F; - byte_t buf[28]; + byte_t buf[28] = {0x00}; + memcpy(buf + 0, uid, 4); num_to_bytes(nt, 4, buf + 4); memcpy(buf + 8, par_list, 8); @@@ -2283,13 -2167,14 +2283,13 @@@ cmd_send(CMD_ACK,isOK,0,0,buf,28); - // Thats it... + set_tracing(FALSE); FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); LEDsoff(); - - set_tracing(FALSE); } -/** + + /* *MIFARE 1K simulate. * *@param flags : @@@ -2490,7 -2375,7 +2490,7 @@@ void Mifare1ksim(uint8_t flags, uint8_ uint32_t nr = bytes_to_num(&receivedCmd[4], 4); //Collect AR/NR - if(ar_nr_collected < 2){ + if(ar_nr_collected < 2 && cardAUTHSC == 2){ if(ar_nr_responses[2] != ar) {// Avoid duplicates... probably not necessary, ar should vary. ar_nr_responses[ar_nr_collected*4] = cuid; @@@ -2498,12 -2383,7 +2498,12 @@@ ar_nr_responses[ar_nr_collected*4+2] = ar; ar_nr_responses[ar_nr_collected*4+3] = nr; ar_nr_collected++; - } + } + // Interactive mode flag, means we need to send ACK + if(flags & FLAG_INTERACTIVE && ar_nr_collected == 2) + { + finished = true; + } } // --- crypto @@@ -2650,7 -2530,7 +2650,7 @@@ mf_crypto1_encrypt(pcs, response, 18, response_par); EmSendCmdPar(response, 18, response_par); numReads++; - if(exitAfterNReads > 0 && numReads == exitAfterNReads) { + if(exitAfterNReads > 0 && numReads >= exitAfterNReads) { Dbprintf("%d reads done, exiting", numReads); finished = true; } @@@ -2770,29 -2650,29 +2770,29 @@@ if(flags & FLAG_INTERACTIVE)// Interactive mode flag, means we need to send ACK { //May just aswell send the collected ar_nr in the response aswell - cmd_send(CMD_ACK,CMD_SIMULATE_MIFARE_CARD,0,0,&ar_nr_responses,ar_nr_collected*4*4); + cmd_send(CMD_ACK,CMD_SIMULATE_MIFARE_CARD,1,0,&ar_nr_responses,ar_nr_collected*4*4); } - if(flags & FLAG_NR_AR_ATTACK) + if(flags & FLAG_NR_AR_ATTACK && MF_DBGLEVEL >= 1 ) { - if(ar_nr_collected > 1) { + if(ar_nr_collected > 1 ) { Dbprintf("Collected two pairs of AR/NR which can be used to extract keys from reader:"); Dbprintf("../tools/mfkey/mfkey32 %08x %08x %08x %08x %08x %08x", ar_nr_responses[0], // UID - ar_nr_responses[1], //NT - ar_nr_responses[2], //AR1 - ar_nr_responses[3], //NR1 - ar_nr_responses[6], //AR2 - ar_nr_responses[7] //NR2 + ar_nr_responses[1], // NT + ar_nr_responses[2], // AR1 + ar_nr_responses[3], // NR1 + ar_nr_responses[6], // AR2 + ar_nr_responses[7] // NR2 ); } else { Dbprintf("Failed to obtain two AR/NR pairs!"); - if(ar_nr_collected >0) { + if(ar_nr_collected > 0 ) { Dbprintf("Only got these: UID=%08x, nonce=%08x, AR1=%08x, NR1=%08x", ar_nr_responses[0], // UID - ar_nr_responses[1], //NT - ar_nr_responses[2], //AR1 - ar_nr_responses[3] //NR1 + ar_nr_responses[1], // NT + ar_nr_responses[2], // AR1 + ar_nr_responses[3] // NR1 ); } } @@@ -2802,6 -2682,7 +2802,6 @@@ } - //----------------------------------------------------------------------------- // MIFARE sniffer. // @@@ -2811,9 -2692,6 +2811,9 @@@ void RAMFUNC SniffMifare(uint8_t param // bit 0 - trigger from first card answer // bit 1 - trigger from first reader 7-bit request + // free eventually allocated BigBuf memory + BigBuf_free(); + // C(red) A(yellow) B(green) LEDsoff(); // init trace buffer @@@ -2829,6 -2707,12 +2829,6 @@@ uint8_t receivedResponse[MAX_MIFARE_FRAME_SIZE]; uint8_t receivedResponsePar[MAX_MIFARE_PARITY_SIZE]; - // As we receive stuff, we copy it from receivedCmd or receivedResponse - // into trace, along with its length and other annotations. - //uint8_t *trace = (uint8_t *)BigBuf; - - // free eventually allocated BigBuf memory - BigBuf_free(); // allocate the DMA buffer, used to stream samples from the FPGA uint8_t *dmaBuf = BigBuf_malloc(DMA_BUFFER_SIZE); uint8_t *data = dmaBuf; @@@ -2919,7 -2803,7 +2919,7 @@@ if (MfSniffLogic(receivedCmd, Uart.len, Uart.parity, Uart.bitCount, TRUE)) break; /* And ready to receive another command. */ - UartReset(); + UartInit(receivedCmd, receivedCmdPar); /* And also reset the demod code */ DemodReset(); @@@ -2936,9 -2820,6 +2936,9 @@@ // And ready to receive another response. DemodReset(); + + // And reset the Miller decoder including its (now outdated) input buffer + UartInit(receivedCmd, receivedCmdPar); } TagIsActive = (Demod.state != DEMOD_UNSYNCD); } @@@ -2960,4 -2841,4 +2960,4 @@@ Dbprintf("maxDataLen=%x, Uart.state=%x, Uart.len=%x", maxDataLen, Uart.state, Uart.len); LEDsoff(); - } + } diff --combined armsrc/lfops.c index 5b0b4904,c3fa8a0e..b9890ceb --- a/armsrc/lfops.c +++ b/armsrc/lfops.c @@@ -379,7 -379,7 +379,7 @@@ void WriteTItag(uint32_t idhi, uint32_ AcquireTiType(); FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); - DbpString("Now use tiread to check"); + DbpString("Now use 'lf ti read' to check"); } void SimulateTagLowFrequency(int period, int gap, int ledcontrol) @@@ -651,7 -651,7 +651,7 @@@ void CmdASKsimTag(uint16_t arg1, uint16 int ledcontrol = 1; int n=0, i=0; uint8_t clk = (arg1 >> 8) & 0xFF; - uint8_t encoding = arg1 & 1; + uint8_t encoding = arg1 & 0xFF; uint8_t separator = arg2 & 1; uint8_t invert = (arg2 >> 8) & 1; @@@ -756,7 -756,7 +756,7 @@@ void CmdHIDdemodFSK(int findone, int *h { uint8_t *dest = BigBuf_get_addr(); //const size_t sizeOfBigBuff = BigBuf_max_traceLen(); - size_t size; + size_t size = 0; uint32_t hi2=0, hi=0, lo=0; int idx=0; // Configure to go in 125Khz listen mode @@@ -866,24 -866,24 +866,24 @@@ void CmdEM410xdemod(int findone, int *h if (errCnt<0) continue; - errCnt = Em410xDecode(dest, &size, &idx, &hi, &lo); - if (errCnt){ - if (size>64){ - Dbprintf("EM XL TAG ID: %06x%08x%08x - (%05d_%03d_%08d)", - hi, - (uint32_t)(lo>>32), - (uint32_t)lo, - (uint32_t)(lo&0xFFFF), - (uint32_t)((lo>>16LL) & 0xFF), - (uint32_t)(lo & 0xFFFFFF)); - } else { - Dbprintf("EM TAG ID: %02x%08x - (%05d_%03d_%08d)", - (uint32_t)(lo>>32), - (uint32_t)lo, - (uint32_t)(lo&0xFFFF), - (uint32_t)((lo>>16LL) & 0xFF), - (uint32_t)(lo & 0xFFFFFF)); - } + errCnt = Em410xDecode(dest, &size, &idx, &hi, &lo); + if (errCnt){ + if (size>64){ + Dbprintf("EM XL TAG ID: %06x%08x%08x - (%05d_%03d_%08d)", + hi, + (uint32_t)(lo>>32), + (uint32_t)lo, + (uint32_t)(lo&0xFFFF), + (uint32_t)((lo>>16LL) & 0xFF), + (uint32_t)(lo & 0xFFFFFF)); + } else { + Dbprintf("EM TAG ID: %02x%08x - (%05d_%03d_%08d)", + (uint32_t)(lo>>32), + (uint32_t)lo, + (uint32_t)(lo&0xFFFF), + (uint32_t)((lo>>16LL) & 0xFF), + (uint32_t)(lo & 0xFFFFFF)); + } if (findone){ if (ledcontrol) LED_A_OFF(); @@@ -908,8 -908,6 +908,8 @@@ void CmdIOdemodFSK(int findone, int *hi uint8_t version=0; uint8_t facilitycode=0; uint16_t number=0; + uint8_t crc = 0; + uint16_t calccrc = 0; // Configure to go in 125Khz listen mode LFSetupFPGAForADC(95, true); @@@ -921,62 -919,45 +921,62 @@@ WDT_HIT(); idx = IOdemodFSK(dest, BigBuf_max_traceLen()); if (idx<0) continue; - //valid tag found - - //Index map - //0 10 20 30 40 50 60 - //| | | | | | | - //01234567 8 90123456 7 89012345 6 78901234 5 67890123 4 56789012 3 45678901 23 - //----------------------------------------------------------------------------- - //00000000 0 11110000 1 facility 1 version* 1 code*one 1 code*two 1 ???????? 11 - // - //XSF(version)facility:codeone+codetwo - //Handle the data - if(findone){ //only print binary if we are doing one - Dbprintf("%d%d%d%d%d%d%d%d %d",dest[idx], dest[idx+1], dest[idx+2],dest[idx+3],dest[idx+4],dest[idx+5],dest[idx+6],dest[idx+7],dest[idx+8]); - Dbprintf("%d%d%d%d%d%d%d%d %d",dest[idx+9], dest[idx+10],dest[idx+11],dest[idx+12],dest[idx+13],dest[idx+14],dest[idx+15],dest[idx+16],dest[idx+17]); - Dbprintf("%d%d%d%d%d%d%d%d %d",dest[idx+18],dest[idx+19],dest[idx+20],dest[idx+21],dest[idx+22],dest[idx+23],dest[idx+24],dest[idx+25],dest[idx+26]); - Dbprintf("%d%d%d%d%d%d%d%d %d",dest[idx+27],dest[idx+28],dest[idx+29],dest[idx+30],dest[idx+31],dest[idx+32],dest[idx+33],dest[idx+34],dest[idx+35]); - Dbprintf("%d%d%d%d%d%d%d%d %d",dest[idx+36],dest[idx+37],dest[idx+38],dest[idx+39],dest[idx+40],dest[idx+41],dest[idx+42],dest[idx+43],dest[idx+44]); - Dbprintf("%d%d%d%d%d%d%d%d %d",dest[idx+45],dest[idx+46],dest[idx+47],dest[idx+48],dest[idx+49],dest[idx+50],dest[idx+51],dest[idx+52],dest[idx+53]); - Dbprintf("%d%d%d%d%d%d%d%d %d%d",dest[idx+54],dest[idx+55],dest[idx+56],dest[idx+57],dest[idx+58],dest[idx+59],dest[idx+60],dest[idx+61],dest[idx+62],dest[idx+63]); - } - code = bytebits_to_byte(dest+idx,32); - code2 = bytebits_to_byte(dest+idx+32,32); - version = bytebits_to_byte(dest+idx+27,8); //14,4 + //valid tag found + + //Index map + //0 10 20 30 40 50 60 + //| | | | | | | + //01234567 8 90123456 7 89012345 6 78901234 5 67890123 4 56789012 3 45678901 23 + //----------------------------------------------------------------------------- + //00000000 0 11110000 1 facility 1 version* 1 code*one 1 code*two 1 checksum 11 + // + //Checksum: + //00000000 0 11110000 1 11100000 1 00000001 1 00000011 1 10110110 1 01110101 11 + //preamble F0 E0 01 03 B6 75 + // How to calc checksum, + // http://www.proxmark.org/forum/viewtopic.php?id=364&p=6 + // F0 + E0 + 01 + 03 + B6 = 28A + // 28A & FF = 8A + // FF - 8A = 75 + // Checksum: 0x75 + //XSF(version)facility:codeone+codetwo + //Handle the data + if(findone){ //only print binary if we are doing one + Dbprintf("%d%d%d%d%d%d%d%d %d",dest[idx], dest[idx+1], dest[idx+2],dest[idx+3],dest[idx+4],dest[idx+5],dest[idx+6],dest[idx+7],dest[idx+8]); + Dbprintf("%d%d%d%d%d%d%d%d %d",dest[idx+9], dest[idx+10],dest[idx+11],dest[idx+12],dest[idx+13],dest[idx+14],dest[idx+15],dest[idx+16],dest[idx+17]); + Dbprintf("%d%d%d%d%d%d%d%d %d",dest[idx+18],dest[idx+19],dest[idx+20],dest[idx+21],dest[idx+22],dest[idx+23],dest[idx+24],dest[idx+25],dest[idx+26]); + Dbprintf("%d%d%d%d%d%d%d%d %d",dest[idx+27],dest[idx+28],dest[idx+29],dest[idx+30],dest[idx+31],dest[idx+32],dest[idx+33],dest[idx+34],dest[idx+35]); + Dbprintf("%d%d%d%d%d%d%d%d %d",dest[idx+36],dest[idx+37],dest[idx+38],dest[idx+39],dest[idx+40],dest[idx+41],dest[idx+42],dest[idx+43],dest[idx+44]); + Dbprintf("%d%d%d%d%d%d%d%d %d",dest[idx+45],dest[idx+46],dest[idx+47],dest[idx+48],dest[idx+49],dest[idx+50],dest[idx+51],dest[idx+52],dest[idx+53]); + Dbprintf("%d%d%d%d%d%d%d%d %d%d",dest[idx+54],dest[idx+55],dest[idx+56],dest[idx+57],dest[idx+58],dest[idx+59],dest[idx+60],dest[idx+61],dest[idx+62],dest[idx+63]); + } + code = bytebits_to_byte(dest+idx,32); + code2 = bytebits_to_byte(dest+idx+32,32); + version = bytebits_to_byte(dest+idx+27,8); //14,4 facilitycode = bytebits_to_byte(dest+idx+18,8); - number = (bytebits_to_byte(dest+idx+36,8)<<8)|(bytebits_to_byte(dest+idx+45,8)); //36,9 - - Dbprintf("XSF(%02d)%02x:%05d (%08x%08x)",version,facilitycode,number,code,code2); - // if we're only looking for one tag - if (findone){ - if (ledcontrol) LED_A_OFF(); - //LED_A_OFF(); - *high=code; - *low=code2; - return; - } - code=code2=0; - version=facilitycode=0; - number=0; - idx=0; + number = (bytebits_to_byte(dest+idx+36,8)<<8)|(bytebits_to_byte(dest+idx+45,8)); //36,9 + + crc = bytebits_to_byte(dest+idx+54,8); + for (uint8_t i=1; i<6; ++i) + calccrc += bytebits_to_byte(dest+idx+9*i,8); + calccrc &= 0xff; + calccrc = 0xff - calccrc; + + char *crcStr = (crc == calccrc) ? "ok":"!crc"; + + Dbprintf("IO Prox XSF(%02d)%02x:%05d (%08x%08x) [%02x %s]",version,facilitycode,number,code,code2, crc, crcStr); + // if we're only looking for one tag + if (findone){ + if (ledcontrol) LED_A_OFF(); + //LED_A_OFF(); + *high=code; + *low=code2; + return; + } + code=code2=0; + version=facilitycode=0; + number=0; + idx=0; WDT_HIT(); } @@@ -1044,23 -1025,9 +1044,23 @@@ * and enlarge the gap ones. */ #define START_GAP 50*8 // 10 - 50fc 250 -#define WRITE_GAP 20*8 // - 30fc 160 -#define WRITE_0 24*8 // 16 - 63fc 54fc 144 -#define WRITE_1 54*8 // 48 - 63fc 54fc 432 for T55x7; 448 for E5550 //400 +#define WRITE_GAP 20*8 // 8 - 30fc +#define WRITE_0 24*8 // 16 - 31fc 24fc 192 +#define WRITE_1 54*8 // 48 - 63fc 54fc 432 for T55x7; 448 for E5550 + +// VALUES TAKEN FROM EM4x function: SendForward +// START_GAP = 440; (55*8) cycles at 125Khz (8us = 1cycle) +// WRITE_GAP = 128; (16*8) +// WRITE_1 = 256 32*8; (32*8) + +// These timings work for 4469/4269/4305 (with the 55*8 above) +// WRITE_0 = 23*8 , 9*8 SpinDelayUs(23*8); + +// Sam7s has several timers, we will use the source TIMER_CLOCK1 (aka AT91C_TC_CLKS_TIMER_DIV1_CLOCK) +// TIMER_CLOCK1 = MCK/2, MCK is running at 48 MHz, Timer is running at 48/2 = 24 MHz +// Hitag units (T0) have duration of 8 microseconds (us), which is 1/125000 per second (carrier) +// T0 = TIMER_CLOCK1 / 125000 = 192 +// 1 Cycle = 8 microseconds(us) #define T55xx_SAMPLES_SIZE 12000 // 32 x 32 x 10 (32 bit times numofblock (7), times clock skip..) @@@ -1070,7 -1037,7 +1070,7 @@@ void T55xxWriteBit(int bit FpgaDownloadAndGo(FPGA_BITSTREAM_LF); FpgaSendCommand(FPGA_CMD_SET_DIVISOR, 95); //125Khz FpgaWriteConfWord(FPGA_MAJOR_MODE_LF_ADC | FPGA_LF_ADC_READER_FIELD); - if (bit == 0) + if (!bit) SpinDelayUs(WRITE_0); else SpinDelayUs(WRITE_1); @@@ -1524,16 -1491,10 +1524,16 @@@ void CopyIndala224toT55x7(int uid1, in #define max(x,y) ( x 18000 ) + GraphTraceLen = 18000; + + int i, j, lastval, bitidx, half_switch; int clock = 64; int tolerance = clock / 8; @@@ -1544,7 -1505,8 +1544,7 @@@ uint8_t dir; LFSetupFPGAForADC(95, true); - DoAcquisition_default(0, 0); - + DoAcquisition_default(0, true); lmin = 64; lmax = 192; @@@ -1552,9 -1514,9 +1552,9 @@@ i = 2; /* Find first local max/min */ - if(GraphBuffer[1] > GraphBuffer[0]) { + if(dest[1] > dest[0]) { while(i < GraphTraceLen) { - if( !(GraphBuffer[i] > GraphBuffer[i-1]) && GraphBuffer[i] > lmax) + if( !(dest[i] > dest[i-1]) && dest[i] > lmax) break; i++; } @@@ -1562,7 -1524,7 +1562,7 @@@ } else { while(i < GraphTraceLen) { - if( !(GraphBuffer[i] < GraphBuffer[i-1]) && GraphBuffer[i] < lmin) + if( !(dest[i] < dest[i-1]) && dest[i] < lmin) break; i++; } @@@ -1576,7 -1538,7 +1576,7 @@@ for (bitidx = 0; i < GraphTraceLen; i++) { - if ( (GraphBuffer[i-1] > GraphBuffer[i] && dir == 1 && GraphBuffer[i] > lmax) || (GraphBuffer[i-1] < GraphBuffer[i] && dir == 0 && GraphBuffer[i] < lmin)) + if ( (dest[i-1] > dest[i] && dir == 1 && dest[i] > lmax) || (dest[i-1] < dest[i] && dir == 0 && dest[i] < lmin)) { lc = i - lastval; lastval = i; @@@ -1605,14 -1567,14 +1605,14 @@@ block_done = 1; } else if(half_switch == 1) { - BitStream[bitidx++] = 0; + bits[bitidx++] = 0; half_switch = 0; } else half_switch++; } else if (abs(lc-clock) < tolerance) { // 64TO - BitStream[bitidx++] = 1; + bits[bitidx++] = 1; } else { // Error warnings++; @@@ -1626,15 -1588,14 +1626,15 @@@ if(block_done == 1) { if(bitidx == 128) { for(j=0; j<16; j++) { - Blocks[num_blocks][j] = 128*BitStream[j*8+7]+ - 64*BitStream[j*8+6]+ - 32*BitStream[j*8+5]+ - 16*BitStream[j*8+4]+ - 8*BitStream[j*8+3]+ - 4*BitStream[j*8+2]+ - 2*BitStream[j*8+1]+ - BitStream[j*8]; + blocks[num_blocks][j] = 128*bits[j*8+7]+ + 64*bits[j*8+6]+ + 32*bits[j*8+5]+ + 16*bits[j*8+4]+ + 8*bits[j*8+3]+ + 4*bits[j*8+2]+ + 2*bits[j*8+1]+ + bits[j*8]; + } num_blocks++; } @@@ -1643,14 -1604,17 +1643,14 @@@ half_switch = 0; } if(i < GraphTraceLen) - { - if (GraphBuffer[i-1] > GraphBuffer[i]) dir=0; - else dir = 1; - } + dir =(dest[i-1] > dest[i]) ? 0 : 1; } if(bitidx==255) bitidx=0; warnings = 0; if(num_blocks == 4) break; } - memcpy(outBlocks, Blocks, 16*num_blocks); + memcpy(outBlocks, blocks, 16*num_blocks); return num_blocks; } @@@ -1948,14 -1912,9 +1948,14 @@@ void EM4xLogin(uint32_t Password) void EM4xReadWord(uint8_t Address, uint32_t Pwd, uint8_t PwdMode) { - uint8_t fwd_bit_count; uint8_t *dest = BigBuf_get_addr(); - int m=0, i=0; + uint16_t bufferlength = BigBuf_max_traceLen(); + uint32_t i = 0; + + // Clear destination buffer before sending the command 0x80 = average. + memset(dest, 0x80, bufferlength); + + uint8_t fwd_bit_count; //If password mode do login if (PwdMode == 1) EM4xLogin(Pwd); @@@ -1964,6 -1923,9 +1964,6 @@@ fwd_bit_count = Prepare_Cmd( FWD_CMD_READ ); fwd_bit_count += Prepare_Addr( Address ); - m = BigBuf_max_traceLen(); - // Clear destination buffer before sending the command - memset(dest, 128, m); // Connect the A/D to the peak-detected low-frequency path. SetAdcMuxFor(GPIO_MUXSEL_LOPKD); // Now set up the SSC to get the ADC samples that are now streaming at us. @@@ -1979,12 -1941,10 +1979,12 @@@ } if (AT91C_BASE_SSC->SSC_SR & AT91C_SSC_RXRDY) { dest[i] = (uint8_t)AT91C_BASE_SSC->SSC_RHR; - i++; - if (i >= m) break; + ++i; + if (i >= bufferlength) break; } } + + cmd_send(CMD_ACK,0,0,0,0,0); FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); // field off LED_D_OFF(); } diff --combined armsrc/mifarecmd.c index 03e15b3b,0586a25d..c56f2337 --- a/armsrc/mifarecmd.c +++ b/armsrc/mifarecmd.c @@@ -19,6 -19,12 +19,12 @@@ #include "crc.h" + // 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}; + + //----------------------------------------------------------------------------- // Select, Authenticate, Read a MIFARE tag. // read block @@@ -86,7 -92,6 +92,6 @@@ void MifareReadBlock(uint8_t arg0, uint LEDsoff(); } - void MifareUC_Auth(uint8_t arg0, uint8_t *keybytes){ bool turnOffField = (arg0 == 1); @@@ -106,17 -111,17 +111,19 @@@ OnError(1); return; } - + if (turnOffField) { FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); LEDsoff(); + } + cmd_send(CMD_ACK,1,0,0,0,0); + } + cmd_send(CMD_ACK,1,0,0,0,0); } // Arg0 = BlockNo, // Arg1 = UsePwd bool - // datain = PWD bytes, + // datain = PWD bytes, void MifareUReadBlock(uint8_t arg0, uint8_t arg1, uint8_t *datain) { uint8_t blockNo = arg0; @@@ -124,53 -129,53 +131,53 @@@ bool useKey = (arg1 == 1); //UL_C bool usePwd = (arg1 == 2); //UL_EV1/NTAG - LEDsoff(); - LED_A_ON(); + LEDsoff(); + LED_A_ON(); clear_trace(); iso14443a_setup(FPGA_HF_ISO14443A_READER_LISTEN); - + int len = iso14443a_select_card(NULL, NULL, NULL); if(!len) { if (MF_DBGLEVEL >= MF_DBG_ERROR) Dbprintf("Can't select card (RC:%02X)",len); OnError(1); return; } - + // UL-C authentication if ( useKey ) { - uint8_t key[16] = {0x00}; + uint8_t key[16] = {0x00}; memcpy(key, datain, sizeof(key) ); if ( !mifare_ultra_auth(key) ) { OnError(1); - return; + return; } } - + // UL-EV1 / NTAG authentication - if (usePwd) { + if ( usePwd ) { uint8_t pwd[4] = {0x00}; memcpy(pwd, datain, 4); uint8_t pack[4] = {0,0,0,0}; if (!mifare_ul_ev1_auth(pwd, pack)) { OnError(1); - return; + return; } - } - + } + if( mifare_ultra_readblock(blockNo, dataout) ) { if (MF_DBGLEVEL >= MF_DBG_ERROR) Dbprintf("Read block error"); OnError(2); return; } - + if( mifare_ultra_halt() ) { if (MF_DBGLEVEL >= MF_DBG_ERROR) Dbprintf("Halt error"); OnError(3); return; } - + - cmd_send(CMD_ACK,1,0,0,dataout,16); + cmd_send(CMD_ACK,1,0,0,dataout,16); FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); LEDsoff(); } @@@ -210,7 -215,7 +217,7 @@@ void MifareReadSector(uint8_t arg0, uin isOK = 0; if (MF_DBGLEVEL >= 1) Dbprintf("Can't select card"); } - + if(isOK && mifare_classic_auth(pcs, cuid, FirstBlockOfSector(sectorNo), keyType, ui64Key, AUTH_FIRST)) { isOK = 0; @@@ -243,10 -248,6 +250,10 @@@ LEDsoff(); } +// arg0 = blockNo (start) +// arg1 = Pages (number of blocks) +// arg2 = useKey +// datain = KEY bytes void MifareUReadCard(uint8_t arg0, uint16_t arg1, uint8_t arg2, uint8_t *datain) { // free eventually allocated BigBuf memory @@@ -268,7 -269,7 +275,7 @@@ } LEDsoff(); - LED_A_ON(); + LED_A_ON(); iso14443a_setup(FPGA_HF_ISO14443A_READER_LISTEN); int len = iso14443a_select_card(NULL, NULL, NULL); @@@ -277,44 -278,44 +284,73 @@@ OnError(1); return; } + + // UL-C authentication + if ( useKey ) { + uint8_t key[16] = {0x00}; + memcpy(key, datain, sizeof(key) ); + + if ( !mifare_ultra_auth(key) ) { + OnError(1); + return; + } + } + + // UL-EV1 / NTAG authentication + if (usePwd) { + uint8_t pwd[4] = {0x00}; + memcpy(pwd, datain, sizeof(pwd)); + uint8_t pack[4] = {0,0,0,0}; + + if (!mifare_ul_ev1_auth(pwd, pack)){ + OnError(1); + return; + } + } + + for (int i = 0; i < blocks; i++){ + if ((i*4) + 4 > CARD_MEMORY_SIZE) { + Dbprintf("Data exceeds buffer!!"); + break; + } - len = mifare_ultra_readblock(blockNo + i, dataout + 4 * i); + // UL-C authentication + if ( useKey ) { + uint8_t key[16] = {0x00}; + memcpy(key, datain, sizeof(key) ); + + if ( !mifare_ultra_auth(key) ) { + OnError(1); + return; + } + } + + // UL-EV1 / NTAG authentication + if (usePwd) { + uint8_t pwd[4] = {0x00}; + memcpy(pwd, datain, sizeof(pwd)); + uint8_t pack[4] = {0,0,0,0}; + if (!mifare_ul_ev1_auth(pwd, pack)){ + OnError(1); + return; + } + } + + for (int i = 0; i < blocks; i++){ + if ((i*4) + 4 > CARD_MEMORY_SIZE) { + Dbprintf("Data exceeds buffer!!"); + break; + } + + len = mifare_ultra_readblock(blockNo + i, dataout + 4 * i); + if (len) { if (MF_DBGLEVEL >= MF_DBG_ERROR) Dbprintf("Read block %d error",i); // if no blocks read - error out if (i==0){ - OnError(2); + OnError(2); - return; + return; } else { //stop at last successful read block and return what we got break; @@@ -323,14 -324,14 +359,14 @@@ countblocks++; } } - + len = mifare_ultra_halt(); if (len) { if (MF_DBGLEVEL >= MF_DBG_ERROR) Dbprintf("Halt error"); OnError(3); return; } - + if (MF_DBGLEVEL >= MF_DBG_EXTENDED) Dbprintf("Blocks read %d", countblocks); countblocks *= 4; @@@ -413,15 -414,15 +449,15 @@@ void MifareWriteBlock(uint8_t arg0, uin void MifareUWriteBlock(uint8_t arg0, uint8_t *datain) { - uint8_t blockNo = arg0; + uint8_t blockNo = arg0; byte_t blockdata[16] = {0x00}; - memcpy(blockdata, datain, 16); - + memcpy(blockdata, datain, 16); + uint8_t uid[10] = {0x00}; LED_A_ON(); LED_B_OFF(); LED_C_OFF(); - + clear_trace(); iso14443a_setup(FPGA_HF_ISO14443A_READER_LISTEN); @@@ -441,7 -442,7 +477,7 @@@ OnError(0); return; }; - + if (MF_DBGLEVEL >= 2) DbpString("WRITE BLOCK FINISHED"); cmd_send(CMD_ACK,1,0,0,0,0); @@@ -449,20 -450,12 +485,20 @@@ LEDsoff(); } -void MifareUWriteBlock_Special(uint8_t arg0, uint8_t *datain) +// Arg0 : Block to write to. +// Arg1 : 0 = use no authentication. +// 1 = use 0x1A authentication. +// 2 = use 0x1B authentication. +// datain : 4 first bytes is data to be written. +// : 4/16 next bytes is authentication key. +void MifareUWriteBlock_Special(uint8_t arg0, uint8_t arg1, uint8_t *datain) { uint8_t blockNo = arg0; + bool useKey = (arg1 == 1); //UL_C + bool usePwd = (arg1 == 2); //UL_EV1/NTAG byte_t blockdata[4] = {0x00}; - - memcpy(blockdata, datain, 4); + + memcpy(blockdata, datain,4); LEDsoff(); LED_A_ON(); @@@ -475,28 -468,6 +511,28 @@@ return; }; + // UL-C authentication + if ( useKey ) { + uint8_t key[16] = {0x00}; + memcpy(key, datain+4, sizeof(key) ); + + if ( !mifare_ultra_auth(key) ) { + OnError(1); + return; + } + } + + // UL-EV1 / NTAG authentication + if (usePwd) { + uint8_t pwd[4] = {0x00}; + memcpy(pwd, datain+4, 4); + uint8_t pack[4] = {0,0,0,0}; + if (!mifare_ul_ev1_auth(pwd, pack)) { + OnError(1); + return; + } + } + if(mifare_ultra_special_writeblock(blockNo, blockdata)) { if (MF_DBGLEVEL >= 1) Dbprintf("Write block error"); OnError(0); @@@ -1034,12 -1005,12 +1070,12 @@@ void MifareCSetBlock(uint32_t arg0, uin if (workFlags & 0x01) { if(!iso14443a_select_card(uid, NULL, &cuid)) { if (MF_DBGLEVEL >= 1) Dbprintf("Can't select card"); - break; + //break; }; if(mifare_classic_halt(NULL, cuid)) { if (MF_DBGLEVEL >= 1) Dbprintf("Halt error"); - break; + //break; }; }; @@@ -1218,74 -1189,7 +1254,74 @@@ void MifareCIdent() cmd_send(CMD_ACK,isOK,0,0,0,0); } - // +void MifareCollectNonces(uint32_t arg0, uint32_t arg1){ + + BigBuf_free(); + + uint32_t iterations = arg0; + uint8_t uid[10] = {0x00}; + + uint8_t *response = BigBuf_malloc(MAX_MIFARE_FRAME_SIZE); + uint8_t *responsePar = BigBuf_malloc(MAX_MIFARE_PARITY_SIZE); + + uint8_t mf_auth[] = { 0x60,0x00,0xf5,0x7b }; + + // get memory from BigBuf. + uint8_t *nonces = BigBuf_malloc(iterations * 4); + + LED_A_ON(); + LED_B_OFF(); + LED_C_OFF(); + + clear_trace(); + set_tracing(TRUE); + iso14443a_setup(FPGA_HF_ISO14443A_READER_LISTEN); + + for (int i = 0; i < iterations; i++) { + + WDT_HIT(); + + // Test if the action was cancelled + if(BUTTON_PRESS()) break; + + // if(mifare_classic_halt(pcs, cuid)) { + // if (MF_DBGLEVEL >= 1) Dbprintf("Halt error"); + //} + + if(!iso14443a_select_card(uid, NULL, NULL)) { + if (MF_DBGLEVEL >= 1) Dbprintf("Can't select card"); + continue; + }; + + // Transmit MIFARE_CLASSIC_AUTH. + ReaderTransmit(mf_auth, sizeof(mf_auth), NULL); + + // Receive the (4 Byte) "random" nonce + if (!ReaderReceive(response, responsePar)) { + if (MF_DBGLEVEL >= 1) Dbprintf("Couldn't receive tag nonce"); + continue; + } + + nonces[i*4] = bytes_to_num(response, 4); + } + + int packLen = iterations * 4; + int packSize = 0; + int packNum = 0; + while (packLen > 0) { + packSize = MIN(USB_CMD_DATA_SIZE, packLen); + LED_B_ON(); + cmd_send(CMD_ACK, 77, 0, packSize, nonces - packLen, packSize); + LED_B_OFF(); + + packLen -= packSize; + packNum++; + } + FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); + LEDsoff(); +} + +// // DESFIRE // @@@ -1293,7 -1197,7 +1329,7 @@@ void Mifare_DES_Auth1(uint8_t arg0, uin byte_t dataout[11] = {0x00}; uint8_t uid[10] = {0x00}; - uint32_t cuid; + uint32_t cuid = 0x00; clear_trace(); iso14443a_setup(FPGA_HF_ISO14443A_READER_LISTEN); @@@ -1319,22 -1223,39 +1355,37 @@@ void Mifare_DES_Auth2(uint32_t arg0, ui uint32_t cuid = arg0; uint8_t key[16] = {0x00}; - byte_t isOK = 0; byte_t dataout[12] = {0x00}; + byte_t isOK = 0; memcpy(key, datain, 16); isOK = mifare_desfire_des_auth2(cuid, key, dataout); if( isOK) { - if (MF_DBGLEVEL >= MF_DBG_EXTENDED) - Dbprintf("Authentication part2: Failed"); - //OnError(4); + if (MF_DBGLEVEL >= MF_DBG_EXTENDED) Dbprintf("Authentication part2: Failed"); + OnError(4); return; } - if (MF_DBGLEVEL >= MF_DBG_EXTENDED) - DbpString("AUTH 2 FINISHED"); + if (MF_DBGLEVEL >= MF_DBG_EXTENDED) DbpString("AUTH 2 FINISHED"); cmd_send(CMD_ACK, isOK, 0, 0, dataout, sizeof(dataout)); FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); LEDsoff(); } + + void OnSuccess(){ + pcb_blocknum = 0; + ReaderTransmit(deselect_cmd, 3 , NULL); + FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); + LEDsoff(); + } + + void OnError(uint8_t reason){ + pcb_blocknum = 0; + ReaderTransmit(deselect_cmd, 3 , NULL); + FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); + cmd_send(CMD_ACK,0,reason,0,0,0); + LEDsoff(); + } diff --combined armsrc/mifareutil.c index 8c44445f,2f84797b..109b91b0 --- a/armsrc/mifareutil.c +++ b/armsrc/mifareutil.c @@@ -315,34 -315,35 +315,35 @@@ int mifare_ul_ev1_auth(uint8_t *keybyte uint16_t len; uint8_t resp[4]; uint8_t respPar[1]; - uint8_t key[4] = {0x00}; + uint8_t key[4] = {0x00}; memcpy(key, keybytes, 4); - + Dbprintf("EV1 Auth : %02x%02x%02x%02x", key[0], key[1], key[2], key[3]); len = mifare_sendcmd_short_mfuev1auth(NULL, 0, 0x1B, key, resp, respPar, NULL); if (len != 4) { if (MF_DBGLEVEL >= MF_DBG_ERROR) Dbprintf("Cmd Error: %02x %u", resp[0], len); return 0; } - + if (MF_DBGLEVEL >= MF_DBG_EXTENDED) - Dbprintf("Auth Resp: %02x%02x%02x%02x", resp[0],resp[1],resp[2],resp[3]); - + Dbprintf("Auth Resp: %02x%02x%02x%02x", resp[0],resp[1],resp[2],resp[3]); + memcpy(pack, resp, 4); return 1; } int mifare_ultra_auth(uint8_t *keybytes){ - // 3des2k + /// 3des2k + uint8_t random_a[8] = {1,1,1,1,1,1,1,1}; uint8_t random_b[8] = {0x00}; uint8_t enc_random_b[8] = {0x00}; uint8_t rnd_ab[16] = {0x00}; uint8_t IV[8] = {0x00}; - uint8_t key[16] = {0x00}; + uint8_t key[16] = {0x00}; memcpy(key, keybytes, 16); - + uint16_t len; uint8_t resp[19] = {0x00}; uint8_t respPar[3] = {0,0,0}; @@@ -362,41 -363,41 +363,61 @@@ rol(random_b,8); memcpy(rnd_ab ,random_a,8); memcpy(rnd_ab+8,random_b,8); - + if (MF_DBGLEVEL >= MF_DBG_EXTENDED) { Dbprintf("enc_B: %02x %02x %02x %02x %02x %02x %02x %02x", enc_random_b[0],enc_random_b[1],enc_random_b[2],enc_random_b[3],enc_random_b[4],enc_random_b[5],enc_random_b[6],enc_random_b[7]); - + Dbprintf(" B: %02x %02x %02x %02x %02x %02x %02x %02x", random_b[0],random_b[1],random_b[2],random_b[3],random_b[4],random_b[5],random_b[6],random_b[7]); Dbprintf("rnd_ab: %02x %02x %02x %02x %02x %02x %02x %02x", rnd_ab[0],rnd_ab[1],rnd_ab[2],rnd_ab[3],rnd_ab[4],rnd_ab[5],rnd_ab[6],rnd_ab[7]); - + Dbprintf("rnd_ab: %02x %02x %02x %02x %02x %02x %02x %02x", rnd_ab[8],rnd_ab[9],rnd_ab[10],rnd_ab[11],rnd_ab[12],rnd_ab[13],rnd_ab[14],rnd_ab[15] ); } - + + // encrypt out, in, length, key, iv + tdes_2key_enc(rnd_ab, rnd_ab, sizeof(rnd_ab), key, enc_random_b); + + len = mifare_sendcmd_short_mfucauth(NULL, 1, 0xAF, rnd_ab, resp, respPar, NULL); + if (len != 11) { + if (MF_DBGLEVEL >= MF_DBG_ERROR) Dbprintf("Cmd Error: %02x", resp[0]); + return 0; + } + + uint8_t enc_resp[8] = { 0,0,0,0,0,0,0,0 }; + uint8_t resp_random_a[8] = { 0,0,0,0,0,0,0,0 }; + memcpy(enc_resp, resp+1, 8); + + // decrypt out, in, length, key, iv + tdes_2key_dec(resp_random_a, enc_resp, 8, key, enc_random_b); + if ( memcmp(resp_random_a, random_a, 8) != 0 ) { + if (MF_DBGLEVEL >= MF_DBG_ERROR) Dbprintf("failed authentication"); + return 0; + } + + // encrypt out, in, length, key, iv + tdes_2key_enc(rnd_ab, rnd_ab, sizeof(rnd_ab), key, enc_random_b); + + len = mifare_sendcmd_short_mfucauth(NULL, 1, 0xAF, rnd_ab, resp, respPar, NULL); + if (len != 11) { + if (MF_DBGLEVEL >= MF_DBG_ERROR) Dbprintf("Cmd Error: %02x", resp[0]); + return 0; + } + + uint8_t enc_resp[8] = { 0,0,0,0,0,0,0,0 }; + uint8_t resp_random_a[8] = { 0,0,0,0,0,0,0,0 }; + memcpy(enc_resp, resp+1, 8); + + // decrypt out, in, length, key, iv + tdes_2key_dec(resp_random_a, enc_resp, 8, key, enc_random_b); + if ( memcmp(resp_random_a, random_a, 8) != 0 ) { + if (MF_DBGLEVEL >= MF_DBG_ERROR) Dbprintf("failed authentication"); + return 0; + } + if (MF_DBGLEVEL >= MF_DBG_EXTENDED) { Dbprintf("e_AB: %02x %02x %02x %02x %02x %02x %02x %02x", rnd_ab[0],rnd_ab[1],rnd_ab[2],rnd_ab[3], @@@ -409,7 -410,7 +430,7 @@@ Dbprintf("a: %02x %02x %02x %02x %02x %02x %02x %02x", random_a[0],random_a[1],random_a[2],random_a[3], random_a[4],random_a[5],random_a[6],random_a[7]); - + Dbprintf("b: %02x %02x %02x %02x %02x %02x %02x %02x", resp_random_a[0],resp_random_a[1],resp_random_a[2],resp_random_a[3], resp_random_a[4],resp_random_a[5],resp_random_a[6],resp_random_a[7]); @@@ -449,9 -450,9 +470,9 @@@ int mifare_classic_writeblock(struct Cr { // variables uint16_t len, i; - uint32_t pos; - uint8_t par[3] = {0}; // enough for 18 Bytes to send - byte_t res; + uint32_t pos = 0; + uint8_t par[3] = {0x00}; // enough for 18 Bytes to send + byte_t res = 0; uint8_t d_block[18], d_block_enc[18]; uint8_t receivedAnswer[MAX_MIFARE_FRAME_SIZE]; @@@ -494,56 -495,56 +515,56 @@@ int mifare_ultra_writeblock(uint8_t blockNo, uint8_t *blockData) { - 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] = {0x00}; uint8_t receivedAnswer[MAX_FRAME_SIZE]; uint8_t receivedAnswerPar[MAX_PARITY_SIZE]; - + - // command MIFARE_CLASSIC_WRITEBLOCK - len = mifare_sendcmd_short(NULL, true, 0xA0, blockNo, receivedAnswer, receivedAnswerPar, NULL); + // command MIFARE_CLASSIC_WRITEBLOCK + 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 >= MF_DBG_ERROR) - Dbprintf("Cmd Addr Error: %02x", receivedAnswer[0]); + Dbprintf("Cmd Addr Error: %02x", receivedAnswer[0]); - return 1; - } + return 1; + } memcpy(d_block, blockData, 16); - AppendCrc14443a(d_block, 16); + AppendCrc14443a(d_block, 16); ReaderTransmitPar(d_block, sizeof(d_block), par, NULL); - len = ReaderReceive(receivedAnswer, receivedAnswerPar); + len = ReaderReceive(receivedAnswer, receivedAnswerPar); if ((len != 1) || (receivedAnswer[0] != 0x0A)) { // 0x0a - ACK if (MF_DBGLEVEL >= MF_DBG_ERROR) Dbprintf("Cmd Data Error: %02x %d", receivedAnswer[0],len); - return 2; + return 2; - } + } - return 0; + return 0; - } + } int mifare_ultra_special_writeblock(uint8_t blockNo, uint8_t *blockData) { - uint16_t len; + uint16_t len; uint8_t d_block[8] = {0x00}; uint8_t receivedAnswer[MAX_MIFARE_FRAME_SIZE]; uint8_t receivedAnswerPar[MAX_MIFARE_PARITY_SIZE]; - // command MIFARE_CLASSIC_WRITEBLOCK + // command MIFARE_CLASSIC_WRITEBLOCK d_block[0]= blockNo; memcpy(d_block+1,blockData,4); AppendCrc14443a(d_block, 6); - 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 >= MF_DBG_ERROR) Dbprintf("Cmd Send Error: %02x %d", receivedAnswer[0],len); - return 1; - } - return 0; + return 1; + } + return 0; } int mifare_classic_halt(struct Crypto1State *pcs, uint32_t uid) @@@ -757,8 -758,8 +778,8 @@@ int mifare_desfire_des_auth2(uint32_t u data[0] = 0xAF; memcpy(data+1,key,16); - uint8_t receivedAnswer[MAX_MIFARE_FRAME_SIZE]; - uint8_t receivedAnswerPar[MAX_MIFARE_PARITY_SIZE]; + uint8_t receivedAnswer[MAX_FRAME_SIZE]; + uint8_t receivedAnswerPar[MAX_PARITY_SIZE]; len = mifare_sendcmd_special2(NULL, 1, 0x03, data, receivedAnswer, receivedAnswerPar ,NULL); diff --combined armsrc/mifareutil.h index f73814be,d4fcd818..9575b9fc --- a/armsrc/mifareutil.h +++ b/armsrc/mifareutil.h @@@ -52,34 -52,34 +52,34 @@@ extern int MF_DBGLEVEL #define cardSTATE_TO_IDLE() cardSTATE = MFEMUL_IDLE; LED_B_OFF(); LED_C_OFF(); -//functions -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); +//functions +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_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_short_mfuev1auth(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_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_ul_ev1_auth(uint8_t *key, uint8_t *pack); int mifare_ultra_auth(uint8_t *key); - int mifare_ultra_readblock(uint8_t blockNo, uint8_t *blockData); + int mifare_ultra_readblock(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(uint8_t blockNo, uint8_t *blockData); -int mifare_ultra_special_writeblock(uint8_t blockNo, uint8_t *blockData); -int mifare_classic_halt(struct Crypto1State *pcs, uint32_t uid); -int mifare_ultra_halt(); +int mifare_classic_writeblock(struct Crypto1State *pcs, uint32_t uid, uint8_t blockNo, uint8_t *blockData); +int mifare_ultra_writeblock(uint8_t blockNo, uint8_t *blockData); +int mifare_ultra_special_writeblock(uint8_t blockNo, uint8_t *blockData); +int mifare_classic_halt(struct Crypto1State *pcs, uint32_t uid); +int mifare_ultra_halt(); // 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 -void mf_crypto1_decrypt(struct Crypto1State *pcs, uint8_t *receivedCmd, int len); + +// crypto functions +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); uint8_t mf_crypto1_encrypt4bit(struct Crypto1State *pcs, uint8_t data); @@@ -94,7 -94,7 +94,7 @@@ void emlGetMem(uint8_t *data, int block void emlGetMemBt(uint8_t *data, int bytePtr, int byteCount); uint64_t emlGetKey(int sectorNum, int keyType); int emlGetValBl(uint32_t *blReg, uint8_t *blBlock, int blockNum); -int emlSetValBl(uint32_t blReg, uint8_t blBlock, int blockNum); -int emlCheckValBl(int blockNum); - -#endif +int emlSetValBl(uint32_t blReg, uint8_t blBlock, int blockNum); +int emlCheckValBl(int blockNum); + +#endif diff --combined client/cmdhf.c index 1a088676,16f7bb0f..614dcdc4 --- a/client/cmdhf.c +++ b/client/cmdhf.c @@@ -23,8 -23,6 +23,8 @@@ #include "cmdhficlass.h" #include "cmdhfmf.h" #include "cmdhfmfu.h" +#include "cmdhfmfdes.h" +#include "cmdhftopaz.h" #include "protocols.h" static int CmdHelp(const char *Cmd); @@@ -36,6 -34,7 +36,6 @@@ int CmdHFTune(const char *Cmd return 0; } - void annotateIso14443a(char *exp, size_t size, uint8_t* cmd, uint8_t cmdsize) { switch(cmd[0]) @@@ -84,46 -83,45 +84,46 @@@ case MIFARE_MAGICWUPC1: snprintf(exp,size,"MAGIC WUPC1"); break; case MIFARE_MAGICWUPC2: snprintf(exp,size,"MAGIC WUPC2"); break; case MIFARE_MAGICWIPEC: snprintf(exp,size,"MAGIC WIPEC"); break; - case MIFARE_ULC_AUTH_1: snprintf(exp,size,"AUTH "); break; - case MIFARE_ULC_AUTH_2: snprintf(exp,size,"AUTH_ANSW"); break; - case MIFARE_ULEV1_AUTH: + case MIFARE_ULC_AUTH_1 : snprintf(exp,size,"AUTH "); break; + case MIFARE_ULC_AUTH_2 : snprintf(exp,size,"AUTH_ANSW"); break; + case MIFARE_ULEV1_AUTH : if ( cmdsize == 7 ) snprintf(exp,size,"PWD-AUTH KEY: 0x%02x%02x%02x%02x", cmd[1], cmd[2], cmd[3], cmd[4] ); else snprintf(exp,size,"PWD-AUTH"); break; - case MIFARE_ULEV1_FASTREAD:{ + + case MIFARE_ULEV1_FASTREAD : { if ( cmdsize >=3 && cmd[2] <= 0xE6) snprintf(exp,size,"READ RANGE (%d-%d)",cmd[1],cmd[2]); else snprintf(exp,size,"?"); break; } - case MIFARE_ULC_WRITE:{ + case MIFARE_ULC_WRITE : { if ( cmd[1] < 0x21 ) snprintf(exp,size,"WRITEBLOCK(%d)",cmd[1]); else snprintf(exp,size,"?"); break; } - case MIFARE_ULEV1_READ_CNT:{ + case MIFARE_ULEV1_READ_CNT :{ if ( cmd[1] < 5 ) snprintf(exp,size,"READ CNT(%d)",cmd[1]); else snprintf(exp,size,"?"); break; } - case MIFARE_ULEV1_INCR_CNT:{ + case MIFARE_ULEV1_INCR_CNT : { if ( cmd[1] < 5 ) snprintf(exp,size,"INCR(%d)",cmd[1]); else snprintf(exp,size,"?"); break; } - case MIFARE_ULEV1_READSIG: snprintf(exp,size,"READ_SIG"); break; - case MIFARE_ULEV1_CHECKTEAR: snprintf(exp,size,"CHK_TEARING(%d)",cmd[1]); break; - case MIFARE_ULEV1_VCSL: snprintf(exp,size,"VCSL"); break; + case MIFARE_ULEV1_READSIG : snprintf(exp,size,"READ_SIG"); break; + case MIFARE_ULEV1_CHECKTEAR : snprintf(exp,size,"CHK_TEARING(%d)",cmd[1]); break; + case MIFARE_ULEV1_VCSL : snprintf(exp,size,"VCSL"); break; default: snprintf(exp,size,"?"); break; } return; @@@ -189,26 -187,6 +189,26 @@@ void annotateIso15693(char *exp, size_ } } + +void annotateTopaz(char *exp, size_t size, uint8_t* cmd, uint8_t cmdsize) +{ + switch(cmd[0]) { + case TOPAZ_REQA :snprintf(exp, size, "REQA");break; + case TOPAZ_WUPA :snprintf(exp, size, "WUPA");break; + case TOPAZ_RID :snprintf(exp, size, "RID");break; + case TOPAZ_RALL :snprintf(exp, size, "RALL");break; + case TOPAZ_READ :snprintf(exp, size, "READ");break; + case TOPAZ_WRITE_E :snprintf(exp, size, "WRITE-E");break; + case TOPAZ_WRITE_NE :snprintf(exp, size, "WRITE-NE");break; + case TOPAZ_RSEG :snprintf(exp, size, "RSEG");break; + case TOPAZ_READ8 :snprintf(exp, size, "READ8");break; + case TOPAZ_WRITE_E8 :snprintf(exp, size, "WRITE-E8");break; + case TOPAZ_WRITE_NE8 :snprintf(exp, size, "WRITE-NE8");break; + default: snprintf(exp,size,"?"); break; + } +} + + /** 06 00 = INITIATE 0E xx = SELECT ID (xx = Chip-ID) @@@ -240,34 -218,7 +240,34 @@@ void annotateIso14443b(char *exp, size_ } /** - * @brief iso14443B_CRC_Ok Checks CRC in command or response + * @brief iso14443A_CRC_check Checks CRC in command or response + * @param isResponse + * @param data + * @param len + * @return 0 : CRC-command, CRC not ok + * 1 : CRC-command, CRC ok + * 2 : Not crc-command + */ + +uint8_t iso14443A_CRC_check(bool isResponse, uint8_t* data, uint8_t len) +{ + uint8_t b1,b2; + + if(len <= 2) return 2; + + if(isResponse & (len < 6)) return 2; + + ComputeCrc14443(CRC_14443_A, data, len-2, &b1, &b2); + if (b1 != data[len-2] || b2 != data[len-1]) { + return 0; + } else { + return 1; + } +} + + +/** + * @brief iso14443B_CRC_check Checks CRC in command or response * @param isResponse * @param data * @param len @@@ -350,66 -301,11 +350,66 @@@ uint8_t iclass_CRC_check(bool isRespons } } -uint16_t printTraceLine(uint16_t tracepos, uint16_t traceLen, uint8_t *trace, uint8_t protocol, bool showWaitCycles) + +bool is_last_record(uint16_t tracepos, uint8_t *trace, uint16_t traceLen) { - bool isResponse; - uint16_t duration, data_len, parity_len; + return(tracepos + sizeof(uint32_t) + sizeof(uint16_t) + sizeof(uint16_t) >= traceLen); +} + + +bool next_record_is_response(uint16_t tracepos, uint8_t *trace) +{ + uint16_t next_records_datalen = *((uint16_t *)(trace + tracepos + sizeof(uint32_t) + sizeof(uint16_t))); + + return(next_records_datalen & 0x8000); +} + + +bool merge_topaz_reader_frames(uint32_t timestamp, uint32_t *duration, uint16_t *tracepos, uint16_t traceLen, uint8_t *trace, uint8_t *frame, uint8_t *topaz_reader_command, uint16_t *data_len) +{ + +#define MAX_TOPAZ_READER_CMD_LEN 16 + + uint32_t last_timestamp = timestamp + *duration; + + if ((*data_len != 1) || (frame[0] == TOPAZ_WUPA) || (frame[0] == TOPAZ_REQA)) return false; + + memcpy(topaz_reader_command, frame, *data_len); + while (!is_last_record(*tracepos, trace, traceLen) && !next_record_is_response(*tracepos, trace)) { + uint32_t next_timestamp = *((uint32_t *)(trace + *tracepos)); + *tracepos += sizeof(uint32_t); + uint16_t next_duration = *((uint16_t *)(trace + *tracepos)); + *tracepos += sizeof(uint16_t); + uint16_t next_data_len = *((uint16_t *)(trace + *tracepos)) & 0x7FFF; + *tracepos += sizeof(uint16_t); + uint8_t *next_frame = (trace + *tracepos); + *tracepos += next_data_len; + if ((next_data_len == 1) && (*data_len + next_data_len <= MAX_TOPAZ_READER_CMD_LEN)) { + memcpy(topaz_reader_command + *data_len, next_frame, next_data_len); + *data_len += next_data_len; + last_timestamp = next_timestamp + next_duration; + } else { + // rewind and exit + *tracepos = *tracepos - next_data_len - sizeof(uint16_t) - sizeof(uint16_t) - sizeof(uint32_t); + break; + } + uint16_t next_parity_len = (next_data_len-1)/8 + 1; + *tracepos += next_parity_len; + } + + *duration = last_timestamp - timestamp; + + return true; +} + + +uint16_t printTraceLine(uint16_t tracepos, uint16_t traceLen, uint8_t *trace, uint8_t protocol, bool showWaitCycles, bool markCRCBytes) +{ + bool isResponse; + uint16_t data_len, parity_len; + uint32_t duration; + uint8_t topaz_reader_command[9]; uint32_t timestamp, first_timestamp, EndOfTransmissionTimestamp; char explanation[30] = {0}; @@@ -440,31 -336,29 +440,31 @@@ uint8_t *parityBytes = trace + tracepos; tracepos += parity_len; + if (protocol == TOPAZ && !isResponse) { + // topaz reader commands come in 1 or 9 separate frames with 7 or 8 Bits each. + // merge them: + if (merge_topaz_reader_frames(timestamp, &duration, &tracepos, traceLen, trace, frame, topaz_reader_command, &data_len)) { + frame = topaz_reader_command; + } + } + //Check the CRC status uint8_t crcStatus = 2; if (data_len > 2) { - uint8_t b1, b2; - if(protocol == ICLASS) - { - crcStatus = iclass_CRC_check(isResponse, frame, data_len); - - }else if (protocol == ISO_14443B) - { - crcStatus = iso14443B_CRC_check(isResponse, frame, data_len); - } - else if (protocol == ISO_14443A){//Iso 14443a - - ComputeCrc14443(CRC_14443_A, frame, data_len-2, &b1, &b2); - - if (b1 != frame[data_len-2] || b2 != frame[data_len-1]) { - if(!(isResponse & (data_len < 6))) - { - crcStatus = 0; - } - } + switch (protocol) { + case ICLASS: + crcStatus = iclass_CRC_check(isResponse, frame, data_len); + break; + case ISO_14443B: + case TOPAZ: + crcStatus = iso14443B_CRC_check(isResponse, frame, data_len); + break; + case ISO_14443A: + crcStatus = iso14443A_CRC_check(isResponse, frame, data_len); + break; + default: + break; } } //0 CRC-command, CRC not ok @@@ -472,6 -366,7 +472,6 @@@ //2 Not crc-command //--- Draw the data column - //char line[16][110]; char line[16][110]; for (int j = 0; j < data_len && j/16 < 16; j++) { @@@ -485,44 -380,45 +485,44 @@@ uint8_t parityBits = parityBytes[j>>3]; if (isResponse && (oddparity != ((parityBits >> (7-(j&0x0007))) & 0x01))) { snprintf(line[j/16]+(( j % 16) * 4),110, "%02x! ", frame[j]); - } else { snprintf(line[j/16]+(( j % 16) * 4),110, "%02x ", frame[j]); } - - } - if(crcStatus == 1) - {//CRC-command - char *pos1 = line[(data_len-2)/16]+(((data_len-2) % 16) * 4)-1; - (*pos1) = '['; - char *pos2 = line[(data_len)/16]+(((data_len) % 16) * 4)-2; - (*pos2) = ']'; } - if(data_len == 0) - { - if(data_len == 0){ - sprintf(line[0],""); + + if (markCRCBytes) { + //CRC-command + if(crcStatus == 0 || crcStatus == 1) { + char *pos1 = line[(data_len-2)/16]+(((data_len-2) % 16) * 4); + (*pos1) = '['; + char *pos2 = line[(data_len)/16]+(((data_len) % 16) * 4); + sprintf(pos2, "%c", ']'); } } - //--- Draw the CRC column + if(data_len == 0){ + sprintf(line[0],""); + } + //--- Draw the CRC column char *crc = (crcStatus == 0 ? "!crc" : (crcStatus == 1 ? " ok " : " ")); EndOfTransmissionTimestamp = timestamp + duration; if(!isResponse) { - if(protocol == ICLASS) - annotateIclass(explanation,sizeof(explanation),frame,data_len); - else if (protocol == ISO_14443A) - annotateIso14443a(explanation,sizeof(explanation),frame,data_len); - else if(protocol == ISO_14443B) - annotateIso14443b(explanation,sizeof(explanation),frame,data_len); + switch(protocol) { + case ICLASS: annotateIclass(explanation,sizeof(explanation),frame,data_len); break; + case ISO_14443A: annotateIso14443a(explanation,sizeof(explanation),frame,data_len); break; + case ISO_14443B: annotateIso14443b(explanation,sizeof(explanation),frame,data_len); break; + case TOPAZ: annotateTopaz(explanation,sizeof(explanation),frame,data_len); break; + default: break; + } } int num_lines = MIN((data_len - 1)/16 + 1, 16); for (int j = 0; j < num_lines ; j++) { if (j == 0) { - PrintAndLog(" %9d | %9d | %s | %-64s| %s| %s", + PrintAndLog(" %10d | %10d | %s |%-64s | %s| %s", (timestamp - first_timestamp), (EndOfTransmissionTimestamp - first_timestamp), (isResponse ? "Tag" : "Rdr"), @@@ -530,23 -426,27 +530,23 @@@ (j == num_lines-1) ? crc : " ", (j == num_lines-1) ? explanation : ""); } else { - PrintAndLog(" | | | %-64s| %s| %s", + PrintAndLog(" | | |%-64s | %s| %s", line[j], - (j == num_lines-1)?crc:" ", + (j == num_lines-1) ? crc : " ", (j == num_lines-1) ? explanation : ""); } } - if (tracepos + sizeof(uint32_t) + sizeof(uint16_t) + sizeof(uint16_t) > traceLen) return traceLen; + if (is_last_record(tracepos, trace, traceLen)) return traceLen; - bool next_isResponse = *((uint16_t *)(trace + tracepos + 6)) & 0x8000; - - if (showWaitCycles && !isResponse && next_isResponse) { + if (showWaitCycles && !isResponse && next_record_is_response(tracepos, trace)) { uint32_t next_timestamp = *((uint32_t *)(trace + tracepos)); - if (next_timestamp != 0x44444444) { - PrintAndLog(" %9d | %9d | %s | fdt (Frame Delay Time): %d", + PrintAndLog(" %10d | %10d | %s |fdt (Frame Delay Time): %d", (EndOfTransmissionTimestamp - first_timestamp), (next_timestamp - first_timestamp), " ", (next_timestamp - EndOfTransmissionTimestamp)); } - } return tracepos; } @@@ -555,35 -455,34 +555,35 @@@ int CmdHFList(const char *Cmd) { bool showWaitCycles = false; + bool markCRCBytes = false; char type[40] = {0}; int tlen = param_getstr(Cmd,0,type); - char param = param_getchar(Cmd, 1); + char param1 = param_getchar(Cmd, 1); + char param2 = param_getchar(Cmd, 2); bool errors = false; uint8_t protocol = 0; //Validate params - if(tlen == 0) - { + + if(tlen == 0) { errors = true; } - if(param == 'h' || (param !=0 && param != 'f')) - { + + if(param1 == 'h' + || (param1 != 0 && param1 != 'f' && param1 != 'c') + || (param2 != 0 && param2 != 'f' && param2 != 'c')) { errors = true; } - if(!errors) - { - if(strcmp(type, "iclass") == 0) - { + + if(!errors) { + if(strcmp(type, "iclass") == 0) { protocol = ICLASS; - }else if(strcmp(type, "14a") == 0) - { + } else if(strcmp(type, "14a") == 0) { protocol = ISO_14443A; - } - else if(strcmp(type, "14b") == 0) - { + } else if(strcmp(type, "14b") == 0) { protocol = ISO_14443B; - }else if(strcmp(type,"raw")== 0) - { + } else if(strcmp(type,"topaz")== 0) { + protocol = TOPAZ; + } else if(strcmp(type,"raw")== 0) { protocol = -1;//No crc, no annotations }else{ errors = true; @@@ -592,15 -491,13 +592,15 @@@ if (errors) { PrintAndLog("List protocol data in trace buffer."); - PrintAndLog("Usage: hf list [f]"); + PrintAndLog("Usage: hf list [f][c]"); PrintAndLog(" f - show frame delay times as well"); + PrintAndLog(" c - mark CRC bytes"); PrintAndLog("Supported values:"); PrintAndLog(" raw - just show raw data without annotations"); PrintAndLog(" 14a - interpret data as iso14443a communications"); PrintAndLog(" 14b - interpret data as iso14443b communications"); PrintAndLog(" iclass - interpret data as iclass communications"); + PrintAndLog(" topaz - interpret data as topaz communications"); PrintAndLog(""); PrintAndLog("example: hf list 14a f"); PrintAndLog("example: hf list iclass"); @@@ -608,13 -505,10 +608,13 @@@ } - if (param == 'f') { + if (param1 == 'f' || param2 == 'f') { showWaitCycles = true; } + if (param1 == 'c' || param2 == 'c') { + markCRCBytes = true; + } uint8_t *trace; uint16_t tracepos = 0; @@@ -643,12 -537,12 +643,12 @@@ PrintAndLog("iso14443a - All times are in carrier periods (1/13.56Mhz)"); PrintAndLog("iClass - Timings are not as accurate"); PrintAndLog(""); - PrintAndLog(" Start | End | Src | Data (! denotes parity error) | CRC | Annotation |"); - PrintAndLog("-----------|-----------|-----|-----------------------------------------------------------------|-----|--------------------|"); + PrintAndLog(" Start | End | Src | Data (! denotes parity error) | CRC | Annotation |"); + PrintAndLog("------------|------------|-----|-----------------------------------------------------------------|-----|--------------------|"); while(tracepos < traceLen) { - tracepos = printTraceLine(tracepos, traceLen, trace, protocol, showWaitCycles); + tracepos = printTraceLine(tracepos, traceLen, trace, protocol, showWaitCycles, markCRCBytes); } free(trace); @@@ -677,7 -571,7 +677,7 @@@ int CmdHFSearch(const char *Cmd) //14b has issues currently... //ans = CmdHF14BRead(Cmd); - //if (ans > 0) return ans; + //if (ans > 0) return ans; return 0; } @@@ -691,12 -585,10 +691,12 @@@ static command_t CommandTable[] {"epa", CmdHFEPA, 1, "{ German Identification Card... }"}, {"legic", CmdHFLegic, 0, "{ LEGIC RFIDs... }"}, {"iclass", CmdHFiClass, 1, "{ ICLASS RFIDs... }"}, - {"mf", CmdHFMF, 1, "{ MIFARE RFIDs... }"}, + {"mf", CmdHFMF, 1, "{ MIFARE RFIDs... }"}, - {"mfu", CmdHFMFUltra, 1, "{ MIFARE Ultralight RFIDs... }"}, + {"mfu", CmdHFMFUltra, 1, "{ MIFARE Ultralight RFIDs... }"}, - {"tune", CmdHFTune, 0, "Continuously measure HF antenna tuning"}, + {"mfdes", CmdHFMFDes, 1, "{ MIFARE Desfire RFIDs... }"}, + {"topaz", CmdHFTopaz, 1, "{ TOPAZ (NFC Type 1) RFIDs... }"}, + {"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"}, {"search", CmdHFSearch, 1, "Search for known HF tags [preliminary]"}, {NULL, NULL, 0, NULL} }; diff --combined client/cmdhficlass.c index d6c79165,824aaa36..e8ba68f1 --- a/client/cmdhficlass.c +++ b/client/cmdhficlass.c @@@ -174,12 -174,12 +174,12 @@@ int HFiClassReader(const char *Cmd, boo SendCommand(&c); UsbCommand resp; while(!ukbhit()){ - if (WaitForResponseTimeout(CMD_ACK,&resp,4500)) { + if (WaitForResponseTimeout(CMD_ACK,&resp, 4500)) { - uint8_t readStatus = resp.arg[0] & 0xff; + uint8_t readStatus = resp.arg[0] & 0xff; - uint8_t * data = resp.d.asBytes; + uint8_t *data = resp.d.asBytes; if (verbose) - PrintAndLog("Readstatus:%02x", readStatus); + PrintAndLog("Readstatus:%02x", readStatus); if( readStatus == 0){ //Aborted if (verbose) PrintAndLog("Quitting..."); diff --combined client/cmdhfmf.c index 1b815326,aa3b66dc..676a8884 --- a/client/cmdhfmf.c +++ b/client/cmdhfmf.c @@@ -781,8 -781,8 +781,8 @@@ int CmdHF14AMfChk(const char *Cmd PrintAndLog("Usage: hf mf chk |<*card memory> [t|d] [] []"); PrintAndLog(" * - all sectors"); PrintAndLog("card memory - 0 - MINI(320 bytes), 1 - 1K, 2 - 2K, 4 - 4K, - 1K"); - PrintAndLog("d - write keys to binary file\n"); - PrintAndLog("t - write keys to emulator memory"); + PrintAndLog("d - write keys to binary file"); + PrintAndLog("t - write keys to emulator memory\n"); PrintAndLog(" sample: hf mf chk 0 A 1234567890ab keys.dic"); PrintAndLog(" hf mf chk *1 ? t"); PrintAndLog(" hf mf chk *1 ? d"); @@@ -1592,8 -1592,8 +1592,9 @@@ int CmdHF14AMfCLoad(const char *Cmd memset(buf, 0, sizeof(buf)); if (fgets(buf, sizeof(buf), f) == NULL) { + fclose(f); PrintAndLog("File reading error."); + fclose(f); return 2; } diff --combined client/cmdhfmfu.c index ea381736,07c379bc..6ab24a43 --- a/client/cmdhfmfu.c +++ b/client/cmdhfmfu.c @@@ -13,19 -13,19 +13,19 @@@ #include "cmdhf14a.h" #include "mifare.h" #include "util.h" -#include "protocols.h" +#include "../common/protocols.h" #include "data.h" - #define MAX_UL_BLOCKS 0x0f - #define MAX_ULC_BLOCKS 0x2b - #define MAX_ULEV1a_BLOCKS 0x13 - #define MAX_ULEV1b_BLOCKS 0x28 - #define MAX_NTAG_203 0x29 - #define MAX_NTAG_210 0x13 - #define MAX_NTAG_212 0x28 - #define MAX_NTAG_213 0x2c - #define MAX_NTAG_215 0x86 - #define MAX_NTAG_216 0xe6 + #define MAX_UL_BLOCKS 0x0f + #define MAX_ULC_BLOCKS 0x2b + #define MAX_ULEV1a_BLOCKS 0x13 + #define MAX_ULEV1b_BLOCKS 0x28 + #define MAX_NTAG_203 0x29 + #define MAX_NTAG_210 0x13 + #define MAX_NTAG_212 0x28 + #define MAX_NTAG_213 0x2c + #define MAX_NTAG_215 0x86 + #define MAX_NTAG_216 0xe6 #define KEYS_3DES_COUNT 7 uint8_t default_3des_keys[KEYS_3DES_COUNT][16] = { @@@ -35,25 -35,25 +35,25 @@@ { 0x49,0x45,0x4D,0x4B,0x41,0x45,0x52,0x42,0x21,0x4E,0x41,0x43,0x55,0x4F,0x59,0x46 },// NFC-key { 0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01 },// all ones { 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF },// all FF - { 0x00,0x11,0x22,0x33,0x44,0x55,0x66,0x77,0x88,0x99,0xAA,0xBB,0xCC,0xDD,0xEE,0xFF },// 11 22 33 - }; + { 0x00,0x11,0x22,0x33,0x44,0x55,0x66,0x77,0x88,0x99,0xAA,0xBB,0xCC,0xDD,0xEE,0xFF } // 11 22 33 + }; #define KEYS_PWD_COUNT 10 uint8_t default_pwd_pack[KEYS_PWD_COUNT][4] = { {0xFF,0xFF,0xFF,0xFF}, // PACK 0x00,0x00 -- factory default - + {0x4A,0xF8,0x4B,0x19}, // PACK 0xE5,0xBE -- italian bus (sniffed) {0x33,0x6B,0xA1,0x19}, // PACK 0x9c,0x2d -- italian bus (sniffed) {0xFF,0x90,0x6C,0xB2}, // PACK 0x12,0x9e -- italian bus (sniffed) {0x46,0x1c,0xA3,0x19}, // PACK 0xE9,0x5A -- italian bus (sniffed) {0x35,0x1C,0xD0,0x19}, // PACK 0x9A,0x5a -- italian bus (sniffed) - + {0x05,0x22,0xE6,0xB4}, // PACK 0x80,0x80 -- Amiiboo (sniffed) pikachu-b UID: {0x7E,0x22,0xE6,0xB4}, // PACK 0x80,0x80 -- AMiiboo (sniffed) {0x02,0xE1,0xEE,0x36}, // PACK 0x80,0x80 -- AMiiboo (sniffed) sonic UID: 04d257 7ae33e8027 {0x32,0x0C,0x16,0x17}, // PACK 0x80,0x80 -- AMiiboo (sniffed) - }; - + }; + #define MAX_UL_TYPES 16 uint16_t UL_TYPES_ARRAY[MAX_UL_TYPES] = {UNKNOWN, UL, UL_C, UL_EV1_48, UL_EV1_128, NTAG, NTAG_203, NTAG_210, NTAG_212, NTAG_213, NTAG_215, NTAG_216, MY_D, MY_D_NFC, MY_D_MOVE, MY_D_MOVE_NFC}; @@@ -65,9 -65,9 +65,9 @@@ uint8_t UL_MEMORY_ARRAY[MAX_UL_TYPES] static int CmdHelp(const char *Cmd); - char* getProductTypeStr( uint8_t id){ + char *getProductTypeStr( uint8_t id){ - static char buf[20]; + static char buf[20]; char *retStr = buf; switch(id) { @@@ -83,18 -83,18 +83,18 @@@ 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). */ - char* getUlev1CardSizeStr( uint8_t fsize ){ - - static char buf[40]; + char *getUlev1CardSizeStr( uint8_t fsize ){ + + static char buf[40]; char *retStr = buf; - memset(buf, 0, sizeof(buf)); - + memset(buf, 0, sizeof(buf)); + uint16_t usize = 1 << ((fsize >>1) + 1); uint16_t lsize = 1 << (fsize >>1); // is LSB set? - if ( fsize & 1 ) - sprintf(retStr, "%02X, (%u <-> %u bytes)", fsize, usize, lsize); + if ( fsize & 1 ) + sprintf(retStr, "%02X, (%u <-> %u bytes)",fsize, usize, lsize); else sprintf(retStr, "%02X, (%u bytes)", fsize, lsize); return buf; @@@ -115,9 -115,9 +115,9 @@@ static int ul_send_cmd_raw( uint8_t *cm memcpy(c.d.asBytes, cmd, cmdlen); SendCommand(&c); UsbCommand resp; - if ( !WaitForResponseTimeout(CMD_ACK, &resp, 1500) ) return -1; - if ( !resp.arg[0] && responseLength) return -1; - + if (!WaitForResponseTimeout(CMD_ACK, &resp, 1500)) return -1; + if (!resp.arg[0] && responseLength) return -1; + uint16_t resplen = (resp.arg[0] < responseLength) ? resp.arg[0] : responseLength; memcpy(response, resp.d.asBytes, resplen); return resplen; @@@ -127,7 -127,7 +127,7 @@@ static int ul_send_cmd_raw_crc( uint8_ UsbCommand c = {CMD_READER_ISO_14443a, {ISO14A_RAW | ISO14A_NO_DISCONNECT , cmdlen, 0}}; if (append_crc) c.arg[0] |= ISO14A_APPEND_CRC; - + memcpy(c.d.asBytes, cmd, cmdlen); SendCommand(&c); UsbCommand resp; @@@ -135,12 -135,12 +135,12 @@@ if (!resp.arg[0] && responseLength) return -1; uint16_t resplen = (resp.arg[0] < responseLength) ? resp.arg[0] : responseLength; - memcpy(response, resp.d.asBytes, resplen ); + memcpy(response, resp.d.asBytes, resplen); return resplen; } */ static int ul_select( iso14a_card_select_t *card ){ - + ul_switch_on_field(); UsbCommand resp; @@@ -151,63 -151,63 +151,127 @@@ ul_switch_off_field(); return 0; } + + memcpy(card, resp.d.asBytes, sizeof(iso14a_card_select_t)); + return 1; + } + + // This read command will at least return 16bytes. + static int ul_read( uint8_t page, uint8_t *response, uint16_t responseLength ){ + + uint8_t cmd[] = {ISO14443A_CMD_READBLOCK, page}; + int len = ul_send_cmd_raw(cmd, sizeof(cmd), response, responseLength); + return len; + } + + static int ul_comp_write( uint8_t page, uint8_t *data, uint8_t datalen ){ + + uint8_t cmd[18]; + memset(cmd, 0x00, sizeof(cmd)); + datalen = ( datalen > 16) ? 16 : datalen; + + cmd[0] = ISO14443A_CMD_WRITEBLOCK; + cmd[1] = page; + memcpy(cmd+2, data, datalen); + + uint8_t response[1] = {0xff}; + ul_send_cmd_raw(cmd, 2+datalen, response, sizeof(response)); + // ACK + if ( response[0] == 0x0a ) return 0; + // NACK + return -1; + } + + static int ulc_requestAuthentication( uint8_t *nonce, uint16_t nonceLength ){ + + uint8_t cmd[] = {MIFARE_ULC_AUTH_1, 0x00}; + int len = ul_send_cmd_raw(cmd, sizeof(cmd), nonce, nonceLength); + return len; + } + + static int ulc_authentication( uint8_t *key, bool switch_off_field ){ + + UsbCommand c = {CMD_MIFAREUC_AUTH, {switch_off_field}}; + memcpy(c.d.asBytes, key, 16); + SendCommand(&c); + UsbCommand resp; + if ( !WaitForResponseTimeout(CMD_ACK, &resp, 1500) ) return 0; + if ( resp.arg[0] == 1 ) return 1; + + return 0; + } + + static int ulev1_requestAuthentication( uint8_t *pwd, uint8_t *pack, uint16_t packLength ){ + + uint8_t cmd[] = {MIFARE_ULEV1_AUTH, pwd[0], pwd[1], pwd[2], pwd[3]}; + int len = ul_send_cmd_raw(cmd, sizeof(cmd), pack, packLength); + return len; + } + ++static int ul_auth_select( iso14a_card_select_t *card, TagTypeUL_t tagtype, bool hasAuthKey, uint8_t *authenticationkey, uint8_t *pack, uint8_t packSize){ ++ if ( hasAuthKey && (tagtype & UL_C)) { ++ //will select card automatically and close connection on error ++ if (!ulc_authentication(authenticationkey, false)) { ++ PrintAndLog("Error: Authentication Failed UL-C"); ++ return 0; ++ } + + memcpy(card, resp.d.asBytes, sizeof(iso14a_card_select_t)); + return 1; +} + +// This read command will at least return 16bytes. +static int ul_read( uint8_t page, uint8_t *response, uint16_t responseLength ){ + + uint8_t cmd[] = {ISO14443A_CMD_READBLOCK, page}; + int len = ul_send_cmd_raw(cmd, sizeof(cmd), response, responseLength); + return len; +} + +static int ul_comp_write( uint8_t page, uint8_t *data, uint8_t datalen ){ + + uint8_t cmd[18]; + memset(cmd, 0x00, sizeof(cmd)); + datalen = ( datalen > 16) ? 16 : datalen; + + cmd[0] = ISO14443A_CMD_WRITEBLOCK; + cmd[1] = page; + memcpy(cmd+2, data, datalen); + + uint8_t response[1] = {0xff}; + ul_send_cmd_raw(cmd, 2+datalen, response, sizeof(response)); + // ACK + if ( response[0] == 0x0a ) return 0; + // NACK + return -1; +} + +static int ulc_requestAuthentication( uint8_t *nonce, uint16_t nonceLength ){ + + uint8_t cmd[] = {MIFARE_ULC_AUTH_1, 0x00}; + int len = ul_send_cmd_raw(cmd, sizeof(cmd), nonce, nonceLength); + return len; +} + +static int ulc_authentication( uint8_t *key, bool switch_off_field ){ + + UsbCommand c = {CMD_MIFAREUC_AUTH, {switch_off_field}}; + memcpy(c.d.asBytes, key, 16); + SendCommand(&c); + UsbCommand resp; + if ( !WaitForResponseTimeout(CMD_ACK, &resp, 1500) ) return 0; + if ( resp.arg[0] == 1 ) return 1; + + return 0; +} + +static int ulev1_requestAuthentication( uint8_t *pwd, uint8_t *pack, uint16_t packLength ){ + + uint8_t cmd[] = {MIFARE_ULEV1_AUTH, pwd[0], pwd[1], pwd[2], pwd[3]}; + int len = ul_send_cmd_raw(cmd, sizeof(cmd), pack, packLength); + return len; +} + static int ul_auth_select( iso14a_card_select_t *card, TagTypeUL_t tagtype, bool hasAuthKey, uint8_t *authenticationkey, uint8_t *pack, uint8_t packSize){ if ( hasAuthKey && (tagtype & UL_C)) { //will select card automatically and close connection on error @@@ -230,7 -230,7 +294,7 @@@ } static int ulev1_getVersion( uint8_t *response, uint16_t responseLength ){ - + uint8_t cmd[] = {MIFARE_ULEV1_VERSION}; int len = ul_send_cmd_raw(cmd, sizeof(cmd), response, responseLength); return len; @@@ -268,7 -268,7 +332,7 @@@ static int ulev1_readSignature( uint8_ } static int ul_print_default( uint8_t *data){ - + uint8_t uid[7]; uid[0] = data[0]; uid[1] = data[1]; @@@ -279,7 -279,7 +343,7 @@@ uid[6] = data[7]; PrintAndLog(" UID : %s ", sprint_hex(uid, 7)); - PrintAndLog(" UID[0] : %02X, %s", uid[0], getTagInfo(uid[0]) ); + PrintAndLog(" UID[0] : %02X, Manufacturer: %s", uid[0], getTagInfo(uid[0]) ); if ( uid[0] == 0x05 ) { uint8_t chip = (data[8] & 0xC7); // 11000111 mask, bit 3,4,5 RFU switch (chip){ @@@ -294,13 -294,13 +358,13 @@@ PrintAndLog(" BCC0 : %02X, Ok", data[3]); else PrintAndLog(" BCC0 : %02X, crc should be %02X", data[3], crc0); - + int crc1 = data[4] ^ data[5] ^ data[6] ^data[7]; if ( data[8] == crc1 ) PrintAndLog(" BCC1 : %02X, Ok", data[8]); else PrintAndLog(" BCC1 : %02X, crc should be %02X", data[8], crc1 ); - + PrintAndLog(" Internal : %02X, %sdefault", data[9], (data[9]==0x48)?"":"not " ); PrintAndLog(" Lock : %s - %s", @@@ -308,359 -308,359 +372,777 @@@ printBits(2, data+10) ); - PrintAndLog("OneTimePad : %s - %s\n", - sprint_hex(data + 12, 4), - printBits(4, data+12) - ); + PrintAndLog("OneTimePad : %s - %s\n", + sprint_hex(data + 12, 4), + printBits(4, data+12) + ); + + return 0; + } + + static int ndef_print_CC(uint8_t *data) { + // no NDEF message + if(data[0] != 0xe1) + return -1; + + PrintAndLog("--- NDEF Message"); + PrintAndLog("Capability Container: %s", sprint_hex(data,4) ); + PrintAndLog(" %02X : NDEF Magic Number", data[0]); + PrintAndLog(" %02X : version %d.%d supported by tag", data[1], (data[1] & 0xF0) >> 4, data[1] & 0x0f); + PrintAndLog(" %02X : Physical Memory Size: %d bytes", data[2], (data[2] + 1) * 8); + if ( data[2] == 0x12 ) + PrintAndLog(" %02X : NDEF Memory Size: %d bytes", data[2], 144); + else if ( data[2] == 0x3e ) + PrintAndLog(" %02X : NDEF Memory Size: %d bytes", data[2], 496); + else if ( data[2] == 0x6d ) + PrintAndLog(" %02X : NDEF Memory Size: %d bytes", data[2], 872); + + PrintAndLog(" %02X : %s / %s", data[3], + (data[3] & 0xF0) ? "(RFU)" : "Read access granted without any security", + (data[3] & 0x0F)==0 ? "Write access granted without any security" : (data[3] & 0x0F)==0x0F ? "No write access granted at all" : "(RFU)"); + return 0; + } + + int ul_print_type(uint32_t tagtype, uint8_t spaces){ + char spc[11] = " "; + spc[10]=0x00; + char *spacer = spc + (10-spaces); + + if ( tagtype & UL ) + PrintAndLog("%sTYPE : MIFARE Ultralight (MF0ICU1) %s", spacer, (tagtype & MAGIC) ? "" : "" ); + else if ( tagtype & UL_C) + PrintAndLog("%sTYPE : MIFARE Ultralight C (MF0ULC) %s", spacer, (tagtype & MAGIC) ? "" : "" ); + else if ( tagtype & UL_EV1_48) + PrintAndLog("%sTYPE : MIFARE Ultralight EV1 48bytes (MF0UL1101)", spacer); + else if ( tagtype & UL_EV1_128) + PrintAndLog("%sTYPE : MIFARE Ultralight EV1 128bytes (MF0UL2101)", spacer); + else if ( tagtype & NTAG ) + PrintAndLog("%sTYPE : NTAG UNKNOWN", spacer); + else if ( tagtype & NTAG_203 ) + PrintAndLog("%sTYPE : NTAG 203 144bytes (NT2H0301F0DT)", spacer); + else if ( tagtype & NTAG_210 ) + PrintAndLog("%sTYPE : NTAG 210 48bytes (NT2L1011G0DU)", spacer); + else if ( tagtype & NTAG_212 ) + PrintAndLog("%sTYPE : NTAG 212 128bytes (NT2L1211G0DU)", spacer); + else if ( tagtype & NTAG_213 ) + PrintAndLog("%sTYPE : NTAG 213 144bytes (NT2H1311G0DU)", spacer); + else if ( tagtype & NTAG_215 ) + PrintAndLog("%sTYPE : NTAG 215 504bytes (NT2H1511G0DU)", spacer); + else if ( tagtype & NTAG_216 ) + PrintAndLog("%sTYPE : NTAG 216 888bytes (NT2H1611G0DU)", spacer); + else if ( tagtype & NTAG_I2C_1K ) + PrintAndLog("%sTYPE : NTAG I%sC 888bytes (NT3H1101FHK)", spacer, "\xFD"); + else if ( tagtype & NTAG_I2C_2K ) + PrintAndLog("%sTYPE : NTAG I%sC 1904bytes (NT3H1201FHK)", spacer, "\xFD"); + else if ( tagtype & MY_D ) + PrintAndLog("%sTYPE : INFINEON my-d\x99", spacer); + else if ( tagtype & MY_D_NFC ) + PrintAndLog("%sTYPE : INFINEON my-d\x99 NFC", spacer); + else if ( tagtype & MY_D_MOVE ) + PrintAndLog("%sTYPE : INFINEON my-d\x99 move", spacer); + else if ( tagtype & MY_D_MOVE_NFC ) + PrintAndLog("%sTYPE : INFINEON my-d\x99 move NFC", spacer); + else + PrintAndLog("%sTYPE : Unknown %06x", spacer, tagtype); + return 0; + } + + static int ulc_print_3deskey( uint8_t *data){ + PrintAndLog(" deskey1 [44/0x2C] : %s [%.4s]", sprint_hex(data ,4),data); + PrintAndLog(" deskey1 [45/0x2D] : %s [%.4s]", sprint_hex(data+4 ,4),data+4); + PrintAndLog(" deskey2 [46/0x2E] : %s [%.4s]", sprint_hex(data+8 ,4),data+8); + PrintAndLog(" deskey2 [47/0x2F] : %s [%.4s]", sprint_hex(data+12,4),data+12); + PrintAndLog("\n 3des key : %s", sprint_hex(SwapEndian64(data, 16, 8), 16)); + return 0; + } + + static int ulc_print_configuration( uint8_t *data){ + + PrintAndLog("--- UL-C Configuration"); + PrintAndLog(" Higher Lockbits [40/0x28] : %s - %s", sprint_hex(data, 4), printBits(2, data)); + PrintAndLog(" Counter [41/0x29] : %s - %s", sprint_hex(data+4, 4), printBits(2, data+4)); + + bool validAuth = (data[8] >= 0x03 && data[8] <= 0x30); + if ( validAuth ) + PrintAndLog(" Auth0 [42/0x2A] : %s page %d/0x%02X and above need authentication", sprint_hex(data+8, 4), data[8],data[8] ); + else{ + if ( data[8] == 0){ + PrintAndLog(" Auth0 [42/0x2A] : %s default", sprint_hex(data+8, 4) ); + } else { + PrintAndLog(" Auth0 [42/0x2A] : %s auth byte is out-of-range", sprint_hex(data+8, 4) ); + } + } + PrintAndLog(" Auth1 [43/0x2B] : %s %s", + sprint_hex(data+12, 4), + (data[12] & 1) ? "write access restricted": "read and write access restricted" + ); + return 0; + } + + static int ulev1_print_configuration( uint8_t *data, uint8_t startPage){ + + PrintAndLog("\n--- Tag Configuration"); + + bool strg_mod_en = (data[0] & 2); + uint8_t authlim = (data[4] & 0x07); + bool cfglck = (data[4] & 0x40); + bool prot = (data[4] & 0x80); + uint8_t vctid = data[5]; + + PrintAndLog(" cfg0 [%u/0x%02X] : %s", startPage, startPage, sprint_hex(data, 4)); + if ( data[3] < 0xff ) + PrintAndLog(" - page %d and above need authentication",data[3]); + else + PrintAndLog(" - pages don't need authentication"); + PrintAndLog(" - strong modulation mode %s", (strg_mod_en) ? "enabled":"disabled"); + PrintAndLog(" cfg1 [%u/0x%02X] : %s", startPage + 1, startPage + 1, sprint_hex(data+4, 4) ); + if ( authlim == 0) + PrintAndLog(" - Unlimited password attempts"); + else + PrintAndLog(" - Max number of password attempts is %d", authlim); + PrintAndLog(" - user configuration %s", cfglck ? "permanently locked":"writeable"); + PrintAndLog(" - %s access is protected with password", prot ? "read and write":"write"); + PrintAndLog(" - %02X, Virtual Card Type Identifier is %s default", vctid, (vctid==0x05)? "":"not"); + PrintAndLog(" PWD [%u/0x%02X] : %s- (cannot be read)", startPage + 2, startPage + 2, sprint_hex(data+8, 4)); + PrintAndLog(" PACK [%u/0x%02X] : %s - (cannot be read)", startPage + 3, startPage + 3, sprint_hex(data+12, 2)); + PrintAndLog(" RFU [%u/0x%02X] : %s- (cannot be read)", startPage + 3, startPage + 3, sprint_hex(data+12, 2)); + return 0; + } + + static int ulev1_print_counters(){ + PrintAndLog("--- Tag Counters"); + uint8_t tear[1] = {0}; + uint8_t counter[3] = {0,0,0}; + uint16_t len = 0; + for ( uint8_t i = 0; i<3; ++i) { + ulev1_readTearing(i,tear,sizeof(tear)); + len = ulev1_readCounter(i,counter, sizeof(counter) ); + if (len == 3) { + PrintAndLog(" [%0d] : %s", i, sprint_hex(counter,3)); + PrintAndLog(" - %02X tearing %s", tear[0], ( tear[0]==0xBD)?"Ok":"failure"); + } + } + return len; + } + + static int ulev1_print_signature( uint8_t *data, uint8_t len){ + PrintAndLog("\n--- Tag Signature"); + //PrintAndLog("IC signature public key name : NXP NTAG21x 2013"); // don't know if there is other NXP public keys.. :( + PrintAndLog("IC signature public key value : 04494e1a386d3d3cfe3dc10e5de68a499b1c202db5b132393e89ed19fe5be8bc61"); + PrintAndLog(" Elliptic curve parameters : secp128r1"); + PrintAndLog(" Tag ECC Signature : %s", sprint_hex(data, len)); + //to do: verify if signature is valid + //PrintAndLog("IC signature status: %s valid", (iseccvalid() )?"":"not"); + return 0; + } + + static int ulev1_print_version(uint8_t *data){ + PrintAndLog("\n--- Tag Version"); + PrintAndLog(" Raw bytes : %s",sprint_hex(data, 8) ); + PrintAndLog(" Vendor ID : %02X, %s", data[1], getTagInfo(data[1])); + PrintAndLog(" Product type : %s", getProductTypeStr(data[2])); + PrintAndLog(" Product subtype : %02X, %s", data[3], (data[3]==1) ?"17 pF":"50pF"); + PrintAndLog(" Major version : %02X", data[4]); + PrintAndLog(" Minor version : %02X", data[5]); + PrintAndLog(" Size : %s", getUlev1CardSizeStr(data[6])); + PrintAndLog(" Protocol type : %02X", data[7]); + return 0; + } + + /* + static int ulc_magic_test(){ + // Magic Ultralight test + // Magic UL-C, by observation, + // 1) it seems to have a static nonce response to 0x1A command. + // 2) the deskey bytes is not-zero:d out on as datasheet states. + // 3) UID - changeable, not only, but pages 0-1-2-3. + // 4) use the ul_magic_test ! magic tags answers specially! + int returnValue = UL_ERROR; + iso14a_card_select_t card; + uint8_t nonce1[11] = {0x00}; + uint8_t nonce2[11] = {0x00}; + int status = ul_select(&card); + if ( !status ){ + return UL_ERROR; + } + status = ulc_requestAuthentication(nonce1, sizeof(nonce1)); + if ( status > 0 ) { + status = ulc_requestAuthentication(nonce2, sizeof(nonce2)); + returnValue = ( !memcmp(nonce1, nonce2, 11) ) ? UL_C_MAGIC : UL_C; + } else { + returnValue = UL; + } + ul_switch_off_field(); + return returnValue; + } + */ + static int ul_magic_test(){ + + // Magic Ultralight tests + // 1) take present UID, and try to write it back. OBSOLETE + // 2) make a wrong length write to page0, and see if tag answers with ACK/NACK: + iso14a_card_select_t card; + if ( !ul_select(&card) ) + return UL_ERROR; + int status = ul_comp_write(0, NULL, 0); + ul_switch_off_field(); + if ( status == 0 ) + return MAGIC; + return 0; + } + + uint32_t GetHF14AMfU_Type(void){ + + TagTypeUL_t tagtype = UNKNOWN; + iso14a_card_select_t card; + uint8_t version[10] = {0x00}; + int status = 0; + int len; + + if (!ul_select(&card)) return UL_ERROR; + + // Ultralight - ATQA / SAK + if ( card.atqa[1] != 0x00 || card.atqa[0] != 0x44 || card.sak != 0x00 ) { + PrintAndLog("Tag is not Ultralight | NTAG | MY-D [ATQA: %02X %02X SAK: %02X]\n", card.atqa[1], card.atqa[0], card.sak); + ul_switch_off_field(); + return UL_ERROR; + } + + if ( card.uid[0] != 0x05) { + + len = ulev1_getVersion(version, sizeof(version)); + ul_switch_off_field(); + + switch (len) { + case 0x0A: { + + if ( version[2] == 0x03 && version[6] == 0x0B ) + tagtype = UL_EV1_48; + else if ( version[2] == 0x03 && version[6] != 0x0B ) + tagtype = UL_EV1_128; + else if ( version[2] == 0x04 && version[3] == 0x01 && version[6] == 0x0B ) + tagtype = NTAG_210; + else if ( version[2] == 0x04 && version[3] == 0x01 && version[6] == 0x0E ) + tagtype = NTAG_212; + else if ( version[2] == 0x04 && version[3] == 0x02 && version[6] == 0x0F ) + tagtype = NTAG_213; + else if ( version[2] == 0x04 && version[3] == 0x02 && version[6] == 0x11 ) + tagtype = NTAG_215; + else if ( version[2] == 0x04 && version[3] == 0x02 && version[6] == 0x13 ) + tagtype = NTAG_216; + else if ( version[2] == 0x04 && version[3] == 0x05 && version[6] == 0x13 ) + tagtype = NTAG_I2C_1K; + else if ( version[2] == 0x04 && version[3] == 0x05 && version[6] == 0x15 ) + tagtype = NTAG_I2C_2K; + else if ( version[2] == 0x04 ) + tagtype = NTAG; + + break; + } + case 0x01: tagtype = UL_C; break; + case 0x00: tagtype = UL; break; + case -1 : tagtype = (UL | UL_C | NTAG_203); break; // could be UL | UL_C magic tags + default : tagtype = UNKNOWN; break; + } + // UL vs UL-C vs ntag203 test + if (tagtype & (UL | UL_C | NTAG_203)) { + if ( !ul_select(&card) ) return UL_ERROR; + + // do UL_C check first... + uint8_t nonce[11] = {0x00}; + status = ulc_requestAuthentication(nonce, sizeof(nonce)); + ul_switch_off_field(); + if (status > 1) { + tagtype = UL_C; + } else { + // need to re-select after authentication error + if ( !ul_select(&card) ) return UL_ERROR; + + uint8_t data[16] = {0x00}; + // read page 0x26-0x29 (last valid ntag203 page) + status = ul_read(0x26, data, sizeof(data)); + if ( status <= 1 ) { + tagtype = UL; + } else { + // read page 0x30 (should error if it is a ntag203) + status = ul_read(0x30, data, sizeof(data)); + if ( status <= 1 ){ + tagtype = NTAG_203; + } else { + tagtype = UNKNOWN; + } + } + ul_switch_off_field(); + } + } + } else { + // Infinition MY-D tests Exam high nibble + uint8_t nib = (card.uid[1] & 0xf0) >> 4; + switch ( nib ){ + case 1: tagtype = MY_D; break; + case 2: tagtype = (MY_D | MY_D_NFC); break; //notice: we can not currently distinguish between these two + case 3: tagtype = (MY_D_MOVE | MY_D_MOVE_NFC); break; //notice: we can not currently distinguish between these two + } + } + + tagtype |= ul_magic_test(); + if (tagtype == (UNKNOWN | MAGIC)) tagtype = (UL_MAGIC); + return tagtype; + } + + int CmdHF14AMfUInfo(const char *Cmd){ + + uint8_t authlim = 0xff; + uint8_t data[16] = {0x00}; + iso14a_card_select_t card; + int status; + bool errors = false; + bool hasAuthKey = false; + bool locked = false; + bool swapEndian = false; + uint8_t cmdp = 0; + uint8_t dataLen = 0; + uint8_t authenticationkey[16] = {0x00}; + uint8_t *authkeyptr = authenticationkey; + uint8_t *key; + uint8_t pack[4] = {0,0,0,0}; + int len = 0; + char tempStr[50]; + + while(param_getchar(Cmd, cmdp) != 0x00) + { + switch(param_getchar(Cmd, cmdp)) + { + case 'h': + case 'H': + return usage_hf_mfu_info(); + case 'k': + case 'K': + dataLen = param_getstr(Cmd, cmdp+1, tempStr); + if (dataLen == 32 || dataLen == 8) { //ul-c or ev1/ntag key length + errors = param_gethex(tempStr, 0, authenticationkey, dataLen); + dataLen /= 2; // handled as bytes from now on + } else { + PrintAndLog("\nERROR: Key is incorrect length\n"); - errors = true; ++ errors = true; ++ } ++ cmdp += 2; ++ hasAuthKey = true; ++ break; ++ case 'l': ++ case 'L': ++ swapEndian = true; ++ cmdp++; ++ break; ++ default: ++ PrintAndLog("Unknown parameter '%c'", param_getchar(Cmd, cmdp)); ++ errors = true; ++ break; ++ } ++ if(errors) break; ++ } ++ ++ //Validations ++ if(errors) return usage_hf_mfu_info(); ++ ++ TagTypeUL_t tagtype = GetHF14AMfU_Type(); ++ if (tagtype == UL_ERROR) return -1; ++ ++ PrintAndLog("\n--- Tag Information ---------"); ++ PrintAndLog("-------------------------------------------------------------"); ++ ul_print_type(tagtype, 6); ++ ++ // Swap endianness ++ if (swapEndian && hasAuthKey) authkeyptr = SwapEndian64(authenticationkey, dataLen, (dataLen == 16) ? 8 : 4 ); ++ ++ if (!ul_auth_select( &card, tagtype, hasAuthKey, authkeyptr, pack, sizeof(pack))) return -1; ++ ++ // read pages 0,1,2,3 (should read 4pages) ++ status = ul_read(0, data, sizeof(data)); ++ if ( status == -1 ) { ++ ul_switch_off_field(); ++ PrintAndLog("Error: tag didn't answer to READ"); ++ return status; ++ } else if (status == 16) { ++ ul_print_default(data); ++ ndef_print_CC(data+12); ++ } else { ++ locked = true; ++ } ++ ++ // UL_C Specific ++ if ((tagtype & UL_C)) { + - return 0; - } ++ // read pages 0x28, 0x29, 0x2A, 0x2B ++ uint8_t ulc_conf[16] = {0x00}; ++ status = ul_read(0x28, ulc_conf, sizeof(ulc_conf)); ++ if ( status == -1 ){ ++ PrintAndLog("Error: tag didn't answer to READ UL-C"); ++ ul_switch_off_field(); ++ return status; ++ } ++ if (status == 16) ulc_print_configuration(ulc_conf); ++ else locked = true; + - static int ndef_print_CC(uint8_t *data) { - // no NDEF message - if(data[0] != 0xe1) - return -1; ++ if ((tagtype & MAGIC)) { ++ //just read key ++ uint8_t ulc_deskey[16] = {0x00}; ++ status = ul_read(0x2C, ulc_deskey, sizeof(ulc_deskey)); ++ if ( status == -1 ) { ++ ul_switch_off_field(); ++ PrintAndLog("Error: tag didn't answer to READ magic"); ++ return status; ++ } ++ if (status == 16) ulc_print_3deskey(ulc_deskey); + - PrintAndLog("--- NDEF Message"); - PrintAndLog("Capability Container: %s", sprint_hex(data,4) ); - PrintAndLog(" %02X : NDEF Magic Number", data[0]); - PrintAndLog(" %02X : version %d.%d supported by tag", data[1], (data[1] & 0xF0) >> 4, data[1] & 0x0f); - PrintAndLog(" %02X : Physical Memory Size: %d bytes", data[2], (data[2] + 1) * 8); - if ( data[2] == 0x12 ) - PrintAndLog(" %02X : NDEF Memory Size: %d bytes", data[2], 144); - else if ( data[2] == 0x3e ) - PrintAndLog(" %02X : NDEF Memory Size: %d bytes", data[2], 496); - else if ( data[2] == 0x6d ) - PrintAndLog(" %02X : NDEF Memory Size: %d bytes", data[2], 872); - - PrintAndLog(" %02X : %s / %s", data[3], - (data[3] & 0xF0) ? "(RFU)" : "Read access granted without any security", - (data[3] & 0x0F)==0 ? "Write access granted without any security" : (data[3] & 0x0F)==0x0F ? "No write access granted at all" : "(RFU)"); - return 0; - } ++ } else { ++ ul_switch_off_field(); ++ // if we called info with key, just return ++ if ( hasAuthKey ) return 1; + - int ul_print_type(uint32_t tagtype, uint8_t spaces){ - char spc[11] = " "; - spc[10]=0x00; - char *spacer = spc + (10-spaces); ++ // also try to diversify default keys.. look into CmdHF14AMfuGenDiverseKeys ++ PrintAndLog("Trying some default 3des keys"); ++ for (uint8_t i = 0; i < KEYS_3DES_COUNT; ++i ) { ++ key = default_3des_keys[i]; ++ if (ulc_authentication(key, true)) { ++ PrintAndLog("Found default 3des key: "); ++ uint8_t keySwap[16]; ++ memcpy(keySwap, SwapEndian64(key,16,8), 16); ++ ulc_print_3deskey(keySwap); ++ return 1; ++ } ++ } ++ return 1; ++ } ++ } + - if ( tagtype & UL ) - PrintAndLog("%sTYPE : MIFARE Ultralight (MF0ICU1) %s", spacer, (tagtype & MAGIC) ? "" : "" ); - else if ( tagtype & UL_C) - PrintAndLog("%sTYPE : MIFARE Ultralight C (MF0ULC) %s", spacer, (tagtype & MAGIC) ? "" : "" ); - else if ( tagtype & UL_EV1_48) - PrintAndLog("%sTYPE : MIFARE Ultralight EV1 48bytes (MF0UL1101)", spacer); - else if ( tagtype & UL_EV1_128) - PrintAndLog("%sTYPE : MIFARE Ultralight EV1 128bytes (MF0UL2101)", spacer); - else if ( tagtype & NTAG ) - PrintAndLog("%sTYPE : NTAG UNKNOWN", spacer); - else if ( tagtype & NTAG_203 ) - PrintAndLog("%sTYPE : NTAG 203 144bytes (NT2H0301F0DT)", spacer); - else if ( tagtype & NTAG_210 ) - PrintAndLog("%sTYPE : NTAG 210 48bytes (NT2L1011G0DU)", spacer); - else if ( tagtype & NTAG_212 ) - PrintAndLog("%sTYPE : NTAG 212 128bytes (NT2L1211G0DU)", spacer); - else if ( tagtype & NTAG_213 ) - PrintAndLog("%sTYPE : NTAG 213 144bytes (NT2H1311G0DU)", spacer); - else if ( tagtype & NTAG_215 ) - PrintAndLog("%sTYPE : NTAG 215 504bytes (NT2H1511G0DU)", spacer); - else if ( tagtype & NTAG_216 ) - PrintAndLog("%sTYPE : NTAG 216 888bytes (NT2H1611G0DU)", spacer); - else if ( tagtype & NTAG_I2C_1K ) - PrintAndLog("%sTYPE : NTAG I%sC 888bytes (NT3H1101FHK)", spacer, "\xFD"); - else if ( tagtype & NTAG_I2C_2K ) - PrintAndLog("%sTYPE : NTAG I%sC 1904bytes (NT3H1201FHK)", spacer, "\xFD"); - else if ( tagtype & MY_D ) - PrintAndLog("%sTYPE : INFINEON my-d\x99", spacer); - else if ( tagtype & MY_D_NFC ) - PrintAndLog("%sTYPE : INFINEON my-d\x99 NFC", spacer); - else if ( tagtype & MY_D_MOVE ) - PrintAndLog("%sTYPE : INFINEON my-d\x99 move", spacer); - else if ( tagtype & MY_D_MOVE_NFC ) - PrintAndLog("%sTYPE : INFINEON my-d\x99 move NFC", spacer); - else - PrintAndLog("%sTYPE : Unknown %06x", spacer, tagtype); - return 0; - } ++ // do counters and signature first (don't neet auth) + - static int ulc_print_3deskey( uint8_t *data){ - PrintAndLog(" deskey1 [44/0x2C] : %s [%.4s]", sprint_hex(data ,4),data); - PrintAndLog(" deskey1 [45/0x2D] : %s [%.4s]", sprint_hex(data+4 ,4),data+4); - PrintAndLog(" deskey2 [46/0x2E] : %s [%.4s]", sprint_hex(data+8 ,4),data+8); - PrintAndLog(" deskey2 [47/0x2F] : %s [%.4s]", sprint_hex(data+12,4),data+12); - PrintAndLog("\n 3des key : %s", sprint_hex(SwapEndian64(data, 16, 8), 16)); - return 0; - } ++ // ul counters are different than ntag counters ++ if ((tagtype & (UL_EV1_48 | UL_EV1_128))) { ++ if (ulev1_print_counters() != 3) { ++ // failed - re-select ++ if (!ul_auth_select( &card, tagtype, hasAuthKey, authkeyptr, pack, sizeof(pack))) return -1; ++ } ++ } + - static int ulc_print_configuration( uint8_t *data){ - - PrintAndLog("--- UL-C Configuration"); - PrintAndLog(" Higher Lockbits [40/0x28] : %s - %s", sprint_hex(data, 4), printBits(2, data)); - PrintAndLog(" Counter [41/0x29] : %s - %s", sprint_hex(data+4, 4), printBits(2, data+4)); ++ if ((tagtype & (UL_EV1_48 | UL_EV1_128 | NTAG_213 | NTAG_215 | NTAG_216 | NTAG_I2C_1K | NTAG_I2C_2K ))) { ++ uint8_t ulev1_signature[32] = {0x00}; ++ status = ulev1_readSignature( ulev1_signature, sizeof(ulev1_signature)); ++ if ( status == -1 ) { ++ PrintAndLog("Error: tag didn't answer to READ SIGNATURE"); ++ ul_switch_off_field(); ++ return status; ++ } ++ if (status == 32) ulev1_print_signature( ulev1_signature, sizeof(ulev1_signature)); ++ else { ++ // re-select ++ if (!ul_auth_select( &card, tagtype, hasAuthKey, authkeyptr, pack, sizeof(pack))) return -1; ++ } ++ } + - bool validAuth = (data[8] >= 0x03 && data[8] <= 0x30); - if ( validAuth ) - PrintAndLog(" Auth0 [42/0x2A] : %s page %d/0x%02X and above need authentication", sprint_hex(data+8, 4), data[8],data[8] ); - else{ - if ( data[8] == 0){ - PrintAndLog(" Auth0 [42/0x2A] : %s default", sprint_hex(data+8, 4) ); ++ if ((tagtype & (UL_EV1_48 | UL_EV1_128 | NTAG_210 | NTAG_212 | NTAG_213 | NTAG_215 | NTAG_216 | NTAG_I2C_1K | NTAG_I2C_2K))) { ++ uint8_t version[10] = {0x00}; ++ status = ulev1_getVersion(version, sizeof(version)); ++ if ( status == -1 ) { ++ PrintAndLog("Error: tag didn't answer to GETVERSION"); ++ ul_switch_off_field(); ++ return status; ++ } else if (status == 10) { ++ ulev1_print_version(version); + } else { - PrintAndLog(" Auth0 [42/0x2A] : %s auth byte is out-of-range", sprint_hex(data+8, 4) ); ++ locked = true; ++ if (!ul_auth_select( &card, tagtype, hasAuthKey, authkeyptr, pack, sizeof(pack))) return -1; ++ } ++ ++ uint8_t startconfigblock = 0; ++ uint8_t ulev1_conf[16] = {0x00}; ++ // config blocks always are last 4 pages ++ for (uint8_t idx = 0; idx < MAX_UL_TYPES; idx++) ++ if (tagtype & UL_TYPES_ARRAY[idx]) ++ startconfigblock = UL_MEMORY_ARRAY[idx]-3; ++ ++ if (startconfigblock){ // if we know where the config block is... ++ status = ul_read(startconfigblock, ulev1_conf, sizeof(ulev1_conf)); ++ if ( status == -1 ) { ++ PrintAndLog("Error: tag didn't answer to READ EV1"); ++ ul_switch_off_field(); ++ return status; ++ } else if (status == 16) { ++ // save AUTHENTICATION LIMITS for later: ++ authlim = (ulev1_conf[4] & 0x07); ++ ulev1_print_configuration(ulev1_conf, startconfigblock); ++ } ++ } ++ ++ // AUTHLIMIT, (number of failed authentications) ++ // 0 = limitless. ++ // 1-7 = limit. No automatic tries then. ++ // hasAuthKey, if we was called with key, skip test. ++ if ( !authlim && !hasAuthKey ) { ++ PrintAndLog("\n--- Known EV1/NTAG passwords."); ++ len = 0; ++ for (uint8_t i = 0; i < KEYS_PWD_COUNT; ++i ) { ++ key = default_pwd_pack[i]; ++ len = ulev1_requestAuthentication(key, pack, sizeof(pack)); ++ if (len >= 1) { ++ PrintAndLog("Found a default password: %s || Pack: %02X %02X",sprint_hex(key, 4), pack[0], pack[1]); ++ break; ++ } else { ++ if (!ul_auth_select( &card, tagtype, hasAuthKey, authkeyptr, pack, sizeof(pack))) return -1; ++ } ++ } ++ if (len < 1) PrintAndLog("password not known"); + } + } - PrintAndLog(" Auth1 [43/0x2B] : %s %s", - sprint_hex(data+12, 4), - (data[12] & 1) ? "write access restricted": "read and write access restricted" - ); - return 0; ++ ++ ul_switch_off_field(); ++ if (locked) PrintAndLog("\nTag appears to be locked, try using the key to get more info"); ++ PrintAndLog(""); ++ return 1; +} + - static int ulev1_print_configuration( uint8_t *data){ ++// ++// Mifare Ultralight Write Single Block ++// ++int CmdHF14AMfUWrBl(const char *Cmd){ ++ uint8_t blockNo = -1; ++ bool chinese_card = FALSE; ++ uint8_t bldata[16] = {0x00}; ++ UsbCommand resp; + + PrintAndLog("\n--- Tag Configuration"); + + bool strg_mod_en = (data[0] & 2); + uint8_t authlim = (data[4] & 0x07); + bool cfglck = (data[4] & 0x40); + bool prot = (data[4] & 0x80); + uint8_t vctid = data[5]; + + PrintAndLog(" cfg0 [16/0x10]: %s", sprint_hex(data, 4)); + if ( data[3] < 0xff ) + PrintAndLog(" - page %d and above need authentication",data[3]); + else + PrintAndLog(" - pages don't need authentication"); + PrintAndLog(" - strong modulation mode %s", (strg_mod_en) ? "enabled":"disabled"); + PrintAndLog(" cfg1 [17/0x11]: %s", sprint_hex(data+4, 4) ); + if ( authlim == 0) + PrintAndLog(" - Unlimited password attempts"); + else + PrintAndLog(" - Max number of password attempts is %d", authlim); + PrintAndLog(" - user configuration %s", cfglck ? "permanently locked":"writeable"); + PrintAndLog(" - %s access is protected with password", prot ? "read and write":"write"); + PrintAndLog(" %02X - Virtual Card Type Identifier is %s default", vctid, (vctid==0x05)? "":"not"); + PrintAndLog(" PWD [18/0x12]: %s", sprint_hex(data+8, 4)); + PrintAndLog(" PACK [19/0x13]: %s", sprint_hex(data+12, 4)); + return 0; +} + +static int ulev1_print_counters(){ + PrintAndLog("--- Tag Counters"); + uint8_t tear[1] = {0}; + uint8_t counter[3] = {0,0,0}; + uint16_t len = 0; + for ( uint8_t i = 0; i<3; ++i) { + ulev1_readTearing(i,tear,sizeof(tear)); + len = ulev1_readCounter(i,counter, sizeof(counter) ); + if (len == 3) { + PrintAndLog(" [%0d] : %s", i, sprint_hex(counter,3)); + PrintAndLog(" - %02X tearing %s", tear[0], ( tear[0]==0xBD)?"Ok":"failure"); + } + } + return len; +} + +static int ulev1_print_signature( uint8_t *data, uint8_t len){ + PrintAndLog("\n--- Tag Signature"); + //PrintAndLog("IC signature public key name : NXP NTAG21x 2013"); // don't know if there is other NXP public keys.. :( + PrintAndLog("IC signature public key value : 04494e1a386d3d3cfe3dc10e5de68a499b1c202db5b132393e89ed19fe5be8bc61"); + PrintAndLog(" Elliptic curve parameters : secp128r1"); + PrintAndLog(" Tag ECC Signature : %s", sprint_hex(data, len)); + //to do: verify if signature is valid + //PrintAndLog("IC signature status: %s valid", (iseccvalid() )?"":"not"); + return 0; +} + +static int ulev1_print_version(uint8_t *data){ + PrintAndLog("\n--- Tag Version"); + PrintAndLog(" Raw bytes : %s", sprint_hex(data, 8) ); + PrintAndLog(" Vendor ID : %02X, %s", data[1], getTagInfo(data[1])); + PrintAndLog(" Product type : %s" , getProductTypeStr(data[2])); + PrintAndLog(" Product subtype : %02X, %s" , data[3], (data[3]==1) ?"17 pF":"50pF"); + PrintAndLog(" Major version : %02X" , data[4]); + PrintAndLog(" Minor version : %02X" , data[5]); + PrintAndLog(" Size : %s", getUlev1CardSizeStr(data[6])); + PrintAndLog(" Protocol type : %02X" , data[7]); + return 0; +} + +/* +static int ulc_magic_test(){ + // Magic Ultralight test + // Magic UL-C, by observation, + // 1) it seems to have a static nonce response to 0x1A command. + // 2) the deskey bytes is not-zero:d out on as datasheet states. + // 3) UID - changeable, not only, but pages 0-1-2-3. + // 4) use the ul_magic_test ! magic tags answers specially! + int returnValue = UL_ERROR; + iso14a_card_select_t card; + uint8_t nonce1[11] = {0x00}; + uint8_t nonce2[11] = {0x00}; + int status = ul_select(&card); + if ( !status ){ + return UL_ERROR; + } + status = ulc_requestAuthentication(nonce1, sizeof(nonce1)); + if ( status > 0 ) { + status = ulc_requestAuthentication(nonce2, sizeof(nonce2)); + returnValue = ( !memcmp(nonce1, nonce2, 11) ) ? UL_C_MAGIC : UL_C; + } else { + returnValue = UL; + } + ul_switch_off_field(); + return returnValue; +} +*/ +static int ul_magic_test(){ + + // Magic Ultralight tests + // 1) take present UID, and try to write it back. OBSOLETE + // 2) make a wrong length write to page0, and see if tag answers with ACK/NACK: + iso14a_card_select_t card; + if ( !ul_select(&card) ) + return UL_ERROR; + int status = ul_comp_write(0, NULL, 0); + ul_switch_off_field(); + if ( status == 0 ) + return MAGIC; + return 0; +} + - uint32_t GetHF14AMfU_Type(void){ - - TagTypeUL_t tagtype = UNKNOWN; - iso14a_card_select_t card; - uint8_t version[10] = {0x00}; - int status = 0; - int len; - - if (!ul_select(&card)) return UL_ERROR; - - // Ultralight - ATQA / SAK - if ( card.atqa[1] != 0x00 || card.atqa[0] != 0x44 || card.sak != 0x00 ) { - PrintAndLog("Tag is not Ultralight | NTAG | MY-D [ATQA: %02X %02X SAK: %02X]\n", card.atqa[1], card.atqa[0], card.sak); - ul_switch_off_field(); - return UL_ERROR; ++ if (blockNo > MAX_UL_BLOCKS){ ++ PrintAndLog("Error: Maximum number of blocks is 15 for Ultralight Cards!"); ++ return 1; + } + + if ( card.uid[0] != 0x05) { + + len = ulev1_getVersion(version, sizeof(version)); + ul_switch_off_field(); + + switch (len) { + case 0x0A: { + + if ( version[2] == 0x03 && version[6] == 0x0B ) + tagtype = UL_EV1_48; + else if ( version[2] == 0x03 && version[6] != 0x0B ) + tagtype = UL_EV1_128; + else if ( version[2] == 0x04 && version[3] == 0x01 && version[6] == 0x0B ) + tagtype = NTAG_210; + else if ( version[2] == 0x04 && version[3] == 0x01 && version[6] == 0x0E ) + tagtype = NTAG_212; + else if ( version[2] == 0x04 && version[3] == 0x02 && version[6] == 0x0F ) + tagtype = NTAG_213; + else if ( version[2] == 0x04 && version[3] == 0x02 && version[6] == 0x11 ) + tagtype = NTAG_215; + else if ( version[2] == 0x04 && version[3] == 0x02 && version[6] == 0x13 ) + tagtype = NTAG_216; + else if ( version[2] == 0x04 && version[3] == 0x05 && version[6] == 0x13 ) + tagtype = NTAG_I2C_1K; + else if ( version[2] == 0x04 && version[3] == 0x05 && version[6] == 0x15 ) + tagtype = NTAG_I2C_2K; + else if ( version[2] == 0x04 ) + tagtype = NTAG; + + break; + } + case 0x01: tagtype = UL_C; break; + case 0x00: tagtype = UL; break; + case -1 : tagtype = (UL | UL_C | NTAG_203); break; // could be UL | UL_C magic tags + default : tagtype = UNKNOWN; break; + } + // UL vs UL-C vs ntag203 test + if (tagtype & (UL | UL_C | NTAG_203)) { + if ( !ul_select(&card) ) return UL_ERROR; + + // do UL_C check first... + uint8_t nonce[11] = {0x00}; + status = ulc_requestAuthentication(nonce, sizeof(nonce)); + ul_switch_off_field(); + if (status > 1) { + tagtype = UL_C; + } else { + // need to re-select after authentication error + if ( !ul_select(&card) ) return UL_ERROR; + + uint8_t data[16] = {0x00}; + // read page 0x26-0x29 (last valid ntag203 page) + status = ul_read(0x26, data, sizeof(data)); + if ( status <= 1 ) { + tagtype = UL; + } else { + // read page 0x30 (should error if it is a ntag203) + status = ul_read(0x30, data, sizeof(data)); + if ( status <= 1 ){ + tagtype = NTAG_203; + } else { + tagtype = UNKNOWN; + } + } + ul_switch_off_field(); + } + } + } else { + // Infinition MY-D tests Exam high nibble + uint8_t nib = (card.uid[1] & 0xf0) >> 4; + switch ( nib ){ + case 1: tagtype = MY_D; break; + case 2: tagtype = (MY_D | MY_D_NFC); break; //notice: we can not currently distinguish between these two + case 3: tagtype = (MY_D_MOVE | MY_D_MOVE_NFC); break; //notice: we can not currently distinguish between these two + } + } + + + tagtype |= ul_magic_test(); + if (tagtype == (UNKNOWN | MAGIC)) tagtype = (UL_MAGIC); + return tagtype; +} + +int CmdHF14AMfUInfo(const char *Cmd){ + + uint8_t authlim = 0xff; + uint8_t data[16] = {0x00}; + iso14a_card_select_t card; + int status; + bool errors = false; + bool hasAuthKey = false; + bool locked = false; + bool swapEndian = false; + uint8_t cmdp = 0; + uint8_t dataLen = 0; + uint8_t authenticationkey[16] = {0x00}; + uint8_t *authkeyptr = authenticationkey; + uint8_t *key; + uint8_t pack[4] = {0,0,0,0}; + int len = 0; + char tempStr[50]; + + while(param_getchar(Cmd, cmdp) != 0x00) + { + switch(param_getchar(Cmd, cmdp)) + { + case 'h': + case 'H': + return usage_hf_mfu_info(); + case 'k': + case 'K': + dataLen = param_getstr(Cmd, cmdp+1, tempStr); + if (dataLen == 32 || dataLen == 8) { //ul-c or ev1/ntag key length + errors = param_gethex(tempStr, 0, authenticationkey, dataLen); + dataLen /= 2; // handled as bytes from now on + } else { + PrintAndLog("\nERROR: Key is incorrect length\n"); + errors = true; } cmdp += 2; hasAuthKey = true; @@@ -680,35 -680,35 +1162,35 @@@ //Validations if(errors) return usage_hf_mfu_info(); - + TagTypeUL_t tagtype = GetHF14AMfU_Type(); if (tagtype == UL_ERROR) return -1; PrintAndLog("\n--- Tag Information ---------"); PrintAndLog("-------------------------------------------------------------"); ul_print_type(tagtype, 6); - + // Swap endianness if (swapEndian && hasAuthKey) authkeyptr = SwapEndian64(authenticationkey, dataLen, (dataLen == 16) ? 8 : 4 ); - + if (!ul_auth_select( &card, tagtype, hasAuthKey, authkeyptr, pack, sizeof(pack))) return -1; // read pages 0,1,2,3 (should read 4pages) status = ul_read(0, data, sizeof(data)); - if ( status == -1 ) { + if ( status == -1 ){ ul_switch_off_field(); PrintAndLog("Error: tag didn't answer to READ"); return status; } else if (status == 16) { ul_print_default(data); ndef_print_CC(data+12); - } else { + } else { locked = true; } // UL_C Specific - if ((tagtype & UL_C)) { - + if ((tagtype & UL_C)){ + // read pages 0x28, 0x29, 0x2A, 0x2B uint8_t ulc_conf[16] = {0x00}; status = ul_read(0x28, ulc_conf, sizeof(ulc_conf)); @@@ -720,11 -720,11 +1202,11 @@@ if (status == 16) ulc_print_configuration(ulc_conf); else locked = true; - if ((tagtype & MAGIC)) { + if ((tagtype & MAGIC)){ //just read key uint8_t ulc_deskey[16] = {0x00}; status = ul_read(0x2C, ulc_deskey, sizeof(ulc_deskey)); - if ( status == -1 ) { + if ( status == -1 ){ ul_switch_off_field(); PrintAndLog("Error: tag didn't answer to READ magic"); return status; @@@ -735,12 -735,12 +1217,12 @@@ ul_switch_off_field(); // if we called info with key, just return if ( hasAuthKey ) return 1; - + // also try to diversify default keys.. look into CmdHF14AMfuGenDiverseKeys PrintAndLog("Trying some default 3des keys"); - for (uint8_t i = 0; i < KEYS_3DES_COUNT; ++i ) { + for (uint8_t i = 0; i < KEYS_3DES_COUNT; ++i ){ key = default_3des_keys[i]; - if (ulc_authentication(key, true)) { + if (ulc_authentication(key, true)){ PrintAndLog("Found default 3des key: "); uint8_t keySwap[16]; memcpy(keySwap, SwapEndian64(key,16,8), 16); @@@ -765,22 -765,22 +1247,22 @@@ if ((tagtype & (UL_EV1_48 | UL_EV1_128 | NTAG_213 | NTAG_215 | NTAG_216 | NTAG_I2C_1K | NTAG_I2C_2K ))) { uint8_t ulev1_signature[32] = {0x00}; status = ulev1_readSignature( ulev1_signature, sizeof(ulev1_signature)); - if ( status == -1 ) { + if ( status == -1 ){ PrintAndLog("Error: tag didn't answer to READ SIGNATURE"); ul_switch_off_field(); return status; - } + } if (status == 32) ulev1_print_signature( ulev1_signature, sizeof(ulev1_signature)); else { // re-select if (!ul_auth_select( &card, tagtype, hasAuthKey, authkeyptr, pack, sizeof(pack))) return -1; } } - + if ((tagtype & (UL_EV1_48 | UL_EV1_128 | NTAG_210 | NTAG_212 | NTAG_213 | NTAG_215 | NTAG_216 | NTAG_I2C_1K | NTAG_I2C_2K))) { uint8_t version[10] = {0x00}; status = ulev1_getVersion(version, sizeof(version)); - if ( status == -1 ) { + if ( status == -1 ){ PrintAndLog("Error: tag didn't answer to GETVERSION"); ul_switch_off_field(); return status; @@@ -799,18 -799,18 +1281,18 @@@ startconfigblock = UL_MEMORY_ARRAY[idx]-3; if (startconfigblock){ // if we know where the config block is... - status = ul_read(startconfigblock, ulev1_conf, sizeof(ulev1_conf)); - if ( status == -1 ) { - PrintAndLog("Error: tag didn't answer to READ EV1"); - ul_switch_off_field(); - return status; - } else if (status == 16) { - // save AUTHENTICATION LIMITS for later: - authlim = (ulev1_conf[4] & 0x07); - ulev1_print_configuration(ulev1_conf, startconfigblock); + status = ul_read(startconfigblock, ulev1_conf, sizeof(ulev1_conf)); + if ( status == -1 ) { + PrintAndLog("Error: tag didn't answer to READ EV1"); + ul_switch_off_field(); + return status; + } else if (status == 16) { + // save AUTHENTICATION LIMITS for later: + authlim = (ulev1_conf[4] & 0x07); + ulev1_print_configuration(ulev1_conf); } } - + // AUTHLIMIT, (number of failed authentications) // 0 = limitless. // 1-7 = limit. No automatic tries then. @@@ -818,15 -818,15 +1300,15 @@@ if ( !authlim && !hasAuthKey ) { PrintAndLog("\n--- Known EV1/NTAG passwords."); len = 0; - for (uint8_t i = 0; i < KEYS_PWD_COUNT; ++i ) { + for (uint8_t i = 0; i < KEYS_PWD_COUNT; ++i ){ key = default_pwd_pack[i]; - len = ulev1_requestAuthentication(key, pack, sizeof(pack)); + len = ulev1_requestAuthentication(key, pack, sizeof(pack)); if (len >= 1) { PrintAndLog("Found a default password: %s || Pack: %02X %02X",sprint_hex(key, 4), pack[0], pack[1]); break; } else { if (!ul_auth_select( &card, tagtype, hasAuthKey, authkeyptr, pack, sizeof(pack))) return -1; - } + } } if (len < 1) PrintAndLog("password not known"); } @@@ -839,242 -839,105 +1321,241 @@@ } // -// Mifare Ultralight Write Single Block +// Write Single Block // int CmdHF14AMfUWrBl(const char *Cmd){ - uint8_t blockNo = -1; - bool chinese_card = FALSE; - uint8_t bldata[16] = {0x00}; - UsbCommand resp; - char cmdp = param_getchar(Cmd, 0); - if (strlen(Cmd) < 3 || cmdp == 'h' || cmdp == 'H') { - PrintAndLog("Usage: hf mfu wrbl [w]"); - PrintAndLog(" [block number]"); - PrintAndLog(" [block data] - (8 hex symbols)"); - PrintAndLog(" [w] - Chinese magic ultralight tag"); - PrintAndLog(""); - PrintAndLog(" sample: hf mfu wrbl 0 01020304"); - PrintAndLog(""); - return 0; - } - - blockNo = param_get8(Cmd, 0); + int blockNo = -1; + bool errors = false; + bool hasAuthKey = false; + bool hasPwdKey = false; + bool swapEndian = false; - if (blockNo > MAX_UL_BLOCKS){ - PrintAndLog("Error: Maximum number of blocks is 15 for Ultralight Cards!"); - return 1; - } + uint8_t cmdp = 0; + uint8_t keylen = 0; + uint8_t blockdata[20] = {0x00}; + uint8_t data[16] = {0x00}; + uint8_t authenticationkey[16] = {0x00}; + uint8_t *authkeyptr = authenticationkey; - if (param_gethex(Cmd, 1, bldata, 8)) { - PrintAndLog("Block data must include 8 HEX symbols"); - return 1; + // starting with getting tagtype + TagTypeUL_t tagtype = GetHF14AMfU_Type(); + if (tagtype == UL_ERROR) return -1; + + while(param_getchar(Cmd, cmdp) != 0x00) + { + switch(param_getchar(Cmd, cmdp)) + { + case 'h': + case 'H': + return usage_hf_mfu_wrbl(); + case 'k': + case 'K': + // EV1/NTAG size key + keylen = param_gethex(Cmd, cmdp+1, data, 8); + if ( !keylen ) { + memcpy(authenticationkey, data, 4); + cmdp += 2; + hasPwdKey = true; + break; + } + // UL-C size key + keylen = param_gethex(Cmd, cmdp+1, data, 32); + if (!keylen){ + memcpy(authenticationkey, data, 16); + cmdp += 2; + hasAuthKey = true; + break; + } + PrintAndLog("\nERROR: Key is incorrect length\n"); + errors = true; + break; + case 'b': + case 'B': + blockNo = param_get8(Cmd, cmdp+1); + + uint8_t maxblockno = 0; + for (uint8_t idx = 0; idx < MAX_UL_TYPES; idx++){ + if (tagtype & UL_TYPES_ARRAY[idx]) + maxblockno = UL_MEMORY_ARRAY[idx]+1; + } + + if (blockNo < 0) { + PrintAndLog("Wrong block number"); + errors = true; + } + if (blockNo > maxblockno){ + PrintAndLog("block number to large. Max block is %u/0x%02X \n", maxblockno,maxblockno); + errors = true; + } + cmdp += 2; + break; + case 'l': + case 'L': + swapEndian = true; + cmdp++; + break; + case 'd': + case 'D': + if ( param_gethex(Cmd, cmdp+1, blockdata, 8) ) { + PrintAndLog("Block data must include 8 HEX symbols"); + errors = true; + break; + } + cmdp += 2; + break; + default: + PrintAndLog("Unknown parameter '%c'", param_getchar(Cmd, cmdp)); + errors = true; + break; + } + //Validations + if(errors) return usage_hf_mfu_wrbl(); } + + if ( blockNo == -1 ) return usage_hf_mfu_wrbl(); + + // Swap endianness + if (swapEndian && hasAuthKey) authkeyptr = SwapEndian64(authenticationkey, 16, 8); + if (swapEndian && hasPwdKey) authkeyptr = SwapEndian64(authenticationkey, 4, 4); + + + if ( blockNo <= 3) + PrintAndLog("Special Block: %0d (0x%02X) [ %s]", blockNo, blockNo, sprint_hex(blockdata, 4)); + else + PrintAndLog("Block: %0d (0x%02X) [ %s]", blockNo, blockNo, sprint_hex(blockdata, 4)); + - if (strchr(Cmd,'w') != 0 || strchr(Cmd,'W') != 0 ) { - chinese_card = TRUE; + + //Send write Block + UsbCommand c = {CMD_MIFAREU_WRITEBL, {blockNo}}; + memcpy(c.d.asBytes,blockdata,4); + + if ( hasAuthKey ){ + c.arg[1] = 1; + memcpy(c.d.asBytes+4,authkeyptr,16); + } + else if ( hasPwdKey ) { + c.arg[1] = 2; + memcpy(c.d.asBytes+4,authkeyptr,4); } - if ( blockNo <= 3) { - if (!chinese_card){ - PrintAndLog("Access Denied"); - } else { - PrintAndLog("--specialblock no:%02x", 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"); - } - } + SendCommand(&c); + UsbCommand resp; + if (WaitForResponseTimeout(CMD_ACK,&resp,1500)) { + uint8_t isOK = resp.arg[0] & 0xff; + PrintAndLog("isOk:%02x", isOK); } else { - PrintAndLog("--block no:%02x", 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"); - } + PrintAndLog("Command execute timeout"); } + return 0; } - // -// Mifare Ultralight Read Single Block +// Read Single Block // int CmdHF14AMfURdBl(const char *Cmd){ - UsbCommand resp; - uint8_t blockNo = -1; - char cmdp = param_getchar(Cmd, 0); + int blockNo = -1; + bool errors = false; + bool hasAuthKey = false; + bool hasPwdKey = false; + bool swapEndian = false; + uint8_t cmdp = 0; + uint8_t keylen = 0; + uint8_t data[16] = {0x00}; + uint8_t authenticationkey[16] = {0x00}; + uint8_t *authkeyptr = authenticationkey; + + // starting with getting tagtype + TagTypeUL_t tagtype = GetHF14AMfU_Type(); + if (tagtype == UL_ERROR) return -1; - if (strlen(Cmd) < 1 || cmdp == 'h' || cmdp == 'H') { - PrintAndLog("Usage: hf mfu rdbl "); - PrintAndLog(" sample: hfu mfu rdbl 0"); - return 0; - } - - blockNo = param_get8(Cmd, 0); - - if (blockNo > MAX_UL_BLOCKS){ - PrintAndLog("Error: Maximum number of blocks is 15 for Ultralight"); - return 1; + while(param_getchar(Cmd, cmdp) != 0x00) + { + switch(param_getchar(Cmd, cmdp)) + { + case 'h': + case 'H': + return usage_hf_mfu_rdbl(); + case 'k': + case 'K': + // EV1/NTAG size key + keylen = param_gethex(Cmd, cmdp+1, data, 8); + if ( !keylen ) { + memcpy(authenticationkey, data, 4); + cmdp += 2; + hasPwdKey = true; + break; + } + // UL-C size key + keylen = param_gethex(Cmd, cmdp+1, data, 32); + if (!keylen){ + memcpy(authenticationkey, data, 16); + cmdp += 2; + hasAuthKey = true; + break; + } + PrintAndLog("\nERROR: Key is incorrect length\n"); + errors = true; + break; + case 'b': + case 'B': + blockNo = param_get8(Cmd, cmdp+1); + + uint8_t maxblockno = 0; + for (uint8_t idx = 0; idx < MAX_UL_TYPES; idx++){ + if (tagtype & UL_TYPES_ARRAY[idx]) + maxblockno = UL_MEMORY_ARRAY[idx]+1; + } + + if (blockNo < 0) { + PrintAndLog("Wrong block number"); + errors = true; + } + if (blockNo > maxblockno){ + PrintAndLog("block number to large. Max block is %u/0x%02X \n", maxblockno,maxblockno); + errors = true; + } + cmdp += 2; + break; + case 'l': + case 'L': + swapEndian = true; + cmdp++; + break; + default: + PrintAndLog("Unknown parameter '%c'", param_getchar(Cmd, cmdp)); + errors = true; + break; + } + //Validations + if(errors) return usage_hf_mfu_rdbl(); } -- + if ( blockNo == -1 ) return usage_hf_mfu_rdbl(); + + // Swap endianness + if (swapEndian && hasAuthKey) authkeyptr = SwapEndian64(authenticationkey, 16, 8); + if (swapEndian && hasPwdKey) authkeyptr = SwapEndian64(authenticationkey, 4, 4); + + //Read Block UsbCommand c = {CMD_MIFAREU_READBL, {blockNo}}; + if ( hasAuthKey ){ + c.arg[1] = 1; + memcpy(c.d.asBytes,authkeyptr,16); + } + else if ( hasPwdKey ) { + c.arg[1] = 2; + memcpy(c.d.asBytes,authkeyptr,4); + } + SendCommand(&c); - UsbCommand resp; + - if (WaitForResponseTimeout(CMD_ACK,&resp,1500)) { uint8_t isOK = resp.arg[0] & 0xff; if (isOK) { uint8_t *data = resp.d.asBytes; - PrintAndLog("Block: %0d (0x%02X) [ %s]", (int)blockNo, blockNo, sprint_hex(data, 4)); + PrintAndLog("Block: %0d (0x%02X) [ %s]", blockNo, blockNo, sprint_hex(data, 4)); } else { PrintAndLog("Failed reading block: (%02x)", isOK); @@@ -1082,6 -945,7 +1563,7 @@@ } else { PrintAndLog("Command execute time-out"); } + return 0; } @@@ -1124,44 -988,14 +1606,44 @@@ int usage_hf_mfu_dump(void) return 0; } +int usage_hf_mfu_rdbl(void) { + PrintAndLog("Read a block and print. It autodetects card type.\n"); + PrintAndLog("Usage: hf mfu rdbl b k l\n"); + PrintAndLog(" Options:"); + PrintAndLog(" b : block to read"); + PrintAndLog(" k : (optional) key for authentication [UL-C 16bytes, EV1/NTAG 4bytes]"); + PrintAndLog(" l : (optional) swap entered key's endianness"); + PrintAndLog(""); + PrintAndLog(" sample : hf mfu rdbl b 0"); + PrintAndLog(" : hf mfu rdbl b 0 k 00112233445566778899AABBCCDDEEFF"); + PrintAndLog(" : hf mfu rdbl b 0 k AABBCCDDD\n"); + return 0; +} + +int usage_hf_mfu_wrbl(void) { + PrintAndLog("Write a block. It autodetects card type.\n"); + PrintAndLog("Usage: hf mfu wrbl b d k l\n"); + PrintAndLog(" Options:"); + PrintAndLog(" b : block to write"); + PrintAndLog(" d : block data - (8 hex symbols)"); + PrintAndLog(" k : (optional) key for authentication [UL-C 16bytes, EV1/NTAG 4bytes]"); + PrintAndLog(" l : (optional) swap entered key's endianness"); + PrintAndLog(""); + PrintAndLog(" sample : hf mfu wrbl b 0 d 01234567"); + PrintAndLog(" : hf mfu wrbl b 0 d 01234567 k AABBCCDDD\n"); + return 0; +} + // // Mifare Ultralight / Ultralight-C / Ultralight-EV1 // Read and Dump Card Contents, using auto detection of tag size. +// +// TODO: take a password to read UL-C / UL-EV1 tags. int CmdHF14AMfUDump(const char *Cmd){ FILE *fout; char filename[FILE_PATH_SIZE] = {0x00}; - char * fnameptr = filename; + char *fnameptr = filename; uint8_t *lockbytes_t = NULL; uint8_t lockbytes[2] = {0x00}; uint8_t *lockbytes_t2 = NULL; @@@ -1173,10 -1007,10 +1655,10 @@@ int i = 0; int Pages = 16; bool tmplockbit = false; - uint8_t dataLen=0; - uint8_t cmdp =0; + uint8_t dataLen = 0; + uint8_t cmdp = 0; uint8_t authenticationkey[16] = {0x00}; - uint8_t *authKeyPtr = authenticationkey; + uint8_t *authKeyPtr = authenticationkey; size_t fileNlen = 0; bool errors = false; bool swapEndian = false; @@@ -1238,13 -1072,13 +1720,13 @@@ //Validations if(errors) return usage_hf_mfu_dump(); - + if (swapEndian && hasAuthKey) authKeyPtr = SwapEndian64(authenticationkey, dataLen, (dataLen == 16) ? 8 : 4); TagTypeUL_t tagtype = GetHF14AMfU_Type(); if (tagtype == UL_ERROR) return -1; - + if (!manualPages) for (uint8_t idx = 0; idx < MAX_UL_TYPES; idx++) if (tagtype & UL_TYPES_ARRAY[idx]) @@@ -1253,7 -1087,7 +1735,7 @@@ ul_print_type(tagtype, 0); PrintAndLog("Reading tag memory..."); UsbCommand c = {CMD_MIFAREU_READCARD, {startPage,Pages}}; - if ( hasAuthKey ) { + if ( hasAuthKey ) { if (tagtype & UL_C) c.arg[2] = 1; //UL_C auth else @@@ -1263,7 -1097,7 +1745,7 @@@ } SendCommand(&c); UsbCommand resp; - if (!WaitForResponseTimeout(CMD_ACK,&resp,1500)) { + if (!WaitForResponseTimeout(CMD_ACK, &resp,1500)) { PrintAndLog("Command execute time-out"); return 1; } @@@ -1283,14 -1117,14 +1765,14 @@@ Pages = bufferSize/4; // Load lock bytes. int j = 0; - + lockbytes_t = data + 8; lockbytes[0] = lockbytes_t[2]; lockbytes[1] = lockbytes_t[3]; for(j = 0; j < 16; j++){ bit[j] = lockbytes[j/8] & ( 1 <<(7-j%8)); - } - + } + // Load bottom lockbytes if available // TODO -- FIGURE OUT LOCK BYTES FOR TO EV1 and/or NTAG if ( Pages == 44 ) { @@@ -1304,15 -1138,20 +1786,20 @@@ // add keys to block dump if (hasAuthKey) { - if (!swapEndian) { + if (!swapEndian){ authKeyPtr = SwapEndian64(authenticationkey, dataLen, (dataLen == 16) ? 8 : 4); - memcpy(data + Pages*4, authKeyPtr, dataLen); } else { - memcpy(data + Pages*4, authenticationkey, dataLen); + authKeyPtr = authenticationkey; + } + + if (tagtype & UL_C){ //add 4 pages + memcpy(data + Pages*4, authKeyPtr, dataLen); + Pages += dataLen/4; + } else { // 2nd page from end + memcpy(data + (Pages*4) - 8, authenticationkey, dataLen); } - Pages += dataLen/4; //not sure output is in correct location for all tag types. } - + for (i = 0; i < Pages; ++i) { if ( i < 3 ) { PrintAndLog("Block %02x:%s ", i,sprint_hex(data + i * 4, 4)); @@@ -1320,11 -1159,11 +1807,11 @@@ } switch(i){ case 3: tmplockbit = bit[4]; break; - case 4: tmplockbit = bit[3]; break; - case 5: tmplockbit = bit[2]; break; - case 6: tmplockbit = bit[1]; break; - case 7: tmplockbit = bit[0]; break; - case 8: tmplockbit = bit[15]; break; + case 4: tmplockbit = bit[3]; break; + case 5: tmplockbit = bit[2]; break; + case 6: tmplockbit = bit[1]; break; + case 7: tmplockbit = bit[0]; break; + case 8: tmplockbit = bit[15]; break; case 9: tmplockbit = bit[14]; break; case 10: tmplockbit = bit[13]; break; case 11: tmplockbit = bit[12]; break; @@@ -1343,7 -1182,7 +1830,7 @@@ case 24: case 25: case 26: - case 27: tmplockbit = bit2[4]; break; + case 27: tmplockbit = bit2[4]; break; case 28: case 29: case 30: @@@ -1362,21 -1201,21 +1849,21 @@@ case 43: tmplockbit = bit2[9]; break; //auth1 default: break; } - PrintAndLog("Block %02x:%s [%d] {%.4s}", i, sprint_hex(data + i * 4, 4), tmplockbit, data+i*4); - } - + PrintAndLog("Block %02X:%s [%d] {%.4s}", i, sprint_hex(data + i * 4, 4), tmplockbit, data+i*4); + } + // user supplied filename? if (fileNlen < 1) { // UID = data 0-1-2 4-5-6-7 (skips a beat) sprintf(fnameptr,"%02X%02X%02X%02X%02X%02X%02X.bin", - data[0], data[1], data[2], data[4], data[5], data[6], data[7]); + data[0],data[1], data[2], data[4],data[5],data[6], data[7]); } else { sprintf(fnameptr + fileNlen,".bin"); } if ((fout = fopen(filename,"wb")) == NULL) { PrintAndLog("Could not create file name %s", filename); - return 1; + return 1; } fwrite( data, 1, Pages*4, fout ); fclose(fout); @@@ -1394,7 -1233,7 +1881,7 @@@ // int CmdHF14AMfucAuth(const char *Cmd){ - uint8_t keyNo = 0; + uint8_t keyNo = 3; bool errors = false; char cmdp = param_getchar(Cmd, 0); @@@ -1428,7 -1267,7 +1915,7 @@@ PrintAndLog("Authentication successful. 3des key: %s",sprint_hex(key, 16)); else PrintAndLog("Authentication failed"); - + return 0; } @@@ -1529,15 -1368,151 +2016,16 @@@ int CmdTestDES(const char * cmd } **/ -// -// Ultralight C Read Single Block -// -int CmdHF14AMfUCRdBl(const char *Cmd) -{ - UsbCommand resp; - bool hasPwd = FALSE; - uint8_t blockNo = -1; - uint8_t key[16]; - char cmdp = param_getchar(Cmd, 0); - - if (strlen(Cmd) < 1 || cmdp == 'h' || cmdp == 'H') { - PrintAndLog("Usage: hf mfu crdbl "); - PrintAndLog(""); - PrintAndLog("sample: hf mfu crdbl 0"); - PrintAndLog(" hf mfu crdbl 0 00112233445566778899AABBCCDDEEFF"); - return 0; - } - - blockNo = param_get8(Cmd, 0); - if (blockNo < 0) { - PrintAndLog("Wrong block number"); - return 1; - } - - if (blockNo > MAX_ULC_BLOCKS ){ - PrintAndLog("Error: Maximum number of blocks is 47 for Ultralight-C"); - return 1; - } - - // key - if ( strlen(Cmd) > 3){ - if (param_gethex(Cmd, 1, key, 32)) { - PrintAndLog("Key must include %d HEX symbols", 32); - return 1; - } else { - hasPwd = TRUE; - } - } - - //Read Block - UsbCommand c = {CMD_MIFAREU_READBL, {blockNo}}; - if ( hasPwd ) { - c.arg[1] = 1; - memcpy(c.d.asBytes,key,16); - } - SendCommand(&c); - - if (WaitForResponseTimeout(CMD_ACK,&resp,1500)) { - uint8_t isOK = resp.arg[0] & 0xff; - if (isOK) { - uint8_t *data = resp.d.asBytes; - PrintAndLog("Block: %0d (0x%02X) [ %s]", (int)blockNo, blockNo, sprint_hex(data, 4)); - } - else { - PrintAndLog("Failed reading block: (%02x)", isOK); - } - } else { - PrintAndLog("Command execute time-out"); - } - return 0; -} - -// -// Mifare Ultralight C Write Single Block -// -int CmdHF14AMfUCWrBl(const char *Cmd){ - - uint8_t blockNo = -1; - bool chinese_card = FALSE; - uint8_t bldata[16] = {0x00}; - UsbCommand resp; - - char cmdp = param_getchar(Cmd, 0); - - if (strlen(Cmd) < 3 || cmdp == 'h' || cmdp == 'H') { - PrintAndLog("Usage: hf mfu cwrbl [w]"); - PrintAndLog(" [block number]"); - PrintAndLog(" [block data] - (8 hex symbols)"); - PrintAndLog(" [w] - Chinese magic ultralight tag"); - PrintAndLog(""); - PrintAndLog(" sample: hf mfu cwrbl 0 01020304"); - PrintAndLog(""); - return 0; - } - - blockNo = param_get8(Cmd, 0); - if (blockNo > MAX_ULC_BLOCKS ){ - PrintAndLog("Error: Maximum number of blocks is 47 for Ultralight-C Cards!"); - return 1; - } - - if (param_gethex(Cmd, 1, bldata, 8)) { - PrintAndLog("Block data must include 8 HEX symbols"); - return 1; - } - - if (strchr(Cmd,'w') != 0 || strchr(Cmd,'W') != 0 ) { - chinese_card = TRUE; - } - - if ( blockNo <= 3 ) { - if (!chinese_card){ - PrintAndLog("Access Denied"); - return 1; - } else { - PrintAndLog("--Special block no: 0x%02x", 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"); - return 1; - } - } - } else { - PrintAndLog("--Block no : 0x%02x", 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"); - return 1; - } - } - return 0; -} - // // Mifare Ultralight C - Set password // int CmdHF14AMfucSetPwd(const char *Cmd){ - uint8_t pwd[16] = {0x00}; + uint8_t pwd[16] = {0x00}; ++ uint8_t key[16]; char cmdp = param_getchar(Cmd, 0); -- ++ if (strlen(Cmd) == 0 || cmdp == 'h' || cmdp == 'H') { PrintAndLog("Usage: hf mfu setpwd "); PrintAndLog(" [password] - (32 hex symbols)"); @@@ -1551,6 -1526,6 +2039,11 @@@ PrintAndLog("Password must include 32 HEX symbols"); return 1; } ++ ++ if (blockNo > MAX_ULC_BLOCKS ){ ++ PrintAndLog("Error: Maximum number of blocks is 47 for Ultralight-C"); ++ return 1; ++ } UsbCommand c = {CMD_MIFAREUC_SETPWD}; memcpy( c.d.asBytes, pwd, 16); @@@ -1607,7 -1582,7 +2100,7 @@@ int CmdHF14AMfucSetUid(const char *Cmd) PrintAndLog("Command execute timeout"); return 2; } -- ++ // save old block2. uint8_t oldblock2[4] = {0x00}; memcpy(resp.d.asBytes, oldblock2, 4); @@@ -1624,7 -1599,7 +2117,7 @@@ PrintAndLog("Command execute timeout"); return 3; } -- ++ // block 1. c.arg[0] = 1; c.d.asBytes[0] = uid[3]; @@@ -1760,8 -1735,10 +2253,8 @@@ static command_t CommandTable[] {"dbg", CmdHF14AMfDbg, 0, "Set default debug mode"}, {"info", CmdHF14AMfUInfo, 0, "Tag information"}, {"dump", CmdHF14AMfUDump, 0, "Dump Ultralight / Ultralight-C tag to binary file"}, - {"rdbl", CmdHF14AMfURdBl, 0, "Read block - Ultralight"}, - {"wrbl", CmdHF14AMfUWrBl, 0, "Write block - Ultralight"}, - {"crdbl", CmdHF14AMfUCRdBl, 0, "Read block - Ultralight C"}, - {"cwrbl", CmdHF14AMfUCWrBl, 0, "Write block - Ultralight C"}, + {"rdbl", CmdHF14AMfURdBl, 0, "Read block"}, + {"wrbl", CmdHF14AMfUWrBl, 0, "Write block"}, {"cauth", CmdHF14AMfucAuth, 0, "Authentication - Ultralight C"}, {"setpwd", CmdHF14AMfucSetPwd, 1, "Set 3des password - Ultralight-C"}, {"setuid", CmdHF14AMfucSetUid, 1, "Set UID - MAGIC tags only"}, diff --combined client/cmdhfmfu.h index d4d3070a,83f28403..4ec48ff9 --- a/client/cmdhfmfu.h +++ b/client/cmdhfmfu.h @@@ -4,24 -4,25 +4,24 @@@ #ifndef CMDHFMFU_H__ #define CMDHFMFU_H__ -//standard ultralight int CmdHF14AMfUWrBl(const char *Cmd); int CmdHF14AMfURdBl(const char *Cmd); //Crypto Cards -int CmdHF14AMfUCRdBl(const char *Cmd); -int CmdHF14AMfUCRdCard(const char *Cmd); int CmdHF14AMfucAuth(const char *Cmd); //general stuff int CmdHF14AMfUDump(const char *Cmd); int CmdHF14AMfUInfo(const char *Cmd); -uint32_t GetHF14AMfU_Type(void); +uint32_t GetHF14AMfU_Type(void); int ul_print_type(uint32_t tagtype, uint8_t spacer); void ul_switch_off_field(void); int usage_hf_mfu_dump(void); int usage_hf_mfu_info(void); +int usage_hf_mfu_rdbl(void); +int usage_hf_mfu_wrbl(void); int CmdHFMFUltra(const char *Cmd); @@@ -32,9 -33,9 +32,9 @@@ typedef enum TAGTYPE_UL UL_EV1_48 = 0x000004, UL_EV1_128 = 0x000008, NTAG = 0x000010, - NTAG_203 = 0x000020, - NTAG_210 = 0x000040, - NTAG_212 = 0x000080, + NTAG_203 = 0x000020, + NTAG_210 = 0x000040, + NTAG_212 = 0x000080, NTAG_213 = 0x000100, NTAG_215 = 0x000200, NTAG_216 = 0x000400, @@@ -42,8 -43,8 +42,8 @@@ MY_D_NFC = 0x001000, MY_D_MOVE = 0x002000, MY_D_MOVE_NFC = 0x004000, - NTAG_I2C_1K = 0x008000, - NTAG_I2C_2K = 0x010000, + NTAG_I2C_1K = 0x008000, + NTAG_I2C_2K = 0x010000, MAGIC = 0x020000, UL_MAGIC = UL | MAGIC, UL_C_MAGIC = UL_C | MAGIC, diff --combined client/lualibs/html_dumplib.lua index bd8e6d0c,566128f7..17096063 --- a/client/lualibs/html_dumplib.lua +++ b/client/lualibs/html_dumplib.lua @@@ -192,9 -192,7 +192,9 @@@ en return { convert_bin_to_html = convert_bin_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, + SaveAsBinary = save_BIN, + SaveAsText = save_TEXT, + SaveAsBinary = save_BIN, SaveAsText = save_TEXT, } diff --combined client/nonce2key/crapto1.c index 1d7441c7,1015e27a..13c4c063 --- a/client/nonce2key/crapto1.c +++ b/client/nonce2key/crapto1.c @@@ -1,21 -1,21 +1,21 @@@ /* crapto1.c - 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 Street, Fifth Floor, - Boston, MA 02110-1301, US$ - - Copyright (C) 2008-2008 bla + 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 Street, Fifth Floor, + Boston, MA 02110-1301, US$ + + Copyright (C) 2008-2008 bla */ #include "crapto1.h" #include @@@ -24,9 -24,9 +24,9 @@@ static uint8_t filterlut[1 << 20]; static void __attribute__((constructor)) fill_lut() { - uint32_t i; - for(i = 0; i < 1 << 20; ++i) - filterlut[i] = filter(i); + uint32_t i; + for(i = 0; i < 1 << 20; ++i) + filterlut[i] = filter(i); } #define filter(x) (filterlut[(x) & 0xfffff]) #endif @@@ -147,7 -147,7 +147,7 @@@ extend_table(uint32_t *tbl, uint32_t ** *p ^= in; } else { // drop *p-- = *(*end)--; - } + } } } @@@ -209,7 -209,7 +209,7 @@@ recover(uint32_t *o_head, uint32_t *o_t for (int i = bucket_info.numbuckets - 1; i >= 0; i--) { sl = recover(bucket_info.bucket_info[1][i].head, bucket_info.bucket_info[1][i].tail, oks, - bucket_info.bucket_info[0][i].head, bucket_info.bucket_info[0][i].tail, eks, + bucket_info.bucket_info[0][i].head, bucket_info.bucket_info[0][i].tail, eks, rem, sl, in, bucket); } @@@ -251,7 -251,7 +251,6 @@@ struct Crypto1State* lfsr_recovery32(ui } } -- // initialize statelists: add all possible states which would result into the rightmost 2 bits of the keystream for(i = 1 << 20; i >= 0; --i) { if(filter(i) == (oks & 1)) @@@ -272,9 -272,9 +271,7 @@@ in = (in >> 16 & 0xff) | (in << 16) | (in & 0xff00); // Byte swapping -- recover(odd_head, odd_tail, oks, -- even_head, even_tail, eks, 11, statelist, in << 1, bucket); -- ++ recover(odd_head, odd_tail, oks, even_head, even_tail, eks, 11, statelist, in << 1, bucket); out: free(odd_head); @@@ -484,7 -484,7 +481,7 @@@ uint32_t *lfsr_prefix_ks(uint8_t ks[8] */ static struct Crypto1State* brute_top(uint32_t prefix, uint32_t rresp, unsigned char parities[8][8], - uint32_t odd, uint32_t even, struct Crypto1State* sl, uint8_t no_chk) + uint32_t odd, uint32_t even, struct Crypto1State* sl, uint8_t no_chk) { struct Crypto1State s; uint32_t ks1, nr, ks2, rr, ks3, good, c; @@@ -536,8 -536,8 +533,7 @@@ * It returns a zero terminated list of possible cipher states after the * tag nonce was fed in */ --struct Crypto1State* --lfsr_common_prefix(uint32_t pfx, uint32_t rr, uint8_t ks[8], uint8_t par[8][8], uint8_t no_par) ++struct Crypto1State* lfsr_common_prefix(uint32_t pfx, uint32_t rr, uint8_t ks[8], uint8_t par[8][8], uint8_t no_par) { struct Crypto1State *statelist, *s; uint32_t *odd, *even, *o, *e, top; @@@ -548,10 -548,10 +544,10 @@@ statelist = malloc((sizeof *statelist) << 21); //how large should be? if(!statelist || !odd || !even) { -- free(statelist); -- free(odd); -- free(even); -- return 0; ++ free(statelist); ++ free(odd); ++ free(even); ++ return 0; } s = statelist; @@@ -571,3 -571,3 +567,66 @@@ return statelist; } ++ ++/* ++struct Crypto1State* lfsr_common_prefix(uint32_t pfx, uint32_t rr, uint8_t ks[8], uint8_t par[8][8], uint8_t no_par, uint32_t nt, uint32_t uid) ++{ ++ long long int amount = 0; ++ struct Crypto1State *statelist, *s; ++ uint32_t *odd, *even, *o, *e, top; ++ ++ odd = lfsr_prefix_ks(ks, 1); ++ even = lfsr_prefix_ks(ks, 0); ++ ++ s = statelist = malloc((sizeof *statelist) << 20); ++ if(!s || !odd || !even) { ++ free(odd); ++ free(even); ++ free(statelist); ++ return 0; ++ } ++ ++ char filename[50] = "archivo.txt"; ++ sprintf(filename, "logs/%x.txt", nt); ++ PrintAndLog("Name: %s\n", filename); ++ FILE *file = fopen(filename,"w+"); ++ if ( !file ) { ++ s->odd = s->even = 0; ++ free(odd); ++ free(even); ++ PrintAndLog("Failed to create file"); ++ return 0; ++ } ++ PrintAndLog("Creating file... "); ++ uint32_t xored = uid^nt; ++ ++ int lastOdd = 0; ++ for(o = odd; *o + 1; ++o) ++ for(e = even; *e + 1; ++e) ++ for(top = 0; top < 64; ++top) { ++ *o += 1 << 21; ++ *e += (!(top & 7) + 1) << 21; ++ ++ //added by MG ++ if(lastOdd != statelist->odd){ ++ // Here I create a temporal crypto1 state, ++ // where I load the odd and even state and work with it, ++ // in order not to interfere with regular mechanism, This is what I save to file ++ struct Crypto1State *state; ++ lastOdd = state->odd = statelist->odd; state->even = statelist->even; ++ lfsr_rollback_word(state,xored,0); ++ fprintf(file,"%x %x \n",state->odd,state->even); ++ amount++; ++ } ++ //s = check_pfx_parity(pfx, rr, par, *o, *e, s); //This is not useful at all when attacking chineese cards ++ s = brute_top(pfx, rr, par, *o, *e, s, no_par); ++ } ++ ++ PrintAndLog("File created, amount %u\n",amount); ++ fclose(file); ++ s->odd = s->even = 0; ++ free(odd); ++ free(even); ++ return statelist; ++} ++ */ diff --combined client/scripting.c index 880b7cb2,152fd9d4..9e643932 --- a/client/scripting.c +++ b/client/scripting.c @@@ -30,34 -30,34 +30,34 @@@ */ static int l_SendCommand(lua_State *L){ - /* - * - The SendCommand (native) expects the following structure: - - typedef struct { - uint64_t cmd; //8 bytes - uint64_t arg[3]; // 8*3 bytes = 24 bytes - union { - uint8_t asBytes[USB_CMD_DATA_SIZE]; // 1 byte * 512 = 512 bytes (OR) - uint32_t asDwords[USB_CMD_DATA_SIZE/4]; // 4 byte * 128 = 512 bytes - } d; - } PACKED UsbCommand; - - ==> A 544 byte buffer will do. - **/ - //Pop cmd - size_t size; - const char *data = luaL_checklstring(L, 1, &size); - if(size != sizeof(UsbCommand)) - { - printf("Got data size %d, expected %d" , (int) size,(int) sizeof(UsbCommand)); - lua_pushstring(L,"Wrong data size"); - return 1; - } + /* + * + The SendCommand (native) expects the following structure: + + typedef struct { + uint64_t cmd; //8 bytes + uint64_t arg[3]; // 8*3 bytes = 24 bytes + union { + uint8_t asBytes[USB_CMD_DATA_SIZE]; // 1 byte * 512 = 512 bytes (OR) + uint32_t asDwords[USB_CMD_DATA_SIZE/4]; // 4 byte * 128 = 512 bytes + } d; + } PACKED UsbCommand; + + ==> A 544 byte buffer will do. + **/ + //Pop cmd + size_t size; + const char *data = luaL_checklstring(L, 1, &size); + if(size != sizeof(UsbCommand)) + { + printf("Got data size %d, expected %d" , (int) size,(int) sizeof(UsbCommand)); + lua_pushstring(L,"Wrong data size"); + return 1; + } // UsbCommand c = (*data); - SendCommand((UsbCommand* )data); - return 0; // no return values + SendCommand((UsbCommand* )data); + return 0; // no return values } /** * @brief The following params expected: @@@ -68,105 -68,105 +68,105 @@@ */ static int l_WaitForResponseTimeout(lua_State *L){ - uint32_t cmd = 0; - size_t ms_timeout = -1; - - //Check number of arguments - int n = lua_gettop(L); - if(n == 0) - { - //signal error by returning Nil, errorstring - lua_pushnil(L); - lua_pushstring(L,"You need to supply at least command to wait for"); - return 2; // two return values - } - if(n >= 1) - { - //pop cmd - cmd = luaL_checkunsigned(L,1); - } - if(n >= 2) - { - //Did the user send a timeout ? - //Check if the current top of stack is an integer - ms_timeout = luaL_checkunsigned(L,2); - //printf("Timeout set to %dms\n" , (int) ms_timeout); - } - - UsbCommand response; - - if(WaitForResponseTimeout(cmd, &response, ms_timeout)) - { - //Push it as a string - lua_pushlstring(L,(const char *)&response,sizeof(UsbCommand)); - - return 1;// return 1 to signal one return value - }else{ - //Push a Nil instead - lua_pushnil(L); - return 1;// one return value - } + uint32_t cmd = 0; + size_t ms_timeout = -1; + + //Check number of arguments + int n = lua_gettop(L); + if(n == 0) + { + //signal error by returning Nil, errorstring + lua_pushnil(L); + lua_pushstring(L,"You need to supply at least command to wait for"); + return 2; // two return values + } + if(n >= 1) + { + //pop cmd + cmd = luaL_checkunsigned(L,1); + } + if(n >= 2) + { + //Did the user send a timeout ? + //Check if the current top of stack is an integer + ms_timeout = luaL_checkunsigned(L,2); + //printf("Timeout set to %dms\n" , (int) ms_timeout); + } + + UsbCommand response; + + if(WaitForResponseTimeout(cmd, &response, ms_timeout)) + { + //Push it as a string + lua_pushlstring(L,(const char *)&response,sizeof(UsbCommand)); + + return 1;// return 1 to signal one return value + }else{ + //Push a Nil instead + lua_pushnil(L); + return 1;// one return value + } } static int returnToLuaWithError(lua_State *L, const char* fmt, ...) { - char buffer[200]; - va_list args; - va_start(args,fmt); - vsnprintf(buffer, sizeof(buffer), fmt,args); - va_end(args); - - lua_pushnil(L); - lua_pushstring(L,buffer); - return 2; + char buffer[200]; + va_list args; + va_start(args,fmt); + vsnprintf(buffer, sizeof(buffer), fmt,args); + va_end(args); + + lua_pushnil(L); + lua_pushstring(L,buffer); + return 2; } static int l_nonce2key(lua_State *L){ - size_t size; - const char *p_uid = luaL_checklstring(L, 1, &size); - if(size != 4) return returnToLuaWithError(L,"Wrong size of uid, got %d bytes, expected 4", (int) size); + size_t size; + const char *p_uid = luaL_checklstring(L, 1, &size); + if(size != 4) return returnToLuaWithError(L,"Wrong size of uid, got %d bytes, expected 4", (int) size); - const char *p_nt = luaL_checklstring(L, 2, &size); - if(size != 4) return returnToLuaWithError(L,"Wrong size of nt, got %d bytes, expected 4", (int) size); + const char *p_nt = luaL_checklstring(L, 2, &size); + if(size != 4) return returnToLuaWithError(L,"Wrong size of nt, got %d bytes, expected 4", (int) size); - const char *p_nr = luaL_checklstring(L, 3, &size); - if(size != 4) return returnToLuaWithError(L,"Wrong size of nr, got %d bytes, expected 4", (int) size); + const char *p_nr = luaL_checklstring(L, 3, &size); + if(size != 4) return returnToLuaWithError(L,"Wrong size of nr, got %d bytes, expected 4", (int) size); - const char *p_par_info = luaL_checklstring(L, 4, &size); - if(size != 8) return returnToLuaWithError(L,"Wrong size of par_info, got %d bytes, expected 8", (int) size); + const char *p_par_info = luaL_checklstring(L, 4, &size); + if(size != 8) return returnToLuaWithError(L,"Wrong size of par_info, got %d bytes, expected 8", (int) size); - const char *p_pks_info = luaL_checklstring(L, 5, &size); - if(size != 8) return returnToLuaWithError(L,"Wrong size of ks_info, got %d bytes, expected 8", (int) size); + const char *p_pks_info = luaL_checklstring(L, 5, &size); + if(size != 8) return returnToLuaWithError(L,"Wrong size of ks_info, got %d bytes, expected 8", (int) size); - uint32_t uid = bytes_to_num(( uint8_t *)p_uid,4); - uint32_t nt = bytes_to_num(( uint8_t *)p_nt,4); + uint32_t uid = bytes_to_num(( uint8_t *)p_uid,4); + uint32_t nt = bytes_to_num(( uint8_t *)p_nt,4); - uint32_t nr = bytes_to_num(( uint8_t*)p_nr,4); - uint64_t par_info = bytes_to_num(( uint8_t *)p_par_info,8); - uint64_t ks_info = bytes_to_num(( uint8_t *)p_pks_info,8); + uint32_t nr = bytes_to_num(( uint8_t*)p_nr,4); + uint64_t par_info = bytes_to_num(( uint8_t *)p_par_info,8); + uint64_t ks_info = bytes_to_num(( uint8_t *)p_pks_info,8); - uint64_t key = 0; + uint64_t key = 0; - int retval = nonce2key(uid,nt, nr, par_info,ks_info, &key); + int retval = nonce2key(uid,nt, nr, par_info,ks_info, &key); - //Push the retval on the stack - lua_pushinteger(L,retval); + //Push the retval on the stack + lua_pushinteger(L,retval); - + - //Push the key onto the stack - uint8_t dest_key[8]; - num_to_bytes(key,sizeof(dest_key),dest_key); + //Push the key onto the stack + uint8_t dest_key[8]; + num_to_bytes(key,sizeof(dest_key),dest_key); - //printf("Pushing to lua stack: %012"llx"\n",key); - lua_pushlstring(L,(const char *) dest_key,sizeof(dest_key)); + //printf("Pushing to lua stack: %012"llx"\n",key); + lua_pushlstring(L,(const char *) dest_key,sizeof(dest_key)); - return 2; //Two return values + return 2; //Two return values } //static int l_PrintAndLog(lua_State *L){ return CmdHF14AMfDump(luaL_checkstring(L, 1));} static int l_clearCommandBuffer(lua_State *L){ - clearCommandBuffer(); - return 0; + clearCommandBuffer(); + return 0; } /** * @brief l_foobar is a dummy function to test lua-integration with @@@ -175,23 -175,23 +175,23 @@@ */ static int l_foobar(lua_State *L) { - //Check number of arguments - int n = lua_gettop(L); - printf("foobar called with %d arguments" , n); - lua_settop(L, 0); - printf("Arguments discarded, stack now contains %d elements", lua_gettop(L)); - - // todo: this is not used, where was it intended for? - // UsbCommand response = {CMD_MIFARE_READBL, {1337, 1338, 1339}}; - - printf("Now returning a uint64_t as a string"); - uint64_t x = 0xDEADBEEF; - uint8_t destination[8]; - num_to_bytes(x,sizeof(x),destination); - lua_pushlstring(L,(const char *)&x,sizeof(x)); - lua_pushlstring(L,(const char *)destination,sizeof(destination)); - - return 2; + //Check number of arguments + int n = lua_gettop(L); + printf("foobar called with %d arguments" , n); + lua_settop(L, 0); + printf("Arguments discarded, stack now contains %d elements", lua_gettop(L)); - ++ + // todo: this is not used, where was it intended for? + // UsbCommand response = {CMD_MIFARE_READBL, {1337, 1338, 1339}}; - ++ + printf("Now returning a uint64_t as a string"); + uint64_t x = 0xDEADBEEF; + uint8_t destination[8]; + num_to_bytes(x,sizeof(x),destination); + lua_pushlstring(L,(const char *)&x,sizeof(x)); + lua_pushlstring(L,(const char *)destination,sizeof(destination)); + + return 2; } @@@ -202,8 -202,8 +202,8 @@@ */ static int l_ukbhit(lua_State *L) { - lua_pushboolean(L,ukbhit() ? true : false); - return 1; + lua_pushboolean(L,ukbhit() ? true : false); + return 1; } /** * @brief Calls the command line parser to deal with the command. This enables @@@ -213,18 -213,18 +213,18 @@@ */ static int l_CmdConsole(lua_State *L) { - CommandReceived((char *)luaL_checkstring(L, 1)); - return 0; + CommandReceived((char *)luaL_checkstring(L, 1)); + return 0; } static int l_iso15693_crc(lua_State *L) { - // uint16_t Iso15693Crc(uint8_t *v, int n); - size_t size; - const char *v = luaL_checklstring(L, 1, &size); - uint16_t retval = Iso15693Crc((uint8_t *) v, size); - lua_pushinteger(L, (int) retval); - return 1; + // uint16_t Iso15693Crc(uint8_t *v, int n); + size_t size; + const char *v = luaL_checklstring(L, 1, &size); + uint16_t retval = Iso15693Crc((uint8_t *) v, size); + lua_pushinteger(L, (int) retval); + return 1; } /* @@@ -235,28 -235,28 +235,29 @@@ static int l_aes128decrypt(lua_State *L { //Check number of arguments int i; - size_t size; - const char *p_key = luaL_checklstring(L, 1, &size); - if(size != 32) return returnToLuaWithError(L,"Wrong size of key, got %d bytes, expected 32", (int) size); + size_t size; + const char *p_key = luaL_checklstring(L, 1, &size); + if(size != 32) return returnToLuaWithError(L,"Wrong size of key, got %d bytes, expected 32", (int) size); - const char *p_encTxt = luaL_checklstring(L, 2, &size); + const char *p_encTxt = luaL_checklstring(L, 2, &size); - + unsigned char indata[16] = {0x00}; unsigned char outdata[16] = {0x00}; - unsigned char aes_key[16] = {0x00}; + unsigned char aes_key[16] = {0x00}; unsigned char iv[16] = {0x00}; + // convert key to bytearray and convert input to bytearray for (i = 0; i < 32; i += 2) { sscanf(&p_encTxt[i], "%02x", (unsigned int *)&indata[i / 2]); sscanf(&p_key[i], "%02x", (unsigned int *)&aes_key[i / 2]); } - aes_context ctx; - aes_init(&ctx); + aes_context ctx; + aes_init(&ctx); + //aes_setkey_enc(&ctx, (const unsigned char *)aes_key, 128); aes_setkey_dec(&ctx, aes_key, 128); - aes_crypt_cbc(&ctx,AES_DECRYPT,sizeof(indata), iv, indata,outdata ); - //Push decrypted array as a string + aes_crypt_cbc(&ctx, AES_DECRYPT, sizeof(indata), iv, indata, outdata ); + //Push decrypted array as a string lua_pushlstring(L,(const char *)&outdata, sizeof(outdata)); return 1;// return 1 to signal one return value } @@@ -264,15 -264,15 +265,15 @@@ static int l_aes128encrypt(lua_State *L { //Check number of arguments int i; - size_t size; - const char *p_key = luaL_checklstring(L, 1, &size); - if(size != 32) return returnToLuaWithError(L,"Wrong size of key, got %d bytes, expected 32", (int) size); - - const char *p_txt = luaL_checklstring(L, 2, &size); + size_t size; + const char *p_key = luaL_checklstring(L, 1, &size); + if(size != 32) return returnToLuaWithError(L,"Wrong size of key, got %d bytes, expected 32", (int) size); + const char *p_txt = luaL_checklstring(L, 2, &size); + unsigned char indata[16] = {0x00}; unsigned char outdata[16] = {0x00}; - unsigned char aes_key[16] = {0x00}; + unsigned char aes_key[16] = {0x00}; unsigned char iv[16] = {0x00}; for (i = 0; i < 32; i += 2) { @@@ -280,11 -280,11 +281,11 @@@ sscanf(&p_key[i], "%02x", (unsigned int *)&aes_key[i / 2]); } - aes_context ctx; - aes_init(&ctx); + aes_context ctx; + aes_init(&ctx); - aes_setkey_enc(&ctx, aes_key, 128); + aes_setkey_enc(&ctx, aes_key, 128); aes_crypt_cbc(&ctx, AES_ENCRYPT, sizeof(indata), iv, indata, outdata ); - //Push encrypted array as a string + //Push encrypted array as a string lua_pushlstring(L,(const char *)&outdata, sizeof(outdata)); return 1;// return 1 to signal one return value } @@@ -293,10 -293,10 +294,10 @@@ static int l_crc16(lua_State *L { size_t size; const char *p_str = luaL_checklstring(L, 1, &size); - + uint16_t retval = crc16_ccitt( (uint8_t*) p_str, size); - lua_pushinteger(L, (int) retval); - return 1; + lua_pushinteger(L, (int) retval); + return 1; } static int l_crc64(lua_State *L) @@@ -306,7 -306,7 +307,7 @@@ unsigned char outdata[8] = {0x00}; const char *p_str = luaL_checklstring(L, 1, &size); - + crc64( (uint8_t*) p_str, size, &crc); outdata[0] = (uint8_t)(crc >> 56) & 0xff; @@@ -318,7 -318,7 +319,7 @@@ outdata[6] = (uint8_t)(crc >> 8) & 0xff; outdata[7] = crc & 0xff; lua_pushlstring(L,(const char *)&outdata, sizeof(outdata)); - return 1; + return 1; } /** @@@ -331,17 -331,17 +332,17 @@@ */ int setLuaPath( lua_State* L, const char* path ) { - lua_getglobal( L, "package" ); - lua_getfield( L, -1, "path" ); // get field "path" from table at top of stack (-1) - const char* cur_path = lua_tostring( L, -1 ); // grab path string from top of stack - int requiredLength = strlen(cur_path)+ strlen(path)+10; //A few bytes too many, whatever we can afford it - char * buf = malloc(requiredLength); - snprintf(buf, requiredLength, "%s;%s", cur_path, path); - lua_pop( L, 1 ); // get rid of the string on the stack we just pushed on line 5 - lua_pushstring( L, buf ); // push the new one - lua_setfield( L, -2, "path" ); // set the field "path" in table at -2 with value at top of stack - lua_pop( L, 1 ); // get rid of package table from top of stack + lua_getglobal( L, "package" ); + lua_getfield( L, -1, "path" ); // get field "path" from table at top of stack (-1) + const char* cur_path = lua_tostring( L, -1 ); // grab path string from top of stack + int requiredLength = strlen(cur_path)+ strlen(path)+10; //A few bytes too many, whatever we can afford it + char * buf = malloc(requiredLength); + snprintf(buf, requiredLength, "%s;%s", cur_path, path); + lua_pop( L, 1 ); // get rid of the string on the stack we just pushed on line 5 + lua_pushstring( L, buf ); // push the new one + lua_setfield( L, -2, "path" ); // set the field "path" in table at -2 with value at top of stack + lua_pop( L, 1 ); // get rid of package table from top of stack - free(buf); + free(buf); return 0; // all done! } @@@ -349,42 -349,42 +350,42 @@@ int set_pm3_libraries(lua_State *L) { - static const luaL_Reg libs[] = { - {"SendCommand", l_SendCommand}, - {"WaitForResponseTimeout", l_WaitForResponseTimeout}, - {"nonce2key", l_nonce2key}, - //{"PrintAndLog", l_PrintAndLog}, - {"foobar", l_foobar}, - {"ukbhit", l_ukbhit}, - {"clearCommandBuffer", l_clearCommandBuffer}, + static const luaL_Reg libs[] = { + {"SendCommand", l_SendCommand}, + {"WaitForResponseTimeout", l_WaitForResponseTimeout}, + {"nonce2key", l_nonce2key}, + //{"PrintAndLog", l_PrintAndLog}, + {"foobar", l_foobar}, + {"ukbhit", l_ukbhit}, + {"clearCommandBuffer", l_clearCommandBuffer}, - {"console", l_CmdConsole}, - {"iso15693_crc", l_iso15693_crc}, + {"console", l_CmdConsole}, + {"iso15693_crc", l_iso15693_crc}, {"aes128_decrypt", l_aes128decrypt}, {"aes128_encrypt", l_aes128encrypt}, {"crc16", l_crc16}, - {"crc64", l_crc64}, + {"crc64", l_crc64}, - {NULL, NULL} - }; - - lua_pushglobaltable(L); - // Core library is in this table. Contains ' - //this is 'pm3' table - lua_newtable(L); - - //Put the function into the hash table. - for (int i = 0; libs[i].name; i++) { - lua_pushcfunction(L, libs[i].func); - lua_setfield(L, -2, libs[i].name);//set the name, pop stack - } - //Name of 'core' - lua_setfield(L, -2, "core"); - - //-- remove the global environment table from the stack - lua_pop(L, 1); - - //-- Last but not least, add to the LUA_PATH (package.path in lua) - // so we can load libraries from the ./lualib/ - directory - setLuaPath(L,"./lualibs/?.lua"); - - return 1; + {NULL, NULL} + }; + + lua_pushglobaltable(L); + // Core library is in this table. Contains ' + //this is 'pm3' table + lua_newtable(L); + + //Put the function into the hash table. + for (int i = 0; libs[i].name; i++) { + lua_pushcfunction(L, libs[i].func); + lua_setfield(L, -2, libs[i].name);//set the name, pop stack + } + //Name of 'core' + lua_setfield(L, -2, "core"); + + //-- remove the global environment table from the stack + lua_pop(L, 1); + + //-- Last but not least, add to the LUA_PATH (package.path in lua) + // so we can load libraries from the ./lualib/ - directory + setLuaPath(L,"./lualibs/?.lua"); + + return 1; } diff --combined client/util.c index 391b9b00,cea9f7d7..a64f46b9 --- a/client/util.c +++ b/client/util.c @@@ -108,16 -108,16 +108,16 @@@ void print_hex(const uint8_t * data, co printf("\n"); } -char * sprint_hex(const uint8_t * data, const size_t len) { +char *sprint_hex(const uint8_t *data, const size_t len) { int maxLen = ( len > 1024/3) ? 1024/3 : len; static char buf[1024]; memset(buf, 0x00, 1024); - char *tmp = buf; + char * tmp = buf; size_t i; for (i=0; i < maxLen; ++i, tmp += 3) - sprintf(tmp, "%02x ", data[i]); + sprintf(tmp, "%02X ", data[i]); return buf; } diff --combined common/protocols.h index 62cfb7ff,58034272..466e84f1 --- a/common/protocols.h +++ b/common/protocols.h @@@ -109,7 -109,7 +109,7 @@@ NXP/Philips CUSTOM COMMAND #define ISO14443A_CMD_WUPA 0x52 #define ISO14443A_CMD_ANTICOLL_OR_SELECT 0x93 #define ISO14443A_CMD_ANTICOLL_OR_SELECT_2 0x95 -#define ISO14443A_CMD_WRITEBLOCK 0xA0 // or 0xA2 ? +#define ISO14443A_CMD_WRITEBLOCK 0xA0 #define ISO14443A_CMD_HALT 0x50 #define ISO14443A_CMD_RATS 0xE0 @@@ -123,19 -123,21 +123,19 @@@ #define MIFARE_CMD_RESTORE 0xC2 #define MIFARE_CMD_TRANSFER 0xB0 - #define MIFARE_ULC_WRITE 0xA2 - //#define MIFARE_ULC_COMP_WRITE 0xA0 + #define MIFARE_ULC_WRITE 0xA2 + //#define MIFARE_ULC__COMP_WRITE 0xA0 #define MIFARE_ULC_AUTH_1 0x1A #define MIFARE_ULC_AUTH_2 0xAF -#define MIFARE_ULEV1_AUTH 0x1B -#define MIFARE_ULEV1_VERSION 0x60 -#define MIFARE_ULEV1_FASTREAD 0x3A -//#define MIFARE_ULEV1_WRITE 0xA2 -//#define MIFARE_ULEV1_COMP_WRITE 0xA0 -#define MIFARE_ULEV1_READ_CNT 0x39 -#define MIFARE_ULEV1_INCR_CNT 0xA5 -#define MIFARE_ULEV1_READSIG 0x3C -#define MIFARE_ULEV1_CHECKTEAR 0x3E -#define MIFARE_ULEV1_VCSL 0x4B +#define MIFARE_ULEV1_AUTH 0x1B +#define MIFARE_ULEV1_VERSION 0x60 +#define MIFARE_ULEV1_FASTREAD 0x3A +#define MIFARE_ULEV1_READ_CNT 0x39 +#define MIFARE_ULEV1_INCR_CNT 0xA5 +#define MIFARE_ULEV1_READSIG 0x3C +#define MIFARE_ULEV1_CHECKTEAR 0x3E +#define MIFARE_ULEV1_VCSL 0x4B /** 06 00 = INITIATE @@@ -178,25 -180,9 +178,25 @@@ #define ISO15693_READ_MULTI_SECSTATUS 0x2C +// Topaz command set: +#define TOPAZ_REQA 0x26 // Request +#define TOPAZ_WUPA 0x52 // WakeUp +#define TOPAZ_RID 0x78 // Read ID +#define TOPAZ_RALL 0x00 // Read All (all bytes) +#define TOPAZ_READ 0x01 // Read (a single byte) +#define TOPAZ_WRITE_E 0x53 // Write-with-erase (a single byte) +#define TOPAZ_WRITE_NE 0x1a // Write-no-erase (a single byte) +// additional commands for Dynamic Memory Model +#define TOPAZ_RSEG 0x10 // Read segment +#define TOPAZ_READ8 0x02 // Read (eight bytes) +#define TOPAZ_WRITE_E8 0x54 // Write-with-erase (eight bytes) +#define TOPAZ_WRITE_NE8 0x1B // Write-no-erase (eight bytes) + + #define ISO_14443A 0 #define ICLASS 1 #define ISO_14443B 2 +#define TOPAZ 3 //-- Picopass fuses #define FUSE_FPERS 0x80 diff --combined include/usb_cmd.h index 2a6e9484,357395d4..345793ec --- a/include/usb_cmd.h +++ b/include/usb_cmd.h @@@ -128,13 -128,12 +128,13 @@@ typedef struct #define CMD_READER_LEGIC_RF 0x0388 #define CMD_WRITER_LEGIC_RF 0x0389 #define CMD_EPA_PACE_COLLECT_NONCE 0x038A +//#define CMD_EPA_ 0x038B #define CMD_SNOOP_ICLASS 0x0392 #define CMD_SIMULATE_TAG_ICLASS 0x0393 #define CMD_READER_ICLASS 0x0394 - #define CMD_READER_ICLASS_REPLAY 0x0395 + #define CMD_READER_ICLASS_REPLAY 0x0395 -#define CMD_ICLASS_ISO14443A_WRITE 0x0397 +#define CMD_ICLASS_ISO14443A_WRITE 0x0397 #define CMD_ICLASS_EML_MEMSET 0x0398 // For measurements of the antenna tuning @@@ -164,20 -163,20 +164,20 @@@ #define CMD_MIFARE_NESTED 0x0612 #define CMD_MIFARE_READBL 0x0620 - #define CMD_MIFAREU_READBL 0x0720 + #define CMD_MIFAREU_READBL 0x0720 #define CMD_MIFARE_READSC 0x0621 - #define CMD_MIFAREU_READCARD 0x0721 + #define CMD_MIFAREU_READCARD 0x0721 #define CMD_MIFARE_WRITEBL 0x0622 -#define CMD_MIFAREU_WRITEBL 0x0722 -#define CMD_MIFAREU_WRITEBL_COMPAT 0x0723 +#define CMD_MIFAREU_WRITEBL 0x0722 +#define CMD_MIFAREU_WRITEBL_COMPAT 0x0723 #define CMD_MIFARE_CHKKEYS 0x0623 #define CMD_MIFARE_SNIFFER 0x0630 //ultralightC - #define CMD_MIFAREUC_AUTH 0x0724 + #define CMD_MIFAREUC_AUTH 0x0724 //0x0725 and 0x0726 no longer used - #define CMD_MIFAREUC_SETPWD 0x0727 + #define CMD_MIFAREUC_SETPWD 0x0727 // mifare desfire @@@ -189,8 -188,6 +189,8 @@@ #define CMD_MIFARE_DESFIRE_INFO 0x072d #define CMD_MIFARE_DESFIRE 0x072e +#define CMD_MIFARE_COLLECT_NONCES 0x072f + #define CMD_UNKNOWN 0xFFFF @@@ -202,11 -199,11 +202,11 @@@ //Iclass reader flags -#define FLAG_ICLASS_READER_ONLY_ONCE 0x01 -#define FLAG_ICLASS_READER_CC 0x02 -#define FLAG_ICLASS_READER_CSN 0x04 -#define FLAG_ICLASS_READER_CONF 0x08 -#define FLAG_ICLASS_READER_AA 0x10 +#define FLAG_ICLASS_READER_ONLY_ONCE 0x01 +#define FLAG_ICLASS_READER_CC 0x02 +#define FLAG_ICLASS_READER_CSN 0x04 +#define FLAG_ICLASS_READER_CONF 0x08 +#define FLAG_ICLASS_READER_AA 0x10 #define FLAG_ICLASS_READER_ONE_TRY 0x20