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: https://git.zerfleddert.de/cgi-bin/gitweb.cgi/proxmark3-svn/commitdiff_plain/bcf61bd34ab2747580aabf648093e5854b7283ed 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 --cc 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 --cc armsrc/appmain.c index b19e079b,96644b9a..04503a4f --- a/armsrc/appmain.c +++ b/armsrc/appmain.c @@@ -845,9 -843,9 +845,10 @@@ void UsbPacketReceived(uint8_t *packet 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); diff --cc 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 --cc armsrc/mifarecmd.c index 03e15b3b,0586a25d..c56f2337 --- a/armsrc/mifarecmd.c +++ b/armsrc/mifarecmd.c @@@ -110,8 -115,8 +115,10 @@@ void MifareUC_Auth(uint8_t arg0, uint8_ 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, @@@ -169,8 -174,8 +176,8 @@@ void MifareUReadBlock(uint8_t arg0, uin 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(); } @@@ -277,44 -278,44 +284,73 @@@ void MifareUReadCard(uint8_t arg0, uint 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; @@@ -449,20 -450,12 +485,20 @@@ void MifareUWriteBlock(uint8_t arg0, ui 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(); diff --cc armsrc/mifareutil.c index 8c44445f,2f84797b..109b91b0 --- a/armsrc/mifareutil.c +++ b/armsrc/mifareutil.c @@@ -376,27 -377,27 +377,47 @@@ int mifare_ultra_auth(uint8_t *keybytes 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], @@@ -494,23 -495,23 +515,23 @@@ int mifare_classic_writeblock(struct Cr 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); @@@ -519,10 -520,10 +540,10 @@@ 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) { diff --cc armsrc/mifareutil.h index f73814be,d4fcd818..9575b9fc --- a/armsrc/mifareutil.h +++ b/armsrc/mifareutil.h @@@ -58,19 -58,19 +58,19 @@@ int mifare_sendcmd_short_special(struc 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); diff --cc client/cmdhf.c index 1a088676,16f7bb0f..614dcdc4 --- a/client/cmdhf.c +++ b/client/cmdhf.c @@@ -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 --cc 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 --cc client/cmdhfmf.c index 1b815326,aa3b66dc..676a8884 --- a/client/cmdhfmf.c +++ b/client/cmdhfmf.c @@@ -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 --cc 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] = { @@@ -151,63 -151,63 +151,127 @@@ static int ul_select( iso14a_card_selec 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 @@@ -308,359 -308,359 +372,777 @@@ static int ul_print_default( uint8_t *d 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; @@@ -974,102 -912,27 +1456,101 @@@ int CmdHF14AMfUWrBl(const char *Cmd) // 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) { @@@ -1534,10 -1509,10 +2021,11 @@@ int CmdTestDES(const char * cmd // 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]; diff --cc 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 --cc client/nonce2key/crapto1.c index 1d7441c7,1015e27a..13c4c063 --- a/client/nonce2key/crapto1.c +++ b/client/nonce2key/crapto1.c @@@ -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); @@@ -536,8 -536,8 +533,7 @@@ brute_top(uint32_t prefix, uint32_t rre * 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 --cc client/scripting.c index 880b7cb2,152fd9d4..9e643932 --- a/client/scripting.c +++ b/client/scripting.c @@@ -123,45 -123,45 +123,45 @@@ static int returnToLuaWithError(lua_Sta 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){ @@@ -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; } @@@ -235,17 -235,18 +235,18 @@@ 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]); @@@ -280,11 -280,11 +281,11 @@@ static int l_aes128encrypt(lua_State *L 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) @@@ -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 --cc include/usb_cmd.h index 2a6e9484,357395d4..345793ec --- a/include/usb_cmd.h +++ b/include/usb_cmd.h @@@ -133,8 -132,8 +133,8 @@@ typedef struct #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,12 -163,12 +164,12 @@@ #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