From e98572a1e2dde603f31cc06f330c6abd295139de Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Wed, 7 Oct 2015 23:00:46 +0200 Subject: [PATCH] I just merged @marshmellow's branch "iclass" and that was a lot of new functionality. *great work* Things like the ICLASS, tryDecryptWord, -- My other stuff like default keys, some new Mifare EV1 commands 0x40, 0x43 for the logging annotation, start of the T55x7 configblock helper functionality (ripped from Adam Lauries RFIdler code) Changes to the PCF7931 functions written, which has a lousy input check.. --- CHANGELOG.md | 14 +- README.txt | 65 +- armsrc/LCD.c | 2 +- armsrc/appmain.c | 21 + armsrc/apps.h | 12 + armsrc/iclass.c | 276 +++--- armsrc/iso14443a.c | 29 +- armsrc/lfops.c | 257 +++++ client/cmdhf14a.c | 2 +- client/cmdhf14b.c | 4 + client/cmdhficlass.c | 1468 +++++++++++++++++++++++----- client/cmdhficlass.h | 21 +- client/cmdhfmf.c | 12 +- client/cmdhfmf.h | 4 +- client/cmdhfmfdes.c | 1 - client/cmdhfmfu.c | 2 +- client/cmdlf.c | 8 +- client/cmdlfpcf7931.c | 140 ++- client/cmdlfpcf7931.h | 13 +- client/cmdlft55xx.c | 8 +- client/cmdlft55xx.h | 15 +- client/default_keys.dic | 4 +- client/loclass/cipher.c | 21 + client/loclass/cipher.h | 2 + client/lualibs/commands.lua | 8 +- client/lualibs/mf_default_keys.lua | 6 + client/mifarehost.c | 20 + client/mifarehost.h | 1 + client/nonce2key/nonce2key.c | 2 +- client/util.c | 21 + client/util.h | 1 + common/protocols.c | 64 +- common/protocols.h | 7 + include/usb_cmd.h | 9 +- 34 files changed, 2053 insertions(+), 487 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index f9e8e2ac..e619d89e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,8 +3,18 @@ All notable changes to this project will be documented in this file. This project uses the changelog in accordance with [keepchangelog](http://keepachangelog.com/). Please use this to write notable changes, which is not the same as git commit log... ## [unreleased][unreleased] + --trying to fix "hf 14b" command to be able to read CALYPSO card. (iceman) + --trying to fix "t55x7" read with password bug. (iceman) + -- ### Added +- `hf mf eload u` added an ultralight/ntag option. (marshmellow) +- `hf iclass managekeys` to save, load and manage iclass keys. (adjusted most commands to accept a loaded key in memory) (marshmellow) +- `hf iclass readblk` to select, authenticate, and read 1 block from an iclass card (marshmellow) +- `hf iclass writeblk` to select, authenticate, and write 1 block to an iclass card (or picopass) (marshmellow + others) +- `hf iclass clone` to take a saved dump file and clone selected blocks to a new tag (marshmellow + others) +- `hf iclass calcnewkey` - to calculate the div_key change to change a key - (experimental) (marshmellow + others) +- `hf iclass encryptblk` - to encrypt a data block hex to prep for writing that block (marshmellow) - ISO14443a stand-alone operation with ARM CFLAG="WITH_ISO14443a_StandAlone". This code can read & emulate two banks of 14a tag UIDs and write to "magic" cards (Craig Young) - AWID26 command context added as 'lf awid' containing realtime demodulation as well as cloning/simulation based on tag numbers (Craig Young) - Added 'hw status'. This command makes the ARM print out some runtime information. (holiman) @@ -12,8 +22,9 @@ This project uses the changelog in accordance with [keepchangelog](http://keepac - Added `data hex2bin` and `data bin2hex` for command line conversion between binary and hexadecimal (holiman) ### Changed +- changed `lf config t ` to be 0 - 128 and will trigger on + or - threshold value (marshmellow) +- `hf iclass dump` cli options - can now dump AA1 and AA2 with different keys in one run (does not go to muliple pages for the larger tags yet) - Revised workflow for StandAloneMode14a (Craig Young) -- Changed lf config's `threshold` to a graph (signed) metric and it will trigger on + or - value set to. (example: set to 50 and recording would begin at first graphed value of >= 50 or <= -50) (marshmellow) - EPA functions (`hf epa`) now support both ISO 14443-A and 14443-B cards (frederikmoellers) - 'hw version' only talks to ARM at startup, after that the info is cached. (pwpiwi) @@ -26,7 +37,6 @@ This project uses the changelog in accordance with [keepchangelog](http://keepac - Added compression of fpga config and data, *BOOTROM REFLASH REQUIRED* (piwi) - Implemented better detection of mifare-tags that are not vulnerable to classic attacks (`hf mf mifare`, `hf mf nested`) (piwi) - ### Added - Add `hf 14b reader` to find and print general info about known 14b tags (marshmellow) - Add `hf 14b info` to find and print full info about std 14b tags and sri tags (using 14b raw commands in the client) (marshmellow) diff --git a/README.txt b/README.txt index 2acd55a1..2bab1bcd 100644 --- a/README.txt +++ b/README.txt @@ -1,24 +1,32 @@ -The iceman fork. - +The iceman fork +--------------- NOTICE: The official Proxmark repository is found here: https://github.com/Proxmark/proxmark3 +NEWS: + +::THIS FORK IS HIGHLY EXPERIMENTAL:: -NEWS: 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 * Jonor's hf 14a raw timing patch * Piwi's updates. (usually gets into the master) + * Piwi's "topaz" branch (not merged) * Holiman's iclass, (usually gets into the master) - * Marshmellow's LF fixes + * Marshmellow's fixes (usually gets into the master) * 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. + * Minor textual changes here and there. + * Simulation of Ultralight/Ntag. + * Marshmellow's and my "RevEng" addon for the client. Ref: http://reveng.sourceforge.net/ + * Someone's alterantive bruteforce Mifare changes.. (you need the two other exe to make it work) + * Give me a hint, and I'll see if I can't merge in the stuff you have. @@ -28,6 +36,7 @@ PM3 GUI: I do tend to rename and move stuff around, the official PM3-GUI from Gaucho will not work so well. *sorry* + DEVELOPMENT: @@ -78,10 +87,54 @@ Solution 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. + + +January 2015, Sweden +iceman at host iuse.se + The Proxmark 3 is available for purchase (assembled and tested) from the following locations: + * http://proxmark3.com/ + * http://www.xfpga.com/ -January 2015, Sweden -iceman at host iuse.se +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 diff --git a/armsrc/LCD.c b/armsrc/LCD.c index 87be5e3a..65d64ac9 100644 --- a/armsrc/LCD.c +++ b/armsrc/LCD.c @@ -6,7 +6,7 @@ // LCD code //----------------------------------------------------------------------------- -#include "../include/proxmark3.h" +#include "proxmark3.h" #include "apps.h" #include "LCD.h" #include "fonts.h" diff --git a/armsrc/appmain.c b/armsrc/appmain.c index 8c4b45f5..6ef18bc8 100644 --- a/armsrc/appmain.c +++ b/armsrc/appmain.c @@ -992,6 +992,9 @@ void UsbPacketReceived(uint8_t *packet, int len) ReadPCF7931(); cmd_send(CMD_ACK,0,0,0,0,0); break; + case CMD_PCF7931_WRITE: + WritePCF7931(c->d.asDwords[0],c->d.asDwords[1],c->d.asDwords[2],c->d.asDwords[3],c->d.asDwords[4],c->d.asDwords[5],c->d.asDwords[6], c->d.asDwords[9], c->d.asDwords[7]-128,c->d.asDwords[8]-128, c->arg[0], c->arg[1], c->arg[2]); + break; case CMD_EM4X_READ_WORD: EM4xReadWord(c->arg[1], c->arg[2],c->d.asBytes[0]); break; @@ -1212,6 +1215,24 @@ void UsbPacketReceived(uint8_t *packet, int len) case CMD_ICLASS_EML_MEMSET: emlSet(c->d.asBytes,c->arg[0], c->arg[1]); break; + case CMD_ICLASS_WRITEBLOCK: + iClass_WriteBlock(c->arg[0], c->d.asBytes); + break; + case CMD_ICLASS_READCHECK: // auth step 1 + iClass_ReadCheck(c->arg[0], c->arg[1]); + break; + case CMD_ICLASS_READBLOCK: + iClass_ReadBlk(c->arg[0]); + break; + case CMD_ICLASS_AUTHENTICATION: //check + iClass_Authentication(c->d.asBytes); + break; + case CMD_ICLASS_DUMP: + iClass_Dump(c->arg[0], c->arg[1]); + break; + case CMD_ICLASS_CLONE: + iClass_Clone(c->arg[0], c->arg[1], c->d.asBytes); + break; #endif case CMD_BUFF_CLEAR: diff --git a/armsrc/apps.h b/armsrc/apps.h index b4cab979..f88e6e91 100644 --- a/armsrc/apps.h +++ b/armsrc/apps.h @@ -94,6 +94,11 @@ int DemodPCF7931(uint8_t **outBlocks); int IsBlock0PCF7931(uint8_t *Block); int IsBlock1PCF7931(uint8_t *Block); void ReadPCF7931(); +void SendCmdPCF7931(uint32_t * tab); +bool AddBytePCF7931(uint8_t byte, uint32_t * tab, int32_t l, int32_t p); +bool AddBitPCF7931(bool b, uint32_t * tab, int32_t l, int32_t p); +bool AddPatternPCF7931(uint32_t a, uint32_t b, uint32_t c, uint32_t * tab); +void WritePCF7931(uint8_t pass1, uint8_t pass2, uint8_t pass3, uint8_t pass4, uint8_t pass5, uint8_t pass6, uint8_t pass7, uint16_t init_delay, int32_t l, int32_t p, uint8_t address, uint8_t byte, uint8_t data); void EM4xReadWord(uint8_t Address, uint32_t Pwd, uint8_t PwdMode); void EM4xWriteWord(uint32_t Data, uint8_t Address, uint32_t Pwd, uint8_t PwdMode); @@ -190,6 +195,13 @@ void SimulateIClass(uint32_t arg0, uint32_t arg1, uint32_t arg2, uint8_t *datain void ReaderIClass(uint8_t arg0); void ReaderIClass_Replay(uint8_t arg0,uint8_t *MAC); void IClass_iso14443A_GetPublic(uint8_t arg0); +void iClass_Authentication(uint8_t *MAC); +void iClass_WriteBlock(uint8_t blockNo, uint8_t *data); +void iClass_ReadBlk(uint8_t blockNo); +bool iClass_ReadBlock(uint8_t blockNo, uint8_t *readdata); +void iClass_Dump(uint8_t blockno, uint8_t numblks); +void iClass_Clone(uint8_t startblock, uint8_t endblock, uint8_t *data); +void iClass_ReadCheck(uint8_t blockNo, uint8_t keyType); void CopyViKingtoT55x7(uint32_t block1,uint32_t block2); // hitag2.h diff --git a/armsrc/iclass.c b/armsrc/iclass.c index 38b52533..9046d51b 100644 --- a/armsrc/iclass.c +++ b/armsrc/iclass.c @@ -1601,16 +1601,16 @@ void setupIclassReader() } -size_t sendCmdGetResponseWithRetries(uint8_t* command, size_t cmdsize, uint8_t* resp, uint8_t expected_size, uint8_t retries) +bool sendCmdGetResponseWithRetries(uint8_t* command, size_t cmdsize, uint8_t* resp, uint8_t expected_size, uint8_t retries) { while(retries-- > 0) { ReaderTransmitIClass(command, cmdsize); if(expected_size == ReaderReceiveIClass(resp)){ - return 0; + return true; } } - return 1;//Error + return false;//Error } /** @@ -1620,14 +1620,17 @@ size_t sendCmdGetResponseWithRetries(uint8_t* command, size_t cmdsize, uint8_t* * 1 = Got CSN * 2 = Got CSN and CC */ -uint8_t handshakeIclassTag(uint8_t *card_data) +uint8_t handshakeIclassTag_ext(uint8_t *card_data, bool use_credit_key) { static uint8_t act_all[] = { 0x0a }; - static uint8_t identify[] = { 0x0c }; + //static uint8_t identify[] = { 0x0c }; + static uint8_t identify[] = { 0x0c, 0x00, 0x73, 0x33 }; static uint8_t select[] = { 0x81, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; - - - static uint8_t readcheck_cc[]= { 0x88, 0x02,}; + static uint8_t readcheck_cc[]= { 0x88, 0x02 }; + if (use_credit_key) + readcheck_cc[0] = 0x18; + else + readcheck_cc[0] = 0x88; uint8_t resp[ICLASS_BUFFER_SIZE]; @@ -1668,6 +1671,9 @@ uint8_t handshakeIclassTag(uint8_t *card_data) return read_status; } +uint8_t handshakeIclassTag(uint8_t *card_data){ + return handshakeIclassTag_ext(card_data, false); +} // Reader iClass Anticollission @@ -1687,6 +1693,9 @@ void ReaderIClass(uint8_t arg0) { uint8_t result_status = 0; bool abort_after_read = arg0 & FLAG_ICLASS_READER_ONLY_ONCE; bool try_once = arg0 & FLAG_ICLASS_READER_ONE_TRY; + bool use_credit_key = false; + if (arg0 & FLAG_ICLASS_READER_CEDITKEY) + use_credit_key = true; set_tracing(TRUE); setupIclassReader(); @@ -1701,7 +1710,7 @@ void ReaderIClass(uint8_t arg0) { } WDT_HIT(); - read_status = handshakeIclassTag(card_data); + read_status = handshakeIclassTag_ext(card_data, use_credit_key); if(read_status == 0) continue; if(read_status == 1) result_status = FLAG_ICLASS_READER_CSN; @@ -1715,11 +1724,10 @@ void ReaderIClass(uint8_t arg0) { if(arg0 & FLAG_ICLASS_READER_CONF) { if(sendCmdGetResponseWithRetries(readConf, sizeof(readConf),card_data+8, 10, 10)) - { - Dbprintf("Failed to dump config block"); - }else { result_status |= FLAG_ICLASS_READER_CONF; + } else { + Dbprintf("Failed to dump config block"); } } @@ -1727,10 +1735,9 @@ void ReaderIClass(uint8_t arg0) { if(arg0 & FLAG_ICLASS_READER_AA){ if(sendCmdGetResponseWithRetries(readAA, sizeof(readAA),card_data+(8*4), 10, 10)) { -// Dbprintf("Failed to dump AA block"); - }else - { result_status |= FLAG_ICLASS_READER_AA; + } else { + //Dbprintf("Failed to dump AA block"); } } @@ -1814,7 +1821,7 @@ void ReaderIClass_Replay(uint8_t arg0, uint8_t *MAC) { //for now replay captured auth (as cc not updated) memcpy(check+5,MAC,4); - if(sendCmdGetResponseWithRetries(check, sizeof(check),resp, 4, 5)) + if(!sendCmdGetResponseWithRetries(check, sizeof(check),resp, 4, 5)) { Dbprintf("Error: Authentication Fail!"); continue; @@ -1826,7 +1833,7 @@ void ReaderIClass_Replay(uint8_t arg0, uint8_t *MAC) { read[2] = crc >> 8; read[3] = crc & 0xff; - if(sendCmdGetResponseWithRetries(read, sizeof(read),resp, 10, 10)) + if(!sendCmdGetResponseWithRetries(read, sizeof(read),resp, 10, 10)) { Dbprintf("Dump config (block 1) failed"); continue; @@ -1853,7 +1860,7 @@ void ReaderIClass_Replay(uint8_t arg0, uint8_t *MAC) { read[2] = crc >> 8; read[3] = crc & 0xff; - if(!sendCmdGetResponseWithRetries(read, sizeof(read), resp, 10, 10)) + if(sendCmdGetResponseWithRetries(read, sizeof(read), resp, 10, 10)) { Dbprintf(" %02x: %02x %02x %02x %02x %02x %02x %02x %02x", block, resp[0], resp[1], resp[2], @@ -1904,130 +1911,129 @@ void ReaderIClass_Replay(uint8_t arg0, uint8_t *MAC) { LED_A_OFF(); } -//2. Create Read method (cut-down from above) based off responses from 1. -// Since we have the MAC could continue to use replay function. -//3. Create Write method -/* -void IClass_iso14443A_write(uint8_t arg0, uint8_t blockNo, uint8_t *data, uint8_t *MAC) { - uint8_t act_all[] = { 0x0a }; - uint8_t identify[] = { 0x0c }; - uint8_t select[] = { 0x81, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; - uint8_t readcheck_cc[]= { 0x88, 0x02 }; - uint8_t check[] = { 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; - uint8_t read[] = { 0x0c, 0x00, 0x00, 0x00 }; - uint8_t write[] = { 0x87, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; - - uint16_t crc = 0; - - uint8_t* resp = (((uint8_t *)BigBuf) + 3560); - - // Reset trace buffer - memset(trace, 0x44, RECV_CMD_OFFSET); - traceLen = 0; - - // Setup SSC - FpgaSetupSsc(); - // Start from off (no field generated) - // Signal field is off with the appropriate LED - LED_D_OFF(); - FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); - SpinDelay(200); +void iClass_ReadCheck(uint8_t blockNo, uint8_t keyType) { + uint8_t readcheck[] = { keyType, blockNo }; + uint8_t resp[] = {0,0,0,0,0,0,0,0}; + size_t isOK = 0; + isOK = sendCmdGetResponseWithRetries(readcheck, sizeof(readcheck), resp, sizeof(resp), 6); + cmd_send(CMD_ACK,isOK,0,0,0,0); +} - SetAdcMuxFor(GPIO_MUXSEL_HIPKD); +void iClass_Authentication(uint8_t *MAC) { + uint8_t check[] = { ICLASS_CMD_CHECK, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; + uint8_t resp[ICLASS_BUFFER_SIZE]; + memcpy(check+5,MAC,4); + bool isOK; + isOK = sendCmdGetResponseWithRetries(check, sizeof(check), resp, 4, 6); + cmd_send(CMD_ACK,isOK,0,0,0,0); +} +bool iClass_ReadBlock(uint8_t blockNo, uint8_t *readdata) { + uint8_t readcmd[] = {ICLASS_CMD_READ_OR_IDENTIFY, blockNo, 0x00, 0x00}; //0x88, 0x00 // can i use 0C? + char bl = blockNo; + uint16_t rdCrc = iclass_crc16(&bl, 1); + readcmd[2] = rdCrc >> 8; + readcmd[3] = rdCrc & 0xff; + uint8_t resp[] = {0,0,0,0,0,0,0,0,0,0}; + bool isOK = false; + + //readcmd[1] = blockNo; + isOK = sendCmdGetResponseWithRetries(readcmd, sizeof(readcmd), resp, 10, 10); + memcpy(readdata, resp, sizeof(resp)); + + return isOK; +} - // Now give it time to spin up. - // Signal field is on with the appropriate LED - FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_ISO14443A | FPGA_HF_ISO14443A_READER_MOD); - SpinDelay(200); +void iClass_ReadBlk(uint8_t blockno) { + uint8_t readblockdata[] = {0,0,0,0,0,0,0,0,0,0}; + bool isOK = false; + isOK = iClass_ReadBlock(blockno, readblockdata); + cmd_send(CMD_ACK, isOK, 0, 0, readblockdata, 8); +} - LED_A_ON(); +void iClass_Dump(uint8_t blockno, uint8_t numblks) { + uint8_t readblockdata[] = {0,0,0,0,0,0,0,0,0,0}; + bool isOK = false; + uint8_t blkCnt = 0; - for(int i=0;i<1;i++) { - - if(traceLen > TRACE_SIZE) { - DbpString("Trace full"); + BigBuf_free(); + uint8_t *dataout = BigBuf_malloc(255*8); + if (dataout == NULL){ + Dbprintf("out of memory"); + OnError(1); + return; + } + memset(dataout,0xFF,255*8); + + for (;blkCnt < numblks; blkCnt++) { + isOK = iClass_ReadBlock(blockno+blkCnt, readblockdata); + if (!isOK || (readblockdata[0] == 0xBB || readblockdata[7] == 0xBB || readblockdata[2] == 0xBB)) { //try again + isOK = iClass_ReadBlock(blockno+blkCnt, readblockdata); + if (!isOK) { + Dbprintf("Block %02X failed to read", blkCnt+blockno); break; } - - if (BUTTON_PRESS()) break; - - // Send act_all - ReaderTransmitIClass(act_all, 1); - // Card present? - if(ReaderReceiveIClass(resp)) { - ReaderTransmitIClass(identify, 1); - if(ReaderReceiveIClass(resp) == 10) { - // Select card - memcpy(&select[1],resp,8); - ReaderTransmitIClass(select, sizeof(select)); - - if(ReaderReceiveIClass(resp) == 10) { - Dbprintf(" Selected CSN: %02x %02x %02x %02x %02x %02x %02x %02x", - resp[0], resp[1], resp[2], - resp[3], resp[4], resp[5], - resp[6], resp[7]); - } - // Card selected - Dbprintf("Readcheck on Sector 2"); - ReaderTransmitIClass(readcheck_cc, sizeof(readcheck_cc)); - if(ReaderReceiveIClass(resp) == 8) { - Dbprintf(" CC: %02x %02x %02x %02x %02x %02x %02x %02x", - resp[0], resp[1], resp[2], - resp[3], resp[4], resp[5], - resp[6], resp[7]); - }else return; - Dbprintf("Authenticate"); - //for now replay captured auth (as cc not updated) - memcpy(check+5,MAC,4); - Dbprintf(" AA: %02x %02x %02x %02x", - check[5], check[6], check[7],check[8]); - ReaderTransmitIClass(check, sizeof(check)); - if(ReaderReceiveIClass(resp) == 4) { - Dbprintf(" AR: %02x %02x %02x %02x", - resp[0], resp[1], resp[2],resp[3]); + } + memcpy(dataout+(blkCnt*8),readblockdata,8); + } + //return pointer to dump memory in arg3 + cmd_send(CMD_ACK,isOK,blkCnt,BigBuf_max_traceLen(),0,0); + FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); + LEDsoff(); + BigBuf_free(); +} + +bool iClass_WriteBlock_ext(uint8_t blockNo, uint8_t *data) { + uint8_t write[] = { ICLASS_CMD_UPDATE, blockNo, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; + //uint8_t readblockdata[10]; + //write[1] = blockNo; + memcpy(write+2, data, 12); // data + mac + uint8_t resp[] = {0,0,0,0,0,0,0,0,0,0}; + bool isOK; + isOK = sendCmdGetResponseWithRetries(write,sizeof(write),resp,sizeof(resp),10); + if (isOK) { + //Dbprintf("WriteResp: %02X%02X%02X%02X%02X%02X%02X%02X%02X%02X",resp[0],resp[1],resp[2],resp[3],resp[4],resp[5],resp[6],resp[7],resp[8],resp[9]); + if (memcmp(write+2,resp,8)) { + //error try again + isOK = sendCmdGetResponseWithRetries(write,sizeof(write),resp,sizeof(resp),10); + } + } + return isOK; +} + +void iClass_WriteBlock(uint8_t blockNo, uint8_t *data) { + bool isOK = iClass_WriteBlock_ext(blockNo, data); + if (isOK){ + Dbprintf("Write block [%02x] successful",blockNo); }else { - Dbprintf("Error: Authentication Fail!"); - return; - } - Dbprintf("Write Block"); - - //read configuration for max block number - read_success=false; - read[1]=1; - uint8_t *blockno=&read[1]; - crc = iclass_crc16((char *)blockno,1); - read[2] = crc >> 8; - read[3] = crc & 0xff; - while(!read_success){ - ReaderTransmitIClass(read, sizeof(read)); - if(ReaderReceiveIClass(resp) == 10) { - read_success=true; - mem=resp[5]; - memory.k16= (mem & 0x80); - memory.book= (mem & 0x20); - memory.k2= (mem & 0x8); - memory.lockauth= (mem & 0x2); - memory.keyaccess= (mem & 0x1); + Dbprintf("Write block [%02x] failed",blockNo); + } + cmd_send(CMD_ACK,isOK,0,0,0,0); +} - } - } - if (memory.k16){ - cardsize=255; - }else cardsize=32; - //check card_size - - memcpy(write+1,blockNo,1); - memcpy(write+2,data,8); - memcpy(write+10,mac,4); - while(!send_success){ - ReaderTransmitIClass(write, sizeof(write)); - if(ReaderReceiveIClass(resp) == 10) { - write_success=true; - } - }// +void iClass_Clone(uint8_t startblock, uint8_t endblock, uint8_t *data) { + int i; + int written = 0; + int total_block = (endblock - startblock) + 1; + for (i = 0; i < total_block;i++){ + // block number + if (iClass_WriteBlock_ext(i+startblock, data+(i*12))){ + Dbprintf("Write block [%02x] successful",i + startblock); + written++; + } else { + if (iClass_WriteBlock_ext(i+startblock, data+(i*12))){ + Dbprintf("Write block [%02x] successful",i + startblock); + written++; + } else { + Dbprintf("Write block [%02x] failed",i + startblock); + } } - WDT_HIT(); } - - LED_A_OFF(); -}*/ + if (written == total_block) + Dbprintf("Clone complete"); + else + Dbprintf("Clone incomplete"); + + cmd_send(CMD_ACK,1,0,0,0,0); + FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); + LEDsoff(); +} diff --git a/armsrc/iso14443a.c b/armsrc/iso14443a.c index a723f502..71f000d0 100644 --- a/armsrc/iso14443a.c +++ b/armsrc/iso14443a.c @@ -947,10 +947,10 @@ void SimulateIso14443aTag(int tagType, int flags, byte_t* data) uint8_t sak; // PACK response to PWD AUTH for EV1/NTAG - uint8_t response8[4]; + uint8_t response8[4] = {0,0,0,0}; // The first response contains the ATQA (note: bytes are transmitted in reverse order). - uint8_t response1[2]; + uint8_t response1[2] = {0,0}; switch (tagType) { case 1: { // MIFARE Classic @@ -1299,7 +1299,8 @@ void SimulateIso14443aTag(int tagType, int flags, byte_t* data) if ( tagType == 7 ) { p_response = &responses[8]; // PACK response uint32_t pwd = bytes_to_num(receivedCmd+1,4); - Dbprintf("Auth attempt: %08x", pwd); + + if ( MF_DBGLEVEL >= 3) Dbprintf("Auth attempt: %08x", pwd); } } else { @@ -2206,28 +2207,6 @@ int32_t dist_nt(uint32_t nt1, uint32_t nt2) { return(-99999); // either nt1 or nt2 are invalid nonces } -int32_t dist_nt_ex32(uint32_t nt1, uint32_t nt2, bool *result) { - - uint16_t i; - uint32_t nttmp1, nttmp2; - - if (nt1 == nt2) return 0; - - nttmp1 = nt1; - nttmp2 = nt2; - - *result = true; - for (i = 1; i < 0xFFFFFFFF; i++) { - nttmp1 = prng_successor(nttmp1, 1); - if (nttmp1 == nt2) return i; - - nttmp2 = prng_successor(nttmp2, 1); - if (nttmp2 == nt1) return -i; - } - - *result = false; - return(-99999); // either nt1 or nt2 are invalid nonces -} //----------------------------------------------------------------------------- // Recover several bits of the cypher stream. This implements (first stages of) diff --git a/armsrc/lfops.c b/armsrc/lfops.c index 8feaa6ae..74086d36 100644 --- a/armsrc/lfops.c +++ b/armsrc/lfops.c @@ -2125,3 +2125,260 @@ void CopyViKingtoT55x7(uint32_t block1,uint32_t block2) DbpString("DONE!"); } + +#define T0_PCF 8 //period for the pcf7931 in us + +/* Write on a byte of a PCF7931 tag + * @param address : address of the block to write + @param byte : address of the byte to write + @param data : data to write + */ +void WritePCF7931(uint8_t pass1, uint8_t pass2, uint8_t pass3, uint8_t pass4, uint8_t pass5, uint8_t pass6, uint8_t pass7, uint16_t init_delay, int32_t l, int32_t p, uint8_t address, uint8_t byte, uint8_t data) +{ + + uint32_t tab[1024]={0}; // data times frame + uint32_t u = 0; + uint8_t parity = 0; + bool comp = 0; + + + //BUILD OF THE DATA FRAME + + //alimentation of the tag (time for initializing) + AddPatternPCF7931(init_delay, 0, 8192/2*T0_PCF, tab); + + //PMC + Dbprintf("Initialization delay : %d us", init_delay); + AddPatternPCF7931(8192/2*T0_PCF + 319*T0_PCF+70, 3*T0_PCF, 29*T0_PCF, tab); + + Dbprintf("Offsets : %d us on the low pulses width, %d us on the low pulses positions", l, p); + + //password indication bit + AddBitPCF7931(1, tab, l, p); + + + //password (on 56 bits) + Dbprintf("Password (LSB first on each byte) : %02x %02x %02x %02x %02x %02x %02x", pass1,pass2,pass3,pass4,pass5,pass6,pass7); + AddBytePCF7931(pass1, tab, l, p); + AddBytePCF7931(pass2, tab, l, p); + AddBytePCF7931(pass3, tab, l, p); + AddBytePCF7931(pass4, tab, l, p); + AddBytePCF7931(pass5, tab, l, p); + AddBytePCF7931(pass6, tab, l, p); + AddBytePCF7931(pass7, tab, l, p); + + + //programming mode (0 or 1) + AddBitPCF7931(0, tab, l, p); + + //block adress on 6 bits + Dbprintf("Block address : %02x", address); + for (u=0; u<6; u++) + { + if (address&(1< 0xFFFF){ + tab[u] -= 0xFFFF; + comp = 0; + } + } + } + + SendCmdPCF7931(tab); +} + + + +/* Send a trame to a PCF7931 tags + * @param tab : array of the data frame + */ + +void SendCmdPCF7931(uint32_t * tab){ + uint16_t u=0; + uint16_t tempo=0; + + Dbprintf("SENDING DATA FRAME..."); + + FpgaDownloadAndGo(FPGA_BITSTREAM_LF); + + FpgaSendCommand(FPGA_CMD_SET_DIVISOR, 95); //125Khz + + FpgaWriteConfWord(FPGA_MAJOR_MODE_LF_PASSTHRU ); + + LED_A_ON(); + + // steal this pin from the SSP and use it to control the modulation + AT91C_BASE_PIOA->PIO_PER = GPIO_SSC_DOUT; + AT91C_BASE_PIOA->PIO_OER = GPIO_SSC_DOUT; + + //initialization of the timer + AT91C_BASE_PMC->PMC_PCER |= (0x1 << 12) | (0x1 << 13) | (0x1 << 14); + AT91C_BASE_TCB->TCB_BMR = AT91C_TCB_TC0XC0S_NONE | AT91C_TCB_TC1XC1S_TIOA0 | AT91C_TCB_TC2XC2S_NONE; + AT91C_BASE_TC0->TC_CCR = AT91C_TC_CLKDIS; // timer disable + AT91C_BASE_TC0->TC_CMR = AT91C_TC_CLKS_TIMER_DIV3_CLOCK; //clock at 48/32 MHz + AT91C_BASE_TC0->TC_CCR = AT91C_TC_CLKEN; + AT91C_BASE_TCB->TCB_BCR = 1; + + + tempo = AT91C_BASE_TC0->TC_CV; + for(u=0;tab[u]!= 0;u+=3){ + + + // modulate antenna + HIGH(GPIO_SSC_DOUT); + while(tempo != tab[u]){ + tempo = AT91C_BASE_TC0->TC_CV; + } + + // stop modulating antenna + LOW(GPIO_SSC_DOUT); + while(tempo != tab[u+1]){ + tempo = AT91C_BASE_TC0->TC_CV; + } + + + // modulate antenna + HIGH(GPIO_SSC_DOUT); + while(tempo != tab[u+2]){ + tempo = AT91C_BASE_TC0->TC_CV; + } + + + } + + LED_A_OFF(); + FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); + SpinDelay(200); + + + AT91C_BASE_TC0->TC_CCR = AT91C_TC_CLKDIS; // timer disable + DbpString("FINISH !"); + DbpString("(Could be usefull to send the same trame many times)"); + LED(0xFFFF, 1000); +} + + +/* Add a byte for building the data frame of PCF7931 tags + * @param b : byte to add + * @param tab : array of the data frame + * @param l : offset on low pulse width + * @param p : offset on low pulse positioning + */ + +bool AddBytePCF7931(uint8_t byte, uint32_t * tab, int32_t l, int32_t p){ + + uint32_t u; + for (u=0; u<8; u++) + { + if (byte&(1< [-b] <0A 0B 0C ... hex>"); + PrintAndLog("Usage: hf 14a raw [-r] [-c] [-p] [-a] [-T] [-t] [-b] <0A 0B 0C ... hex>"); PrintAndLog(" -r do not read response"); PrintAndLog(" -c calculate and append CRC"); PrintAndLog(" -p leave the signal field ON after receive"); diff --git a/client/cmdhf14b.c b/client/cmdhf14b.c index d9e56693..7b67f8c2 100644 --- a/client/cmdhf14b.c +++ b/client/cmdhf14b.c @@ -73,10 +73,14 @@ int CmdSrix4kRead(const char *Cmd) } int rawClose(void){ + UsbCommand resp; UsbCommand c = {CMD_ISO_14443B_COMMAND, {0, 0, 0}}; clearCommandBuffer(); SendCommand(&c); + if (!WaitForResponseTimeout(CMD_ACK,&resp,1000)) { return 0; + } + return 0; } int HF14BCmdRaw(bool reply, bool *crc, bool power, uint8_t *data, uint8_t *datalen, bool verbose){ diff --git a/client/cmdhficlass.c b/client/cmdhficlass.c index e8ba68f1..f17f96ca 100644 --- a/client/cmdhficlass.c +++ b/client/cmdhficlass.c @@ -31,11 +31,29 @@ #include "loclass/fileutils.h" #include "protocols.h" #include "usb_cmd.h" +#include "cmdhfmfu.h" + +#define llX PRIx64 static int CmdHelp(const char *Cmd); -int xorbits_8(uint8_t val) -{ +#define ICLASS_KEYS_MAX 8 +static uint8_t iClass_Key_Table[ICLASS_KEYS_MAX][8] = { + { 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 }, + { 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 }, + { 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 }, + { 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 }, + { 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 }, + { 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 }, + { 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 }, + { 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } +}; + +typedef struct iclass_block { + uint8_t d[8]; +} iclass_block_t; + +int xorbits_8(uint8_t val) { uint8_t res = val ^ (val >> 1); //1st pass res = res ^ (res >> 1); // 2nd pass res = res ^ (res >> 2); // 3rd pass @@ -43,20 +61,18 @@ int xorbits_8(uint8_t val) return res & 1; } -int CmdHFiClassList(const char *Cmd) -{ +int CmdHFiClassList(const char *Cmd) { PrintAndLog("Deprecated command, use 'hf list iclass' instead"); return 0; } -int CmdHFiClassSnoop(const char *Cmd) -{ +int CmdHFiClassSnoop(const char *Cmd) { UsbCommand c = {CMD_SNOOP_ICLASS}; SendCommand(&c); return 0; } -int usage_hf_iclass_sim() -{ + +int usage_hf_iclass_sim(void) { PrintAndLog("Usage: hf iclass sim