-NOTICE:
-(2014-03-26)
-This is now the official Proxmark repository!
-
-INTRODUCTION:
-
-The proxmark3 is a powerful general purpose RFID tool, the size of a deck
-of cards, designed to snoop, listen and emulate everything from
-Low Frequency (125kHz) to High Frequency (13.56MHz) tags.
-
-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.
-
-RESOURCES:
-
- * 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:
-
-The tools required to build or run the project will vary depending on
-your operating system. Please refer to the Wiki for details.
+The iceman fork.
- * https://github.com/Proxmark/proxmark3/wiki
-
-OBTAINING HARDWARE:
-
-The Proxmark 3 is available for purcahse (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.
+NOTICE:
-The printed circuit board artwork is also available, as Gerbers and an
-Excellon drill file.
+The official Proxmark repository is found here: https://github.com/Proxmark/proxmark3
-LICENSING:
+NEWS:
-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.
+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 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.
+ * 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.
-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
+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:
+I do tend to rename and move stuff around, the official PM3-GUI from Gaucho will not work so well. *sorry*
-Jonathan Westhues
-user jwesthues, at host cq.cx
+
+DEVELOPMENT:
-May 2007, Cambridge MA
+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]
+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.
+
+
+
+January 2015, Sweden
+iceman at host iuse.se
\ No newline at end of file
// LCD code
//-----------------------------------------------------------------------------
-#include "proxmark3.h"
+#include "../include/proxmark3.h"
#include "apps.h"
#include "LCD.h"
#include "fonts.h"
BigBuf.c \
optimized_cipher.c
+
# stdint.h provided locally until GCC 4.5 becomes C99 compliant
APP_CFLAGS += -I.
// executes.
//-----------------------------------------------------------------------------
-#include "usb_cdc.h"
-#include "cmd.h"
+#include "../common/usb_cdc.h"
+#include "../common/cmd.h"
-#include "proxmark3.h"
+#include "../include/proxmark3.h"
#include "apps.h"
#include "util.h"
#include "printf.h"
#include "string.h"
-
#include <stdarg.h>
#include "legicrf.h"
-#include <hitag2.h>
+#include "../include/hitag2.h"
#include "lfsampling.h"
#include "BigBuf.h"
#ifdef WITH_LCD
int i, adcval = 0, peak = 0, peakv = 0, peakf = 0; //ptr = 0
int vLf125 = 0, vLf134 = 0, vHf = 0; // in mV
- LED_B_ON();
+ LED_B_ON();
/*
* Sweeps the useful LF range of the proxmark from
for (i=18; i >= 0; i--) LF_Results[i] = 0;
- LED_A_ON();
+ LED_A_ON();
// Let the FPGA drive the high-frequency antenna around 13.56 MHz.
FpgaDownloadAndGo(FPGA_BITSTREAM_HF);
FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_READER_RX_XCORR);
cmd_send(CMD_MEASURED_ANTENNA_TUNING, vLf125 | (vLf134<<16), vHf, peakf | (peakv<<16), LF_Results, 256);
FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
- LED_A_OFF();
- LED_B_OFF();
- return;
+ LED_A_OFF();
+ LED_B_OFF();
+ return;
}
void MeasureAntennaTuningHf(void)
for (;;)
{
usb_poll();
- WDT_HIT();
+ WDT_HIT();
// Was our button held down or pressed?
int button_pressed = BUTTON_HELD(1000);
{
UsbCommand *c = (UsbCommand *)packet;
-// Dbprintf("received %d bytes, with command: 0x%04x and args: %d %d %d",len,c->cmd,c->arg[0],c->arg[1],c->arg[2]);
+ //Dbprintf("received %d bytes, with command: 0x%04x and args: %d %d %d",len,c->cmd,c->arg[0],c->arg[1],c->arg[2]);
switch(c->cmd) {
#ifdef WITH_LF
WriteTItag(c->arg[0],c->arg[1],c->arg[2]);
break;
case CMD_SIMULATE_TAG_125K:
- LED_A_ON();
- SimulateTagLowFrequency(c->arg[0], c->arg[1], 1);
- LED_A_OFF();
+ SimulateTagLowFrequency(c->arg[0], c->arg[1], 0);
+ //SimulateTagLowFrequencyA(c->arg[0], c->arg[1]);
break;
case CMD_LF_SIMULATE_BIDIR:
SimulateTagLowFrequencyBidir(c->arg[0], c->arg[1]);
EPA_PACE_Collect_Nonce(c);
break;
+ // case CMD_EPA_:
+ // EpaFoo(c);
+ // break;
+
case CMD_READER_MIFARE:
ReaderMifare(c->arg[0]);
break;
break;
case CMD_MIFAREU_READCARD:
MifareUReadCard(c->arg[0], c->arg[1], c->d.asBytes);
- break;
+ break;
case CMD_MIFAREUC_READCARD:
MifareUReadCard(c->arg[0], c->arg[1], c->d.asBytes);
break;
ReaderIClass(c->arg[0]);
break;
case CMD_READER_ICLASS_REPLAY:
- ReaderIClass_Replay(c->arg[0], c->d.asBytes);
+ ReaderIClass_Replay(c->arg[0], c->d.asBytes);
break;
case CMD_ICLASS_EML_MEMSET:
emlSet(c->d.asBytes,c->arg[0], c->arg[1]);
LED_A_OFF();
// Init USB device
- usb_enable();
+ usb_enable();
// The FPGA gets its clock from us from PCK0 output, so set that up.
AT91C_BASE_PIOA->PIO_BSR = GPIO_PCK0;
size_t rx_len;
for(;;) {
- if (usb_poll()) {
- rx_len = usb_read(rx,sizeof(UsbCommand));
- if (rx_len) {
- UsbPacketReceived(rx,rx_len);
- }
- }
+ if (usb_poll()) {
+ rx_len = usb_read(rx,sizeof(UsbCommand));
+ if (rx_len) {
+ UsbPacketReceived(rx,rx_len);
+ }
+ }
WDT_HIT();
#ifdef WITH_LF
#include <stdint.h>
#include <stddef.h>
-#include "common.h"
-#include "hitag2.h"
-#include "mifare.h"
+#include <stdlib.h>
+#include <sys/types.h>
+#include <string.h>
+#include <strings.h>
#include "../common/crc32.h"
#include "BigBuf.h"
+#include "../include/hitag2.h"
extern const uint8_t OddByteParity[256];
extern int rsamples; // = 0;
void WriteTItag(uint32_t idhi, uint32_t idlo, uint16_t crc);
void AcquireTiType(void);
void AcquireRawBitsTI(void);
-void SimulateTagLowFrequency(int period, int gap, int ledcontrol);
+void SimulateTagLowFrequency( uint16_t period, uint32_t gap, uint8_t ledcontrol);
+//void SimulateTagLowFrequencyA(int period, int gap);
+
void CmdHIDsimTAG(int hi, int lo, int ledcontrol);
void CmdFSKsimTAG(uint16_t arg1, uint16_t arg2, size_t size, uint8_t *BitStream);
void CmdASKsimTag(uint16_t arg1, uint16_t arg2, size_t size, uint8_t *BitStream);
void T55xxWriteBlock(uint32_t Data, uint32_t Block, uint32_t Pwd, uint8_t PwdMode);
void T55xxReadBlock(uint32_t Block, uint32_t Pwd, uint8_t PwdMode );
void T55xxReadTrace(void);
+void TurnReadLFOn();
int DemodPCF7931(uint8_t **outBlocks);
int IsBlock0PCF7931(uint8_t *Block);
int IsBlock1PCF7931(uint8_t *Block);
/* crapto1.c\r
\r
- This program is free software; you can redistribute it and/or\r
- modify it under the terms of the GNU General Public License\r
- as published by the Free Software Foundation; either version 2\r
- of the License, or (at your option) any later version.\r
-\r
- This program is distributed in the hope that it will be useful,\r
- but WITHOUT ANY WARRANTY; without even the implied warranty of\r
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\r
- GNU General Public License for more details.\r
-\r
- You should have received a copy of the GNU General Public License\r
- along with this program; if not, write to the Free Software\r
- Foundation, Inc., 51 Franklin Street, Fifth Floor,\r
- Boston, MA 02110-1301, US$\r
-\r
- Copyright (C) 2008-2008 bla <blapost@gmail.com>\r
+ This program is free software; you can redistribute it and/or\r
+ modify it under the terms of the GNU General Public License\r
+ as published by the Free Software Foundation; either version 2\r
+ of the License, or (at your option) any later version.\r
+\r
+ This program is distributed in the hope that it will be useful,\r
+ but WITHOUT ANY WARRANTY; without even the implied warranty of\r
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\r
+ GNU General Public License for more details.\r
+\r
+ You should have received a copy of the GNU General Public License\r
+ along with this program; if not, write to the Free Software\r
+ Foundation, Inc., 51 Franklin Street, Fifth Floor,\r
+ Boston, MA 02110-1301, US$\r
+\r
+ Copyright (C) 2008-2008 bla <blapost@gmail.com>\r
*/\r
#include "crapto1.h"\r
#include <stdlib.h>\r
static uint8_t filterlut[1 << 20];\r
static void __attribute__((constructor)) fill_lut()\r
{\r
- uint32_t i;\r
- for(i = 0; i < 1 << 20; ++i)\r
- filterlut[i] = filter(i);\r
+ uint32_t i;\r
+ for(i = 0; i < 1 << 20; ++i)\r
+ filterlut[i] = filter(i);\r
}\r
#define filter(x) (filterlut[(x) & 0xfffff])\r
#endif\r
eks >>= 1;\r
in >>= 2;\r
extend_table(o_head, &o_tail, oks & 1, LF_POLY_EVEN << 1 | 1,\r
- LF_POLY_ODD << 1, 0);\r
+ LF_POLY_ODD << 1, 0);\r
if(o_head > o_tail)\r
return sl;\r
\r
extend_table(e_head, &e_tail, eks & 1, LF_POLY_ODD,\r
- LF_POLY_EVEN << 1 | 1, in & 3);\r
+ LF_POLY_EVEN << 1 | 1, in & 3);\r
if(e_head > e_tail)\r
return sl;\r
}\r
o_tail = binsearch(o_head, o = o_tail);\r
e_tail = binsearch(e_head, e = e_tail);\r
sl = recover(o_tail--, o, oks,\r
- e_tail--, e, eks, rem, sl, in);\r
+ e_tail--, e, eks, rem, sl, in);\r
}\r
else if(*o_tail > *e_tail)\r
o_tail = binsearch(o_head, o_tail) - 1;\r
*/\r
static struct Crypto1State*\r
check_pfx_parity(uint32_t prefix, uint32_t rresp, uint8_t parities[8][8],\r
- uint32_t odd, uint32_t even, struct Crypto1State* sl)\r
+ uint32_t odd, uint32_t even, struct Crypto1State* sl)\r
{\r
uint32_t ks1, nr, ks2, rr, ks3, c, good = 1;\r
\r
\r
odd = lfsr_prefix_ks(ks, 1);\r
even = lfsr_prefix_ks(ks, 0);\r
-\r
+ \r
s = statelist = malloc((sizeof *statelist) << 20);\r
if(!s || !odd || !even) {\r
free(statelist);\r
statelist = 0;\r
- goto out;\r
+ goto out;\r
}\r
\r
for(o = odd; *o + 1; ++o)\r
--- /dev/null
+/*-
+ * Copyright (C) 2010, Romain Tartiere.
+ *
+ * This program is free software: you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as published by the
+ * Free Software Foundation, either version 3 of the License, or (at your
+ * option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>
+ *
+ * $Id$
+ */
+
+/*
+ * This implementation was written based on information provided by the
+ * following documents:
+ *
+ * NIST Special Publication 800-38B
+ * Recommendation for Block Cipher Modes of Operation: The CMAC Mode for Authentication
+ * May 2005
+ */
+#include "desfire_crypto.h"
+
+static void xor (const uint8_t *ivect, uint8_t *data, const size_t len);
+
+static size_t key_macing_length (desfirekey_t key);
+
+static void xor (const uint8_t *ivect, uint8_t *data, const size_t len) {
+ for (size_t i = 0; i < len; i++) {
+ data[i] ^= ivect[i];
+ }
+}
+
+void cmac_generate_subkeys ( desfirekey_t key) {
+ int kbs = key_block_size (key);
+ const uint8_t R = (kbs == 8) ? 0x1B : 0x87;
+
+ uint8_t l[kbs];
+ memset (l, 0, kbs);
+
+ uint8_t ivect[kbs];
+ memset (ivect, 0, kbs);
+
+ mifare_cypher_blocks_chained (NULL, key, ivect, l, kbs, MCD_RECEIVE, MCO_ENCYPHER);
+
+ bool xor = false;
+
+ // Used to compute CMAC on complete blocks
+ memcpy (key->cmac_sk1, l, kbs);
+ xor = l[0] & 0x80;
+ lsl (key->cmac_sk1, kbs);
+ if (xor)
+ key->cmac_sk1[kbs-1] ^= R;
+
+ // Used to compute CMAC on the last block if non-complete
+ memcpy (key->cmac_sk2, key->cmac_sk1, kbs);
+ xor = key->cmac_sk1[0] & 0x80;
+ lsl (key->cmac_sk2, kbs);
+ if (xor)
+ key->cmac_sk2[kbs-1] ^= R;
+}
+
+void cmac (const desfirekey_t key, uint8_t *ivect, const uint8_t *data, size_t len, uint8_t *cmac) {
+ int kbs = key_block_size (key);
+ uint8_t *buffer = malloc (padded_data_length (len, kbs));
+
+ memcpy (buffer, data, len);
+
+ if ((!len) || (len % kbs)) {
+ buffer[len++] = 0x80;
+ while (len % kbs) {
+ buffer[len++] = 0x00;
+ }
+ xor (key->cmac_sk2, buffer + len - kbs, kbs);
+ } else {
+ xor (key->cmac_sk1, buffer + len - kbs, kbs);
+ }
+
+ mifare_cypher_blocks_chained (NULL, key, ivect, buffer, len, MCD_SEND, MCO_ENCYPHER);
+
+ memcpy (cmac, ivect, kbs);
+}
+
+size_t key_block_size (const desfirekey_t key) {
+ size_t block_size = 8;
+
+ switch (key->type) {
+ case T_DES:
+ case T_3DES:
+ case T_3K3DES:
+ block_size = 8;
+ break;
+ case T_AES:
+ block_size = 16;
+ break;
+ }
+
+ return block_size;
+}
+
+/*
+ * Size of MACing produced with the key.
+ */
+static size_t key_macing_length (const desfirekey_t key) {
+ size_t mac_length = MAC_LENGTH;
+
+ switch (key->type) {
+ case T_DES:
+ case T_3DES:
+ mac_length = MAC_LENGTH;
+ break;
+ case T_3K3DES:
+ case T_AES:
+ mac_length = CMAC_LENGTH;
+ break;
+ }
+
+ return mac_length;
+}
+
+/*
+ * Size required to store nbytes of data in a buffer of size n*block_size.
+ */
+size_t padded_data_length (const size_t nbytes, const size_t block_size) {
+ if ((!nbytes) || (nbytes % block_size))
+ return ((nbytes / block_size) + 1) * block_size;
+ else
+ return nbytes;
+}
+
+/*
+ * Buffer size required to MAC nbytes of data
+ */
+size_t maced_data_length (const desfirekey_t key, const size_t nbytes) {
+ return nbytes + key_macing_length (key);
+}
+/*
+ * Buffer size required to encipher nbytes of data and a two bytes CRC.
+ */
+size_t enciphered_data_length (const desfiretag_t tag, const size_t nbytes, int communication_settings) {
+ size_t crc_length = 0;
+ if (!(communication_settings & NO_CRC)) {
+ switch (DESFIRE(tag)->authentication_scheme) {
+ case AS_LEGACY:
+ crc_length = 2;
+ break;
+ case AS_NEW:
+ crc_length = 4;
+ break;
+ }
+ }
+
+ size_t block_size = DESFIRE(tag)->session_key ? key_block_size (DESFIRE(tag)->session_key) : 1;
+
+ return padded_data_length (nbytes + crc_length, block_size);
+}
+
+void* mifare_cryto_preprocess_data (desfiretag_t tag, void *data, size_t *nbytes, off_t offset, int communication_settings) {
+ uint8_t *res = data;
+ uint8_t mac[4];
+ size_t edl;
+ bool append_mac = true;
+ desfirekey_t key = DESFIRE(tag)->session_key;
+
+ if (!key)
+ return data;
+
+ switch (communication_settings & MDCM_MASK) {
+ case MDCM_PLAIN:
+ if (AS_LEGACY == DESFIRE(tag)->authentication_scheme)
+ break;
+
+ /*
+ * When using new authentication methods, PLAIN data transmission from
+ * the PICC to the PCD are CMACed, so we have to maintain the
+ * cryptographic initialisation vector up-to-date to check data
+ * integrity later.
+ *
+ * The only difference with CMACed data transmission is that the CMAC
+ * is not apended to the data send by the PCD to the PICC.
+ */
+
+ append_mac = false;
+
+ /* pass through */
+ case MDCM_MACED:
+ switch (DESFIRE(tag)->authentication_scheme) {
+ case AS_LEGACY:
+ if (!(communication_settings & MAC_COMMAND))
+ break;
+
+ /* pass through */
+ edl = padded_data_length (*nbytes - offset, key_block_size (DESFIRE(tag)->session_key)) + offset;
+
+ // Fill in the crypto buffer with data ...
+ memcpy (res, data, *nbytes);
+ // ... and 0 padding
+ memset (res + *nbytes, 0, edl - *nbytes);
+
+ mifare_cypher_blocks_chained (tag, NULL, NULL, res + offset, edl - offset, MCD_SEND, MCO_ENCYPHER);
+
+ memcpy (mac, res + edl - 8, 4);
+
+ // Copy again provided data (was overwritten by mifare_cypher_blocks_chained)
+ memcpy (res, data, *nbytes);
+
+ if (!(communication_settings & MAC_COMMAND))
+ break;
+ // Append MAC
+ size_t bla = maced_data_length (DESFIRE(tag)->session_key, *nbytes - offset) + offset;
+ bla++;
+
+ memcpy (res + *nbytes, mac, 4);
+
+ *nbytes += 4;
+ break;
+ case AS_NEW:
+ if (!(communication_settings & CMAC_COMMAND))
+ break;
+ cmac (key, DESFIRE (tag)->ivect, res, *nbytes, DESFIRE (tag)->cmac);
+
+ if (append_mac) {
+ maced_data_length (key, *nbytes);
+
+ memcpy (res, data, *nbytes);
+ memcpy (res + *nbytes, DESFIRE (tag)->cmac, CMAC_LENGTH);
+ *nbytes += CMAC_LENGTH;
+ }
+ break;
+ }
+
+ break;
+ case MDCM_ENCIPHERED:
+ /* |<-------------- data -------------->|
+ * |<--- offset -->| |
+ * +---------------+--------------------+-----+---------+
+ * | CMD + HEADERS | DATA TO BE SECURED | CRC | PADDING |
+ * +---------------+--------------------+-----+---------+ ----------------
+ * | |<~~~~v~~~~~~~~~~~~~>| ^ | | (DES / 3DES)
+ * | | `---- crc16() ----' | |
+ * | | | ^ | | ----- *or* -----
+ * |<~~~~~~~~~~~~~~~~~~~~v~~~~~~~~~~~~~>| ^ | | (3K3DES / AES)
+ * | `---- crc32() ----' | |
+ * | | ---- *then* ----
+ * |<---------------------------------->|
+ * encypher()/decypher()
+ */
+
+ if (!(communication_settings & ENC_COMMAND))
+ break;
+ edl = enciphered_data_length (tag, *nbytes - offset, communication_settings) + offset;
+
+ // Fill in the crypto buffer with data ...
+ memcpy (res, data, *nbytes);
+ if (!(communication_settings & NO_CRC)) {
+ // ... CRC ...
+ switch (DESFIRE (tag)->authentication_scheme) {
+ case AS_LEGACY:
+ AppendCrc14443a(res + offset, *nbytes - offset);
+ *nbytes += 2;
+ break;
+ case AS_NEW:
+ crc32_append (res, *nbytes);
+ *nbytes += 4;
+ break;
+ }
+ }
+ // ... and padding
+ memset (res + *nbytes, 0, edl - *nbytes);
+
+ *nbytes = edl;
+
+ mifare_cypher_blocks_chained (tag, NULL, NULL, res + offset, *nbytes - offset, MCD_SEND, (AS_NEW == DESFIRE(tag)->authentication_scheme) ? MCO_ENCYPHER : MCO_DECYPHER);
+ break;
+ default:
+
+ *nbytes = -1;
+ res = NULL;
+ break;
+ }
+
+ return res;
+
+}
+
+void* mifare_cryto_postprocess_data (desfiretag_t tag, void *data, ssize_t *nbytes, int communication_settings)
+{
+ void *res = data;
+ size_t edl;
+ void *edata = NULL;
+ uint8_t first_cmac_byte = 0x00;
+
+ desfirekey_t key = DESFIRE(tag)->session_key;
+
+ if (!key)
+ return data;
+
+ // Return directly if we just have a status code.
+ if (1 == *nbytes)
+ return res;
+
+ switch (communication_settings & MDCM_MASK) {
+ case MDCM_PLAIN:
+
+ if (AS_LEGACY == DESFIRE(tag)->authentication_scheme)
+ break;
+
+ /* pass through */
+ case MDCM_MACED:
+ switch (DESFIRE (tag)->authentication_scheme) {
+ case AS_LEGACY:
+ if (communication_settings & MAC_VERIFY) {
+ *nbytes -= key_macing_length (key);
+ if (*nbytes <= 0) {
+ *nbytes = -1;
+ res = NULL;
+#ifdef WITH_DEBUG
+ Dbprintf ("No room for MAC!");
+#endif
+ break;
+ }
+
+ edl = enciphered_data_length (tag, *nbytes - 1, communication_settings);
+ edata = malloc (edl);
+
+ memcpy (edata, data, *nbytes - 1);
+ memset ((uint8_t *)edata + *nbytes - 1, 0, edl - *nbytes + 1);
+
+ mifare_cypher_blocks_chained (tag, NULL, NULL, edata, edl, MCD_SEND, MCO_ENCYPHER);
+
+ if (0 != memcmp ((uint8_t *)data + *nbytes - 1, (uint8_t *)edata + edl - 8, 4)) {
+#ifdef WITH_DEBUG
+ Dbprintf ("MACing not verified");
+ hexdump ((uint8_t *)data + *nbytes - 1, key_macing_length (key), "Expect ", 0);
+ hexdump ((uint8_t *)edata + edl - 8, key_macing_length (key), "Actual ", 0);
+#endif
+ DESFIRE (tag)->last_pcd_error = CRYPTO_ERROR;
+ *nbytes = -1;
+ res = NULL;
+ }
+ }
+ break;
+ case AS_NEW:
+ if (!(communication_settings & CMAC_COMMAND))
+ break;
+ if (communication_settings & CMAC_VERIFY) {
+ if (*nbytes < 9) {
+ *nbytes = -1;
+ res = NULL;
+ break;
+ }
+ first_cmac_byte = ((uint8_t *)data)[*nbytes - 9];
+ ((uint8_t *)data)[*nbytes - 9] = ((uint8_t *)data)[*nbytes-1];
+ }
+
+ int n = (communication_settings & CMAC_VERIFY) ? 8 : 0;
+ cmac (key, DESFIRE (tag)->ivect, ((uint8_t *)data), *nbytes - n, DESFIRE (tag)->cmac);
+
+ if (communication_settings & CMAC_VERIFY) {
+ ((uint8_t *)data)[*nbytes - 9] = first_cmac_byte;
+ if (0 != memcmp (DESFIRE (tag)->cmac, (uint8_t *)data + *nbytes - 9, 8)) {
+#ifdef WITH_DEBUG
+ Dbprintf ("CMAC NOT verified :-(");
+ hexdump ((uint8_t *)data + *nbytes - 9, 8, "Expect ", 0);
+ hexdump (DESFIRE (tag)->cmac, 8, "Actual ", 0);
+#endif
+ DESFIRE (tag)->last_pcd_error = CRYPTO_ERROR;
+ *nbytes = -1;
+ res = NULL;
+ } else {
+ *nbytes -= 8;
+ }
+ }
+ break;
+ }
+
+ free (edata);
+
+ break;
+ case MDCM_ENCIPHERED:
+ (*nbytes)--;
+ bool verified = false;
+ int crc_pos = 0x00;
+ int end_crc_pos = 0x00;
+ uint8_t x;
+
+ /*
+ * AS_LEGACY:
+ * ,-----------------+-------------------------------+--------+
+ * \ BLOCK n-1 | BLOCK n | STATUS |
+ * / PAYLOAD | CRC0 | CRC1 | 0x80? | 0x000000000000 | 0x9100 |
+ * `-----------------+-------------------------------+--------+
+ *
+ * <------------ DATA ------------>
+ * FRAME = PAYLOAD + CRC(PAYLOAD) + PADDING
+ *
+ * AS_NEW:
+ * ,-------------------------------+-----------------------------------------------+--------+
+ * \ BLOCK n-1 | BLOCK n | STATUS |
+ * / PAYLOAD | CRC0 | CRC1 | CRC2 | CRC3 | 0x80? | 0x0000000000000000000000000000 | 0x9100 |
+ * `-------------------------------+-----------------------------------------------+--------+
+ * <----------------------------------- DATA ------------------------------------->|
+ *
+ * <----------------- DATA ---------------->
+ * FRAME = PAYLOAD + CRC(PAYLOAD + STATUS) + PADDING + STATUS
+ * `------------------'
+ */
+
+ mifare_cypher_blocks_chained (tag, NULL, NULL, res, *nbytes, MCD_RECEIVE, MCO_DECYPHER);
+
+ /*
+ * Look for the CRC and ensure it is followed by NULL padding. We
+ * can't start by the end because the CRC is supposed to be 0 when
+ * verified, and accumulating 0's in it should not change it.
+ */
+ switch (DESFIRE (tag)->authentication_scheme) {
+ case AS_LEGACY:
+ crc_pos = *nbytes - 8 - 1; // The CRC can be over two blocks
+ if (crc_pos < 0) {
+ /* Single block */
+ crc_pos = 0;
+ }
+ break;
+ case AS_NEW:
+ /* Move status between payload and CRC */
+ res = DESFIRE (tag)->crypto_buffer;
+ memcpy (res, data, *nbytes);
+
+ crc_pos = (*nbytes) - 16 - 3;
+ if (crc_pos < 0) {
+ /* Single block */
+ crc_pos = 0;
+ }
+ memcpy ((uint8_t *)res + crc_pos + 1, (uint8_t *)res + crc_pos, *nbytes - crc_pos);
+ ((uint8_t *)res)[crc_pos] = 0x00;
+ crc_pos++;
+ *nbytes += 1;
+ break;
+ }
+
+ do {
+ uint16_t crc16 =0x00;
+ uint32_t crc;
+ switch (DESFIRE (tag)->authentication_scheme) {
+ case AS_LEGACY:
+ end_crc_pos = crc_pos + 2;
+ AppendCrc14443a (res, end_crc_pos);
+
+ //
+
+
+ crc = crc16;
+ break;
+ case AS_NEW:
+ end_crc_pos = crc_pos + 4;
+ crc32 (res, end_crc_pos, (uint8_t *)&crc);
+ break;
+ }
+ if (!crc) {
+ verified = true;
+ for (int n = end_crc_pos; n < *nbytes - 1; n++) {
+ uint8_t byte = ((uint8_t *)res)[n];
+ if (!( (0x00 == byte) || ((0x80 == byte) && (n == end_crc_pos)) ))
+ verified = false;
+ }
+ }
+ if (verified) {
+ *nbytes = crc_pos;
+ switch (DESFIRE (tag)->authentication_scheme) {
+ case AS_LEGACY:
+ ((uint8_t *)data)[(*nbytes)++] = 0x00;
+ break;
+ case AS_NEW:
+ /* The status byte was already before the CRC */
+ break;
+ }
+ } else {
+ switch (DESFIRE (tag)->authentication_scheme) {
+ case AS_LEGACY:
+ break;
+ case AS_NEW:
+ x = ((uint8_t *)res)[crc_pos - 1];
+ ((uint8_t *)res)[crc_pos - 1] = ((uint8_t *)res)[crc_pos];
+ ((uint8_t *)res)[crc_pos] = x;
+ break;
+ }
+ crc_pos++;
+ }
+ } while (!verified && (end_crc_pos < *nbytes));
+
+ if (!verified) {
+#ifdef WITH_DEBUG
+ /* FIXME In some configurations, the file is transmitted PLAIN */
+ Dbprintf("CRC not verified in decyphered stream");
+#endif
+ DESFIRE (tag)->last_pcd_error = CRYPTO_ERROR;
+ *nbytes = -1;
+ res = NULL;
+ }
+
+ break;
+ default:
+ Dbprintf("Unknown communication settings");
+ *nbytes = -1;
+ res = NULL;
+ break;
+
+ }
+ return res;
+}
+
+
+void mifare_cypher_single_block (desfirekey_t key, uint8_t *data, uint8_t *ivect, MifareCryptoDirection direction, MifareCryptoOperation operation, size_t block_size)
+{
+ uint8_t ovect[MAX_CRYPTO_BLOCK_SIZE];
+
+ if (direction == MCD_SEND) {
+ xor (ivect, data, block_size);
+ } else {
+ memcpy (ovect, data, block_size);
+ }
+
+ uint8_t edata[MAX_CRYPTO_BLOCK_SIZE];
+
+ switch (key->type) {
+ case T_DES:
+ switch (operation) {
+ case MCO_ENCYPHER:
+ //DES_ecb_encrypt ((DES_cblock *) data, (DES_cblock *) edata, &(key->ks1), DES_ENCRYPT);
+ des_enc(edata, data, key->data);
+ break;
+ case MCO_DECYPHER:
+ //DES_ecb_encrypt ((DES_cblock *) data, (DES_cblock *) edata, &(key->ks1), DES_DECRYPT);
+ des_dec(edata, data, key->data);
+ break;
+ }
+ break;
+ case T_3DES:
+ switch (operation) {
+ case MCO_ENCYPHER:
+ // DES_ecb_encrypt ((DES_cblock *) data, (DES_cblock *) edata, &(key->ks1), DES_ENCRYPT);
+ // DES_ecb_encrypt ((DES_cblock *) edata, (DES_cblock *) data, &(key->ks2), DES_DECRYPT);
+ // DES_ecb_encrypt ((DES_cblock *) data, (DES_cblock *) edata, &(key->ks1), DES_ENCRYPT);
+ tdes_enc(edata,data, key->data);
+ break;
+ case MCO_DECYPHER:
+ // DES_ecb_encrypt ((DES_cblock *) data, (DES_cblock *) edata, &(key->ks1), DES_DECRYPT);
+ // DES_ecb_encrypt ((DES_cblock *) edata, (DES_cblock *) data, &(key->ks2), DES_ENCRYPT);
+ // DES_ecb_encrypt ((DES_cblock *) data, (DES_cblock *) edata, &(key->ks1), DES_DECRYPT);
+ tdes_dec(data, edata, key->data);
+ break;
+ }
+ break;
+ case T_3K3DES:
+ switch (operation) {
+ case MCO_ENCYPHER:
+ tdes_enc(edata,data, key->data);
+ // DES_ecb_encrypt ((DES_cblock *) data, (DES_cblock *) edata, &(key->ks1), DES_ENCRYPT);
+ // DES_ecb_encrypt ((DES_cblock *) edata, (DES_cblock *) data, &(key->ks2), DES_DECRYPT);
+ // DES_ecb_encrypt ((DES_cblock *) data, (DES_cblock *) edata, &(key->ks3), DES_ENCRYPT);
+ break;
+ case MCO_DECYPHER:
+ tdes_dec(data, edata, key->data);
+ // DES_ecb_encrypt ((DES_cblock *) data, (DES_cblock *) edata, &(key->ks3), DES_DECRYPT);
+ // DES_ecb_encrypt ((DES_cblock *) edata, (DES_cblock *) data, &(key->ks2), DES_ENCRYPT);
+ // DES_ecb_encrypt ((DES_cblock *) data, (DES_cblock *) edata, &(key->ks1), DES_DECRYPT);
+ break;
+ }
+ break;
+ case T_AES:
+ switch (operation)
+ {
+ case MCO_ENCYPHER:
+ {
+ AesCtx ctx;
+ AesCtxIni(&ctx, ivect, key->data, KEY128,CBC);
+ AesEncrypt(&ctx, data, edata, sizeof(data) );
+ break;
+ }
+ case MCO_DECYPHER:
+ {
+ AesCtx ctx;
+ AesCtxIni(&ctx, ivect, key->data, KEY128,CBC);
+ AesDecrypt(&ctx, edata, data, sizeof(edata));
+ break;
+ }
+ }
+ break;
+ }
+
+ memcpy (data, edata, block_size);
+
+ if (direction == MCD_SEND) {
+ memcpy (ivect, data, block_size);
+ } else {
+ xor (ivect, data, block_size);
+ memcpy (ivect, ovect, block_size);
+ }
+}
+
+/*
+ * This function performs all CBC cyphering / deciphering.
+ *
+ * The tag argument may be NULL, in which case both key and ivect shall be set.
+ * When using the tag session_key and ivect for processing data, these
+ * arguments should be set to NULL.
+ *
+ * Because the tag may contain additional data, one may need to call this
+ * function with tag, key and ivect defined.
+ */
+void mifare_cypher_blocks_chained (desfiretag_t tag, desfirekey_t key, uint8_t *ivect, uint8_t *data, size_t data_size, MifareCryptoDirection direction, MifareCryptoOperation operation) {
+ size_t block_size;
+
+ if (tag) {
+ if (!key)
+ key = DESFIRE (tag)->session_key;
+ if (!ivect)
+ ivect = DESFIRE (tag)->ivect;
+
+ switch (DESFIRE (tag)->authentication_scheme) {
+ case AS_LEGACY:
+ memset (ivect, 0, MAX_CRYPTO_BLOCK_SIZE);
+ break;
+ case AS_NEW:
+ break;
+ }
+ }
+
+ block_size = key_block_size (key);
+
+ size_t offset = 0;
+ while (offset < data_size) {
+ mifare_cypher_single_block (key, data + offset, ivect, direction, operation, block_size);
+ offset += block_size;
+ }
+}
\ No newline at end of file
--- /dev/null
+#ifndef __DESFIRE_CRYPTO_H
+#define __DESFIRE_CRYPTO_H
+
+#include <string.h>
+#include <strings.h>
+#include <stdarg.h>
+#include "printf.h"
+
+#include "iso14443a.h"
+#include "../common/desfire.h"
+#include "des.h"
+//#include "aes.h"
+
+#endif
--- /dev/null
+/*-
+ * Copyright (C) 2010, Romain Tartiere.
+ *
+ * This program is free software: you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as published by the
+ * Free Software Foundation, either version 3 of the License, or (at your
+ * option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>
+ *
+ * $Id$
+ */
+#include <stdlib.h>
+#include "desfire_key.h"
+
+static inline void update_key_schedules (desfirekey_t key);
+
+static inline void update_key_schedules (desfirekey_t key) {
+ // DES_set_key ((DES_cblock *)key->data, &(key->ks1));
+ // DES_set_key ((DES_cblock *)(key->data + 8), &(key->ks2));
+ // if (T_3K3DES == key->type) {
+ // DES_set_key ((DES_cblock *)(key->data + 16), &(key->ks3));
+ // }
+}
+
+void Desfire_des_key_new (const uint8_t value[8], desfirekey_t key) {
+ uint8_t data[8];
+ memcpy (data, value, 8);
+ for (int n=0; n < 8; n++)
+ data[n] &= 0xfe;
+ Desfire_des_key_new_with_version (data, key);
+}
+
+void Desfire_des_key_new_with_version (const uint8_t value[8], desfirekey_t key) {
+ if ( key != NULL) {
+ key->type = T_DES;
+ memcpy (key->data, value, 8);
+ memcpy (key->data+8, value, 8);
+ update_key_schedules (key);
+ }
+}
+
+void Desfire_3des_key_new (const uint8_t value[16], desfirekey_t key) {
+ uint8_t data[16];
+ memcpy (data, value, 16);
+ for (int n=0; n < 8; n++)
+ data[n] &= 0xfe;
+ for (int n=8; n < 16; n++)
+ data[n] |= 0x01;
+ Desfire_3des_key_new_with_version (data, key);
+}
+
+void Desfire_3des_key_new_with_version (const uint8_t value[16], desfirekey_t key) {
+ if ( key != NULL ){
+ key->type = T_3DES;
+ memcpy (key->data, value, 16);
+ update_key_schedules (key);
+ }
+}
+
+void Desfire_3k3des_key_new (const uint8_t value[24], desfirekey_t key) {
+ uint8_t data[24];
+ memcpy (data, value, 24);
+ for (int n=0; n < 8; n++)
+ data[n] &= 0xfe;
+ Desfire_3k3des_key_new_with_version (data, key);
+}
+
+void Desfire_3k3des_key_new_with_version (const uint8_t value[24], desfirekey_t key) {
+ if ( key != NULL){
+ key->type = T_3K3DES;
+ memcpy (key->data, value, 24);
+ update_key_schedules (key);
+ }
+}
+
+ void Desfire_aes_key_new (const uint8_t value[16], desfirekey_t key) {
+ Desfire_aes_key_new_with_version (value, 0, key);
+}
+
+ void Desfire_aes_key_new_with_version (const uint8_t value[16], uint8_t version, desfirekey_t key) {
+
+ if (key != NULL) {
+ memcpy (key->data, value, 16);
+ key->type = T_AES;
+ key->aes_version = version;
+ }
+}
+
+uint8_t Desfire_key_get_version (desfirekey_t key) {
+ uint8_t version = 0;
+
+ for (int n = 0; n < 8; n++) {
+ version |= ((key->data[n] & 1) << (7 - n));
+ }
+ return version;
+}
+
+void Desfire_key_set_version (desfirekey_t key, uint8_t version)
+{
+ for (int n = 0; n < 8; n++) {
+ uint8_t version_bit = ((version & (1 << (7-n))) >> (7-n));
+ key->data[n] &= 0xfe;
+ key->data[n] |= version_bit;
+ if (key->type == T_DES) {
+ key->data[n+8] = key->data[n];
+ } else {
+ // Write ~version to avoid turning a 3DES key into a DES key
+ key->data[n+8] &= 0xfe;
+ key->data[n+8] |= ~version_bit;
+ }
+ }
+}
+
+void Desfire_session_key_new (const uint8_t rnda[], const uint8_t rndb[], desfirekey_t authkey, desfirekey_t key) {
+
+ uint8_t buffer[24];
+
+ switch (authkey->type) {
+ case T_DES:
+ memcpy (buffer, rnda, 4);
+ memcpy (buffer+4, rndb, 4);
+ Desfire_des_key_new_with_version (buffer, key);
+ break;
+ case T_3DES:
+ memcpy (buffer, rnda, 4);
+ memcpy (buffer+4, rndb, 4);
+ memcpy (buffer+8, rnda+4, 4);
+ memcpy (buffer+12, rndb+4, 4);
+ Desfire_3des_key_new_with_version (buffer, key);
+ break;
+ case T_3K3DES:
+ memcpy (buffer, rnda, 4);
+ memcpy (buffer+4, rndb, 4);
+ memcpy (buffer+8, rnda+6, 4);
+ memcpy (buffer+12, rndb+6, 4);
+ memcpy (buffer+16, rnda+12, 4);
+ memcpy (buffer+20, rndb+12, 4);
+ Desfire_3k3des_key_new (buffer, key);
+ break;
+ case T_AES:
+ memcpy (buffer, rnda, 4);
+ memcpy (buffer+4, rndb, 4);
+ memcpy (buffer+8, rnda+12, 4);
+ memcpy (buffer+12, rndb+12, 4);
+ Desfire_aes_key_new (buffer, key);
+ break;
+ }
+}
\ No newline at end of file
--- /dev/null
+#ifndef __DESFIRE_KEY_INCLUDED
+#define __DESFIRE_KEY_INCLUDED
+#include "iso14443a.h"
+// desfire_key.h
+void Desfire_des_key_new (const uint8_t value[8], desfirekey_t key);
+void Desfire_3des_key_new (const uint8_t value[16], desfirekey_t key);
+void Desfire_des_key_new_with_version (const uint8_t value[8], desfirekey_t key);
+void Desfire_3des_key_new_with_version (const uint8_t value[16], desfirekey_t key);
+void Desfire_3k3des_key_new (const uint8_t value[24], desfirekey_t key);
+void Desfire_3k3des_key_new_with_version (const uint8_t value[24], desfirekey_t key);
+void Desfire_aes_key_new (const uint8_t value[16], desfirekey_t key);
+void Desfire_aes_key_new_with_version (const uint8_t value[16], uint8_t version,desfirekey_t key);
+uint8_t Desfire_key_get_version (desfirekey_t key);
+void Desfire_key_set_version (desfirekey_t key, uint8_t version);
+void Desfire_session_key_new (const uint8_t rnda[], const uint8_t rndb[], desfirekey_t authkey, desfirekey_t key);
+
+#endif
\ No newline at end of file
#include "iso14443a.h"
#include "epa.h"
-#include "cmd.h"
+#include "../common/cmd.h"
+
// Protocol and Parameter Selection Request
// use regular (1x) speed in both directions
EPA_Finish();
// send the USB packet
- cmd_send(CMD_ACK,step,func_return,0,0,0);
+ cmd_send(CMD_ACK,step,func_return,0,0,0);
}
//-----------------------------------------------------------------------------
// set up communication
func_return = EPA_Setup();
- if (func_return != 0) {
+ if (func_return != 0) {
EPA_PACE_Collect_Nonce_Abort(1, func_return);
+ Dbprintf("epa: setup fucked up! %d", func_return);
return;
}
int card_access_length = EPA_Read_CardAccess(card_access, 256);
// the response has to be at least this big to hold the OID
if (card_access_length < 18) {
+ Dbprintf("epa: Too small!");
EPA_PACE_Collect_Nonce_Abort(2, card_access_length);
return;
}
+ Dbprintf("epa: foo!");
+
// this will hold the PACE info of the card
pace_version_info_t pace_version_info;
// search for the PACE OID
return;
}
+ Dbprintf("epa: bar!");
+
// initiate the PACE protocol
// use the CAN for the password since that doesn't change
func_return = EPA_PACE_MSE_Set_AT(pace_version_info, 2);
// save received information
// ack->arg[1] = func_return;
// memcpy(ack->d.asBytes, nonce, func_return);
- cmd_send(CMD_ACK,0,func_return,0,nonce,func_return);
+ cmd_send(CMD_ACK,0,func_return,0,nonce,func_return);
}
//-----------------------------------------------------------------------------
// power up the field
iso14443a_setup(FPGA_HF_ISO14443A_READER_MOD);
-
+
// select the card
return_code = iso14443a_select_card(uid, &card_select_info, NULL);
if (return_code != 1) {
// Routines to load the FPGA image, and then to configure the FPGA's major
// mode once it is configured.
//-----------------------------------------------------------------------------
-#include "proxmark3.h"
+
+#include "../include/proxmark3.h"
#include "apps.h"
#include "util.h"
#include "string.h"
// (c) 2012 Roel Verdult
//-----------------------------------------------------------------------------
-#include "proxmark3.h"
+#include "../include/proxmark3.h"
#include "apps.h"
#include "util.h"
-#include "hitag2.h"
+#include "../include/hitag2.h"
#include "string.h"
#include "BigBuf.h"
AT91C_BASE_PMC->PMC_PCER = (1 << AT91C_ID_TC1);
AT91C_BASE_PIOA->PIO_BSR = GPIO_SSC_FRAME;
- // Disable timer during configuration
+ // Disable timer during configuration
AT91C_BASE_TC1->TC_CCR = AT91C_TC_CLKDIS;
// Capture mode, default timer source = MCK/2 (TIMER_CLOCK1), TIOA is external trigger,
//
//-----------------------------------------------------------------------------
-#include "proxmark3.h"
+#include "../include/proxmark3.h"
#include "apps.h"
#include "util.h"
#include "string.h"
// Needed for CRC in emulation mode;
// same construction as in ISO 14443;
// different initial value (CRC_ICLASS)
-#include "iso14443crc.h"
-#include "iso15693tools.h"
+#include "../common/iso14443crc.h"
+#include "../common/iso15693tools.h"
+//#include "iso15693tools.h"
#include "protocols.h"
#include "optimized_cipher.h"
SUB_SECOND_HALF,
SUB_BOTH
} sub;
- uint8_t *output;
+ uint8_t *output;
} Demod;
static RAMFUNC int ManchesterDecoding(int v)
clear_trace();
iso14a_set_trigger(FALSE);
- int lastRxCounter;
+ int lastRxCounter;
uint8_t *upTo;
int smpl;
int maxBehindBy = 0;
if(ManchesterDecoding(smpl & 0x0F)) {
time_stop = (GetCountSspClk()-time_0) << 4;
- rsamples = samples - Demod.samples;
+ rsamples = samples - Demod.samples;
LED_B_ON();
if(tracing) {
uint8_t b = cmd[i];
ToSend[++ToSendMax] = encode4Bits(b & 0xF); //Least significant half
ToSend[++ToSendMax] = encode4Bits((b >>4) & 0xF);//Most significant half
- }
+ }
// Send EOF
ToSend[++ToSendMax] = 0xB8;
//exitLoop = true;
}else
{ //Not fullsim, we don't respond
- // We do not know what to answer, so lets keep quiet
+ // We do not know what to answer, so lets keep quiet
modulated_response = resp_sof; modulated_response_size = 0;
- trace_data = NULL;
- trace_data_size = 0;
+ trace_data = NULL;
+ trace_data_size = 0;
if (simulationMode == MODE_EXIT_AFTER_MAC){
- // dbprintf:ing ...
- Dbprintf("CSN: %02x %02x %02x %02x %02x %02x %02x %02x"
- ,csn[0],csn[1],csn[2],csn[3],csn[4],csn[5],csn[6],csn[7]);
- Dbprintf("RDR: (len=%02d): %02x %02x %02x %02x %02x %02x %02x %02x %02x",len,
- receivedCmd[0], receivedCmd[1], receivedCmd[2],
- receivedCmd[3], receivedCmd[4], receivedCmd[5],
- receivedCmd[6], receivedCmd[7], receivedCmd[8]);
- if (reader_mac_buf != NULL)
- {
- memcpy(reader_mac_buf,receivedCmd+1,8);
- }
- exitLoop = true;
+ // dbprintf:ing ...
+ Dbprintf("CSN: %02x %02x %02x %02x %02x %02x %02x %02x"
+ ,csn[0],csn[1],csn[2],csn[3],csn[4],csn[5],csn[6],csn[7]);
+ Dbprintf("RDR: (len=%02d): %02x %02x %02x %02x %02x %02x %02x %02x %02x",len,
+ receivedCmd[0], receivedCmd[1], receivedCmd[2],
+ receivedCmd[3], receivedCmd[4], receivedCmd[5],
+ receivedCmd[6], receivedCmd[7], receivedCmd[8]);
+ if (reader_mac_buf != NULL)
+ {
+ memcpy(reader_mac_buf,receivedCmd+1,8);
}
+ exitLoop = true;
+ }
}
} else if(receivedCmd[0] == ICLASS_CMD_HALT && len == 1) {
{
if(*wait < 10) *wait = 10;
- for(c = 0; c < *wait;) {
- if(AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_TXRDY)) {
- AT91C_BASE_SSC->SSC_THR = 0x00; // For exact timing!
- c++;
- }
- if(AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_RXRDY)) {
- volatile uint32_t r = AT91C_BASE_SSC->SSC_RHR;
- (void)r;
- }
- WDT_HIT();
- }
+ for(c = 0; c < *wait;) {
+ if(AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_TXRDY)) {
+ AT91C_BASE_SSC->SSC_THR = 0x00; // For exact timing!
+ c++;
+ }
+ if(AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_RXRDY)) {
+ volatile uint32_t r = AT91C_BASE_SSC->SSC_RHR;
+ (void)r;
+ }
+ WDT_HIT();
+ }
}
void ReaderTransmitIClass(uint8_t* frame, int len)
{
- int wait = 0;
- int samples = 0;
+ int wait = 0;
+ int samples = 0;
- // This is tied to other size changes
- CodeIClassCommand(frame,len);
+ // This is tied to other size changes
+ CodeIClassCommand(frame,len);
- // Select the card
- TransmitIClassCommand(ToSend, ToSendMax, &samples, &wait);
- if(trigger)
- LED_A_ON();
+ // Select the card
+ TransmitIClassCommand(ToSend, ToSendMax, &samples, &wait);
+ if(trigger)
+ LED_A_ON();
- // Store reader command in buffer
+ // Store reader command in buffer
if (tracing) {
uint8_t par[MAX_PARITY_SIZE];
GetParity(frame, len, par);
for(;;) {
WDT_HIT();
- if(BUTTON_PRESS()) return FALSE;
+ if(BUTTON_PRESS()) return FALSE;
if(AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_TXRDY)) {
AT91C_BASE_SSC->SSC_THR = 0x00; // To make use of exact timing of next command from reader!!
//Then we can 'ship' back the 8 * 5 bytes of data,
// with 0xFF:s in block 3 and 4.
- LED_B_ON();
- //Send back to client, but don't bother if we already sent this
- if(memcmp(last_csn, card_data, 8) != 0)
+ LED_B_ON();
+ //Send back to client, but don't bother if we already sent this
+ if(memcmp(last_csn, card_data, 8) != 0)
{
if(!get_cc || (get_cc && read_status == 2))
{
- cmd_send(CMD_ACK,read_status,0,0,card_data,datasize);
+ cmd_send(CMD_ACK,read_status,0,0,card_data,datasize);
if(abort_after_read) {
LED_A_OFF();
return;
}
- //Save that we already sent this....
- memcpy(last_csn, card_data, 8);
+ //Save that we already sent this....
+ memcpy(last_csn, card_data, 8);
}
//If 'get_cc' was specified and we didn't get a CC, we'll just keep trying...
}
uint8_t read_status = handshakeIclassTag(card_data);
if(read_status < 2) continue;
- //for now replay captured auth (as cc not updated)
- memcpy(check+5,MAC,4);
+ //for now replay captured auth (as cc not updated)
+ memcpy(check+5,MAC,4);
if(sendCmdGetResponseWithRetries(check, sizeof(check),resp, 4, 5))
{
- Dbprintf("Error: Authentication Fail!");
+ Dbprintf("Error: Authentication Fail!");
continue;
- }
+ }
//first get configuration block (block 1)
crc = block_crc_LUT[1];
- read[1]=1;
- read[2] = crc >> 8;
- read[3] = crc & 0xff;
+ read[1]=1;
+ read[2] = crc >> 8;
+ read[3] = crc & 0xff;
if(sendCmdGetResponseWithRetries(read, sizeof(read),resp, 10, 10))
{
continue;
}
- mem=resp[5];
- memory.k16= (mem & 0x80);
- memory.book= (mem & 0x20);
- memory.k2= (mem & 0x8);
- memory.lockauth= (mem & 0x2);
- memory.keyaccess= (mem & 0x1);
+ mem=resp[5];
+ memory.k16= (mem & 0x80);
+ memory.book= (mem & 0x20);
+ memory.k2= (mem & 0x8);
+ memory.lockauth= (mem & 0x2);
+ memory.keyaccess= (mem & 0x1);
cardsize = memory.k16 ? 255 : 32;
WDT_HIT();
memset(card_data,0x0,USB_CMD_DATA_SIZE);
uint8_t failedRead =0;
uint32_t stored_data_length =0;
- //then loop around remaining blocks
+ //then loop around remaining blocks
for(int block=0; block < cardsize; block++){
read[1]= block;
crc = block_crc_LUT[block];
- read[2] = crc >> 8;
- read[3] = crc & 0xff;
+ read[2] = crc >> 8;
+ read[3] = crc & 0xff;
if(!sendCmdGetResponseWithRetries(read, sizeof(read), resp, 10, 10))
{
- Dbprintf(" %02x: %02x %02x %02x %02x %02x %02x %02x %02x",
+ Dbprintf(" %02x: %02x %02x %02x %02x %02x %02x %02x %02x",
block, resp[0], resp[1], resp[2],
- resp[3], resp[4], resp[5],
- resp[6], resp[7]);
+ resp[3], resp[4], resp[5],
+ resp[6], resp[7]);
//Fill up the buffer
memcpy(card_data+stored_data_length,resp,8);
uint8_t* resp = (((uint8_t *)BigBuf) + 3560);
// Reset trace buffer
- memset(trace, 0x44, RECV_CMD_OFFSET);
+ memset(trace, 0x44, RECV_CMD_OFFSET);
traceLen = 0;
// Setup SSC
// supported.
//-----------------------------------------------------------------------------
-#include "proxmark3.h"
+#include "../include/proxmark3.h"
#include "apps.h"
#include "util.h"
#include "string.h"
-#include "iso14443crc.h"
+#include "../common/iso14443crc.h"
//static void GetSamplesFor14443(int weTx, int n);
}
if(cardSTATE == MFEMUL_NOFIELD) continue;
- //Now, get data
-
res = EmGetCmd(receivedCmd, &len, receivedCmd_par);
if (res == 2) { //Field is off!
cardSTATE = MFEMUL_NOFIELD;
uint32_t nr = bytes_to_num(&receivedCmd[4], 4);
//Collect AR/NR
- if(ar_nr_collected < 2){
+ if(ar_nr_collected < 2 && cardAUTHSC == 2){
if(ar_nr_responses[2] != ar)
{// Avoid duplicates... probably not necessary, ar should vary.
ar_nr_responses[ar_nr_collected*4] = cuid;
ar_nr_responses[ar_nr_collected*4+2] = ar;
ar_nr_responses[ar_nr_collected*4+3] = nr;
ar_nr_collected++;
+ }
+ // Interactive mode flag, means we need to send ACK
+ if(flags & FLAG_INTERACTIVE && ar_nr_collected == 2)
+ {
+ finished = true;
}
}
mf_crypto1_encrypt(pcs, response, 18, response_par);
EmSendCmdPar(response, 18, response_par);
numReads++;
- if(exitAfterNReads > 0 && numReads == exitAfterNReads) {
+ if(exitAfterNReads > 0 && numReads >= exitAfterNReads) {
Dbprintf("%d reads done, exiting", numReads);
finished = true;
}
if(flags & FLAG_INTERACTIVE)// Interactive mode flag, means we need to send ACK
{
//May just aswell send the collected ar_nr in the response aswell
- cmd_send(CMD_ACK,CMD_SIMULATE_MIFARE_CARD,0,0,&ar_nr_responses,ar_nr_collected*4*4);
+ cmd_send(CMD_ACK,CMD_SIMULATE_MIFARE_CARD,1,0,&ar_nr_responses,ar_nr_collected*4*4);
}
- if(flags & FLAG_NR_AR_ATTACK)
+ if(flags & FLAG_NR_AR_ATTACK && MF_DBGLEVEL >= 1 )
{
- if(ar_nr_collected > 1) {
+ if(ar_nr_collected > 1 ) {
Dbprintf("Collected two pairs of AR/NR which can be used to extract keys from reader:");
Dbprintf("../tools/mfkey/mfkey32 %08x %08x %08x %08x %08x %08x",
ar_nr_responses[0], // UID
);
} else {
Dbprintf("Failed to obtain two AR/NR pairs!");
- if(ar_nr_collected >0) {
+ if(ar_nr_collected > 0 ) {
Dbprintf("Only got these: UID=%08x, nonce=%08x, AR1=%08x, NR1=%08x",
ar_nr_responses[0], // UID
ar_nr_responses[1], //NT
#ifndef __ISO14443A_H
#define __ISO14443A_H
-#include "common.h"
+#include "../include/common.h"
+#include "../include/mifare.h"
#include "mifaresniff.h"
typedef struct {
// LEGIC RF simulation code
//-----------------------------------------------------------------------------
-#include "proxmark3.h"
+#include "../include/proxmark3.h"
#include "apps.h"
#include "util.h"
#include "string.h"
#include "legicrf.h"
-#include "legic_prng.h"
-#include "crc.h"
+#include "../include/legic_prng.h"
+#include "../common/crc.h"
static struct legic_frame {
int bits;
sample_config sc = { 0,0,1, divisor_used, 0};
setSamplingConfig(&sc);
- /* Make sure the tag is reset */
- FpgaDownloadAndGo(FPGA_BITSTREAM_LF);
- FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
- SpinDelay(2500);
+ /* Make sure the tag is reset */
+ FpgaDownloadAndGo(FPGA_BITSTREAM_LF);
+ FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
+ SpinDelay(2500);
LFSetupFPGAForADC(sc.divisor, 1);
- // And a little more time for the tag to fully power up
- SpinDelay(2000);
+ // And a little more time for the tag to fully power up
+ SpinDelay(2000);
// now modulate the reader field
while(*command != '\0' && *command != ' ') {
DoAcquisition_config(false);
}
-
-
/* blank r/w tag data stream
...0000000000000000 01111111
1010101010101010101010101010101010101010101010101010101010101010
DbpString("Now use tiread to check");
}
-void SimulateTagLowFrequency(int period, int gap, int ledcontrol)
+void SimulateTagLowFrequency(uint16_t period, uint32_t gap, uint8_t ledcontrol)
{
int i;
uint8_t *tab = BigBuf_get_addr();
if (ledcontrol) LED_A_ON();
DoAcquisition_default(-1,true);
- // FSK demodulator
+ // FSK demodulator
size = sizeOfBigBuff; //variable size will change after demod so re initialize it before use
idx = HIDdemodFSK(dest, &size, &hi2, &hi, &lo);
if (ledcontrol) LED_A_ON();
DoAcquisition_default(-1,true);
- size = BigBuf_max_traceLen();
+ size = BigBuf_max_traceLen();
//Dbprintf("DEBUG: Buffer got");
//askdemod and manchester decode
errCnt = askmandemod(dest, &size, &clk, &invert, maxErr);
WDT_HIT();
if (ledcontrol) LED_A_ON();
DoAcquisition_default(-1,true);
- //fskdemod and get start index
+ //fskdemod and get start index
WDT_HIT();
idx = IOdemodFSK(dest, BigBuf_max_traceLen());
if (idx>0){
* To compensate antenna falling times shorten the write times
* and enlarge the gap ones.
*/
-#define START_GAP 250
-#define WRITE_GAP 160
-#define WRITE_0 144 // 192
-#define WRITE_1 400 // 432 for T55x7; 448 for E5550
+#define START_GAP 30*8 // 10 - 50fc 250
+#define WRITE_GAP 20*8 // 8 - 30fc
+#define WRITE_0 24*8 // 16 - 31fc 24fc 192
+#define WRITE_1 54*8 // 48 - 63fc 54fc 432 for T55x7; 448 for E5550
+
+// VALUES TAKEN FROM EM4x function: SendForward
+// START_GAP = 440; (55*8) cycles at 125Khz (8us = 1cycle)
+// WRITE_GAP = 128; (16*8)
+// WRITE_1 = 256 32*8; (32*8)
+
+// These timings work for 4469/4269/4305 (with the 55*8 above)
+// WRITE_0 = 23*8 , 9*8 SpinDelayUs(23*8);
+
+#define T55xx_SAMPLES_SIZE 12000 // 32 x 32 x 10 (32 bit times numofblock (7), times clock skip..)
// Write one bit to card
void T55xxWriteBit(int bit)
FpgaDownloadAndGo(FPGA_BITSTREAM_LF);
FpgaSendCommand(FPGA_CMD_SET_DIVISOR, 95); //125Khz
FpgaWriteConfWord(FPGA_MAJOR_MODE_LF_ADC | FPGA_LF_ADC_READER_FIELD);
- if (bit == 0)
+ if (!bit)
SpinDelayUs(WRITE_0);
else
SpinDelayUs(WRITE_1);
// Write one card block in page 0, no lock
void T55xxWriteBlock(uint32_t Data, uint32_t Block, uint32_t Pwd, uint8_t PwdMode)
{
- //unsigned int i; //enio adjustment 12/10/14
- uint32_t i;
-
- FpgaDownloadAndGo(FPGA_BITSTREAM_LF);
- FpgaSendCommand(FPGA_CMD_SET_DIVISOR, 95); //125Khz
- FpgaWriteConfWord(FPGA_MAJOR_MODE_LF_ADC | FPGA_LF_ADC_READER_FIELD);
+ uint32_t i = 0;
- // Give it a bit of time for the resonant antenna to settle.
- // And for the tag to fully power up
- SpinDelay(150);
+ // Set up FPGA, 125kHz
+ // Wait for config.. (192+8190xPOW)x8 == 67ms
+ LFSetupFPGAForADC(0, true);
// Now start writting
FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
// Read one card block in page 0
void T55xxReadBlock(uint32_t Block, uint32_t Pwd, uint8_t PwdMode)
{
+ uint32_t i = 0;
uint8_t *dest = BigBuf_get_addr();
- //int m=0, i=0; //enio adjustment 12/10/14
- uint32_t m=0, i=0;
- FpgaDownloadAndGo(FPGA_BITSTREAM_LF);
- m = BigBuf_max_traceLen();
- // Clear destination buffer before sending the command
- memset(dest, 128, m);
- // Connect the A/D to the peak-detected low-frequency path.
- SetAdcMuxFor(GPIO_MUXSEL_LOPKD);
- // Now set up the SSC to get the ADC samples that are now streaming at us.
- FpgaSetupSsc();
-
- LED_D_ON();
- FpgaSendCommand(FPGA_CMD_SET_DIVISOR, 95); //125Khz
- FpgaWriteConfWord(FPGA_MAJOR_MODE_LF_ADC | FPGA_LF_ADC_READER_FIELD);
-
- // Give it a bit of time for the resonant antenna to settle.
- // And for the tag to fully power up
- SpinDelay(150);
-
- // Now start writting
+ uint16_t bufferlength = BigBuf_max_traceLen();
+ if ( bufferlength > T55xx_SAMPLES_SIZE )
+ bufferlength = T55xx_SAMPLES_SIZE;
+
+ memset(dest, 0x80, bufferlength);
+
+ // Set up FPGA, 125kHz
+ // Wait for config.. (192+8190xPOW)x8 == 67ms
+ LFSetupFPGAForADC(0, true);
FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
SpinDelayUs(START_GAP);
T55xxWriteBit(Block & i);
// Turn field on to read the response
- FpgaSendCommand(FPGA_CMD_SET_DIVISOR, 95); //125Khz
- FpgaWriteConfWord(FPGA_MAJOR_MODE_LF_ADC | FPGA_LF_ADC_READER_FIELD);
+ TurnReadLFOn();
// Now do the acquisition
i = 0;
for(;;) {
if (AT91C_BASE_SSC->SSC_SR & AT91C_SSC_TXRDY) {
AT91C_BASE_SSC->SSC_THR = 0x43;
+ LED_D_ON();
}
if (AT91C_BASE_SSC->SSC_SR & AT91C_SSC_RXRDY) {
dest[i] = (uint8_t)AT91C_BASE_SSC->SSC_RHR;
- // we don't care about actual value, only if it's more or less than a
- // threshold essentially we capture zero crossings for later analysis
- // if(dest[i] < 127) dest[i] = 0; else dest[i] = 1;
- i++;
- if (i >= m) break;
+ ++i;
+ LED_D_OFF();
+ if (i >= bufferlength) break;
}
}
+ cmd_send(CMD_ACK,0,0,0,0,0);
FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); // field off
LED_D_OFF();
- DbpString("DONE!");
}
// Read card traceability data (page 1)
void T55xxReadTrace(void){
- uint8_t *dest = BigBuf_get_addr();
- int m=0, i=0;
-
- FpgaDownloadAndGo(FPGA_BITSTREAM_LF);
- m = BigBuf_max_traceLen();
- // Clear destination buffer before sending the command
- memset(dest, 128, m);
- // Connect the A/D to the peak-detected low-frequency path.
- SetAdcMuxFor(GPIO_MUXSEL_LOPKD);
- // Now set up the SSC to get the ADC samples that are now streaming at us.
- FpgaSetupSsc();
-
- LED_D_ON();
- FpgaSendCommand(FPGA_CMD_SET_DIVISOR, 95); //125Khz
- FpgaWriteConfWord(FPGA_MAJOR_MODE_LF_ADC | FPGA_LF_ADC_READER_FIELD);
- // Give it a bit of time for the resonant antenna to settle.
- // And for the tag to fully power up
- SpinDelay(150);
+ uint32_t i = 0;
+ uint8_t *dest = BigBuf_get_addr();
+ uint16_t bufferlength = BigBuf_max_traceLen();
+ if ( bufferlength > T55xx_SAMPLES_SIZE )
+ bufferlength = T55xx_SAMPLES_SIZE;
- // Now start writting
+ memset(dest, 0x80, bufferlength);
+
+ LFSetupFPGAForADC(0, true);
FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
SpinDelayUs(START_GAP);
T55xxWriteBit(1); //Page 1
// Turn field on to read the response
- FpgaSendCommand(FPGA_CMD_SET_DIVISOR, 95); //125Khz
- FpgaWriteConfWord(FPGA_MAJOR_MODE_LF_ADC | FPGA_LF_ADC_READER_FIELD);
+ TurnReadLFOn();
// Now do the acquisition
- i = 0;
for(;;) {
if (AT91C_BASE_SSC->SSC_SR & AT91C_SSC_TXRDY) {
AT91C_BASE_SSC->SSC_THR = 0x43;
+ LED_D_ON();
}
if (AT91C_BASE_SSC->SSC_SR & AT91C_SSC_RXRDY) {
dest[i] = (uint8_t)AT91C_BASE_SSC->SSC_RHR;
- i++;
- if (i >= m) break;
- }
- }
-
+ ++i;
+ LED_D_OFF();
+
+ if (i >= bufferlength) break;
+ }
+ }
+
+ cmd_send(CMD_ACK,0,0,0,0,0);
FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); // field off
LED_D_OFF();
- DbpString("DONE!");
+}
+
+void TurnReadLFOn(){
+ //FpgaSendCommand(FPGA_CMD_SET_DIVISOR, 95); //125Khz
+ FpgaWriteConfWord(FPGA_MAJOR_MODE_LF_ADC | FPGA_LF_ADC_READER_FIELD);
+ // Give it a bit of time for the resonant antenna to settle.
+ //SpinDelay(30);
+ SpinDelayUs(9*150);
}
/*-------------- Cloning routines -----------*/
#define max(x,y) ( x<y ? y:x)
int DemodPCF7931(uint8_t **outBlocks) {
- uint8_t BitStream[256];
- uint8_t Blocks[8][16];
- uint8_t *GraphBuffer = BigBuf_get_addr();
+
+ uint8_t BitStream[256] = {0x00};
+ uint8_t Blocks[8][16];
+ uint8_t *dest = BigBuf_get_addr();
int GraphTraceLen = BigBuf_max_traceLen();
int i, j, lastval, bitidx, half_switch;
int clock = 64;
uint8_t dir;
LFSetupFPGAForADC(95, true);
- DoAcquisition_default(0, 0);
-
+ DoAcquisition_default(0, true);
lmin = 64;
lmax = 192;
i = 2;
/* Find first local max/min */
- if(GraphBuffer[1] > GraphBuffer[0]) {
+ if(dest[1] > dest[0]) {
while(i < GraphTraceLen) {
- if( !(GraphBuffer[i] > GraphBuffer[i-1]) && GraphBuffer[i] > lmax)
+ if( !(dest[i] > dest[i-1]) && dest[i] > lmax)
break;
i++;
}
}
else {
while(i < GraphTraceLen) {
- if( !(GraphBuffer[i] < GraphBuffer[i-1]) && GraphBuffer[i] < lmin)
+ if( !(dest[i] < dest[i-1]) && dest[i] < lmin)
break;
i++;
}
for (bitidx = 0; i < GraphTraceLen; i++)
{
- if ( (GraphBuffer[i-1] > GraphBuffer[i] && dir == 1 && GraphBuffer[i] > lmax) || (GraphBuffer[i-1] < GraphBuffer[i] && dir == 0 && GraphBuffer[i] < lmin))
+ if ( (dest[i-1] > dest[i] && dir == 1 && dest[i] > lmax) || (dest[i-1] < dest[i] && dir == 0 && dest[i] < lmin))
{
lc = i - lastval;
lastval = i;
}
if(i < GraphTraceLen)
{
- if (GraphBuffer[i-1] > GraphBuffer[i]) dir=0;
+ if (dest[i-1] > dest[i]) dir=0;
else dir = 1;
}
}
void EM4xReadWord(uint8_t Address, uint32_t Pwd, uint8_t PwdMode) {
+ uint8_t *dest = BigBuf_get_addr();
+ uint16_t bufferlength = BigBuf_max_traceLen();
+ uint32_t i = 0;
+
+ // Clear destination buffer before sending the command 0x80 = average.
+ memset(dest, 0x80, bufferlength);
+
uint8_t fwd_bit_count;
- uint8_t *dest = BigBuf_get_addr();
- int m=0, i=0;
//If password mode do login
if (PwdMode == 1) EM4xLogin(Pwd);
fwd_bit_count = Prepare_Cmd( FWD_CMD_READ );
fwd_bit_count += Prepare_Addr( Address );
- m = BigBuf_max_traceLen();
- // Clear destination buffer before sending the command
- memset(dest, 128, m);
// Connect the A/D to the peak-detected low-frequency path.
SetAdcMuxFor(GPIO_MUXSEL_LOPKD);
// Now set up the SSC to get the ADC samples that are now streaming at us.
}
if (AT91C_BASE_SSC->SSC_SR & AT91C_SSC_RXRDY) {
dest[i] = (uint8_t)AT91C_BASE_SSC->SSC_RHR;
- i++;
- if (i >= m) break;
- }
- }
+ ++i;
+ if (i >= bufferlength) break;
+ }
+ }
+
+ cmd_send(CMD_ACK,0,0,0,0,0);
FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); // field off
LED_D_OFF();
}
if (workFlags & 0x01) {\r
if(!iso14443a_select_card(uid, NULL, &cuid)) {\r
if (MF_DBGLEVEL >= 1) Dbprintf("Can't select card");\r
- break;\r
+ //break;\r
};\r
\r
if(mifare_classic_halt(NULL, cuid)) {\r
if (MF_DBGLEVEL >= 1) Dbprintf("Halt error");\r
- break;\r
+ //break;\r
};\r
};\r
\r
#ifndef __MIFARECMD_H\r
#define __MIFARECMD_H\r
\r
-#include "proxmark3.h"\r
+#include "../include/proxmark3.h"\r
#include "apps.h"\r
#include "util.h"\r
#include "string.h"\r
\r
-#include "iso14443crc.h"\r
+#include "../common/iso14443crc.h"\r
#include "iso14443a.h"\r
#include "crapto1.h"\r
#include "mifareutil.h"\r
-#include "common.h"\r
-\r
+#include "../include/common.h"\r
\r
#endif
\ No newline at end of file
--- /dev/null
+#include "mifaredesfire.h"
+#include "des.h"
+
+#define MAX_APPLICATION_COUNT 28
+#define MAX_FILE_COUNT 16
+#define MAX_DESFIRE_FRAME_SIZE 60
+#define NOT_YET_AUTHENTICATED 255
+#define FRAME_PAYLOAD_SIZE (MAX_DESFIRE_FRAME_SIZE - 5)
+#define RECEIVE_SIZE 64
+
+// the block number for the ISO14443-4 PCB
+uint8_t pcb_blocknum = 0;
+// Deselect card by sending a s-block. the crc is precalced for speed
+static uint8_t deselect_cmd[] = {0xc2,0xe0,0xb4};
+
+//static uint8_t __msg[MAX_FRAME_SIZE] = { 0x0A, 0x00, 0x00, /* ..., */ 0x00 };
+/* PCB CID CMD PAYLOAD */
+//static uint8_t __res[MAX_FRAME_SIZE];
+
+bool InitDesfireCard(){
+
+ byte_t cardbuf[USB_CMD_DATA_SIZE] = {0x00};
+
+ iso14a_card_select_t *card = (iso14a_card_select_t*)cardbuf;
+
+ iso14a_set_tracing(TRUE);
+ iso14443a_setup(FPGA_HF_ISO14443A_READER_LISTEN);
+
+ int len = iso14443a_select_card(NULL,card,NULL);
+
+ if (!len) {
+ if (MF_DBGLEVEL >= MF_DBG_ERROR)
+ Dbprintf("Can't select card");
+ OnError(1);
+ return false;
+ }
+ return true;
+}
+
+// ARG0 flag enums
+enum {
+ NONE = 0x00,
+ INIT = 0x01,
+ DISCONNECT = 0x02,
+ CLEARTRACE = 0x04,
+ BAR = 0x08,
+} CmdOptions ;
+
+void MifareSendCommand(uint8_t arg0, uint8_t arg1, uint8_t *datain){
+
+ /* ARG0 contains flags.
+ 0x01 = init card.
+ 0x02 = Disconnect
+ 0x03
+ */
+ uint8_t flags = arg0;
+ size_t datalen = arg1;
+ uint8_t resp[RECEIVE_SIZE];
+ memset(resp,0,sizeof(resp));
+
+ if (MF_DBGLEVEL >= 4) {
+ Dbprintf(" flags : %02X", flags);
+ Dbprintf(" len : %02X", datalen);
+ print_result(" RX : ", datain, datalen);
+ }
+
+ if ( flags & CLEARTRACE ){
+ iso14a_clear_trace();
+ }
+
+ if ( flags & INIT ){
+ if ( !InitDesfireCard() )
+ return;
+ }
+
+ int len = DesfireAPDU(datain, datalen, resp);
+ if (MF_DBGLEVEL >= 4) {
+ print_result("ERR <--: ", resp, len);
+ }
+
+ if ( !len ) {
+ OnError(2);
+ return;
+ }
+
+ // reset the pcb_blocknum,
+ pcb_blocknum = 0;
+
+ if ( flags & DISCONNECT ){
+ OnSuccess();
+ }
+
+ cmd_send(CMD_ACK,1,len,0,resp,len);
+}
+
+void MifareDesfireGetInformation(){
+
+ int len = 0;
+ uint8_t resp[USB_CMD_DATA_SIZE] = {0x00};
+ uint8_t dataout[USB_CMD_DATA_SIZE] = {0x00};
+ byte_t cardbuf[USB_CMD_DATA_SIZE] = {0x00};
+
+ /*
+ 1 = PCB 1
+ 2 = cid 2
+ 3 = desfire command 3
+ 4-5 = crc 4 key
+ 5-6 crc
+ PCB == 0x0A because sending CID byte.
+ CID == 0x00 first card?
+ */
+ iso14a_clear_trace();
+ iso14a_set_tracing(TRUE);
+ iso14443a_setup(FPGA_HF_ISO14443A_READER_LISTEN);
+
+ // card select - information
+ iso14a_card_select_t *card = (iso14a_card_select_t*)cardbuf;
+ byte_t isOK = iso14443a_select_card(NULL, card, NULL);
+ if ( isOK == 0) {
+ if (MF_DBGLEVEL >= MF_DBG_ERROR) {
+ Dbprintf("Can't select card");
+ }
+ OnError(1);
+ return;
+ }
+
+ memcpy(dataout,card->uid,7);
+
+ LED_A_ON();
+ LED_B_OFF();
+ LED_C_OFF();
+
+ uint8_t cmd[] = {GET_VERSION};
+ size_t cmd_len = sizeof(cmd);
+
+ len = DesfireAPDU(cmd, cmd_len, resp);
+ if ( !len ) {
+ print_result("ERROR <--: ", resp, len);
+ OnError(2);
+ return;
+ }
+
+ LED_A_OFF();
+ LED_B_ON();
+ memcpy(dataout+7,resp+3,7);
+
+ // ADDITION_FRAME 1
+ cmd[0] = ADDITIONAL_FRAME;
+ len = DesfireAPDU(cmd, cmd_len, resp);
+ if ( !len ) {
+ print_result("ERROR <--: ", resp, len);
+ OnError(2);
+ return;
+ }
+
+ LED_B_OFF();
+ LED_C_ON();
+ memcpy(dataout+7+7,resp+3,7);
+
+ // ADDITION_FRAME 2
+ len = DesfireAPDU(cmd, cmd_len, resp);
+ if ( !len ) {
+ print_result("ERROR <--: ", resp, len);
+ OnError(2);
+ return;
+ }
+
+ memcpy(dataout+7+7+7,resp+3,14);
+
+ cmd_send(CMD_ACK,1,0,0,dataout,sizeof(dataout));
+
+ // reset the pcb_blocknum,
+ pcb_blocknum = 0;
+ OnSuccess();
+}
+
+void MifareDES_Auth1(uint8_t mode, uint8_t algo, uint8_t keyno, uint8_t *datain){
+
+ int len = 0;
+ //uint8_t PICC_MASTER_KEY8[8] = { 0x40,0x41,0x42,0x43,0x44,0x45,0x46,0x47};
+ uint8_t PICC_MASTER_KEY16[16] = { 0x40,0x41,0x42,0x43,0x44,0x45,0x46,0x47,0x48,0x49,0x4a,0x4b,0x4c,0x4d,0x4e,0x4f };
+ uint8_t null_key_data8[8] = {0x00};
+ //uint8_t null_key_data16[16] = {0x00};
+ //uint8_t new_key_data8[8] = { 0x00,0x11,0x22,0x33,0x44,0x55,0x66,0x77};
+ //uint8_t new_key_data16[16] = { 0x00,0x11,0x22,0x33,0x44,0x55,0x66,0x77,0x88,0x99,0xAA,0xBB,0xCC,0xDD,0xEE,0xFF};
+
+ uint8_t resp[256] = {0x00};
+ uint8_t IV[16] = {0x00};
+
+ size_t datalen = datain[0];
+
+ uint8_t cmd[40] = {0x00};
+ uint8_t encRndB[16] = {0x00};
+ uint8_t decRndB[16] = {0x00};
+ uint8_t nonce[16] = {0x00};
+ uint8_t both[32] = {0x00};
+ uint8_t encBoth[32] = {0x00};
+
+ InitDesfireCard();
+
+ // 3 olika sätt att authenticera. AUTH (CRC16) , AUTH_ISO (CRC32) , AUTH_AES (CRC32)
+ // 4 olika crypto algo DES, 3DES, 3K3DES, AES
+ // 3 olika kommunikations sätt, PLAIN,MAC,CRYPTO
+
+ // des, nyckel 0,
+ switch (mode){
+ case 1:{
+ if (algo == 1) {
+
+ uint8_t keybytes[8] = {0x00};
+ uint8_t RndA[8] = {0x00};
+ uint8_t RndB[8] = {0x00};
+
+ if (datain[1] == 0xff){
+ memcpy(keybytes,null_key_data8,8);
+ } else{
+ memcpy(keybytes, datain+1, datalen);
+ }
+
+ struct desfire_key defaultkey = {0};
+ desfirekey_t key = &defaultkey;
+ Desfire_des_key_new(keybytes, key);
+
+ cmd[0] = AUTHENTICATE;
+ cmd[1] = keyno; //keynumber
+ len = DesfireAPDU(cmd, 2, resp);
+ if ( !len ) {
+ if (MF_DBGLEVEL >= MF_DBG_ERROR) {
+ DbpString("Authentication failed. Card timeout.");
+ }
+ OnError(3);
+ return;
+ }
+
+ if ( resp[2] == 0xaf ){
+ } else {
+ DbpString("Authetication failed. Invalid key number.");
+ OnError(3);
+ return;
+ }
+
+ memcpy( encRndB, resp+3, 8);
+
+ des_dec(&decRndB, &encRndB, key->data);
+ memcpy(RndB, decRndB, 8);
+ rol(decRndB,8);
+
+ // This should be random
+ uint8_t decRndA[8] = {0x00};
+ memcpy(RndA, decRndA, 8);
+ uint8_t encRndA[8] = {0x00};
+
+ des_dec(&encRndA, &decRndA, key->data);
+
+ memcpy(both, encRndA, 8);
+
+ for (int x = 0; x < 8; x++) {
+ decRndB[x] = decRndB[x] ^ encRndA[x];
+ }
+
+ des_dec(&encRndB, &decRndB, key->data);
+
+ memcpy(both + 8, encRndB, 8);
+
+ cmd[0] = ADDITIONAL_FRAME;
+ memcpy(cmd+1, both, 16 );
+
+ len = DesfireAPDU(cmd, 17, resp);
+ if ( !len ) {
+ if (MF_DBGLEVEL >= MF_DBG_ERROR) {
+ DbpString("Authentication failed. Card timeout.");
+ }
+ OnError(3);
+ return;
+ }
+
+ if ( resp[2] == 0x00 ){
+
+ struct desfire_key sessionKey = {0};
+ desfirekey_t skey = &sessionKey;
+ Desfire_session_key_new( RndA, RndB , key, skey );
+ //print_result("SESSION : ", skey->data, 8);
+
+ memcpy(encRndA, resp+3, 8);
+ des_dec(&encRndA, &encRndA, key->data);
+ rol(decRndA,8);
+ for (int x = 0; x < 8; x++) {
+ if (decRndA[x] != encRndA[x]) {
+ DbpString("Authetication failed. Cannot varify PICC.");
+ OnError(4);
+ return;
+ }
+ }
+
+ //Change the selected key to a new value.
+ /*
+
+ cmd[0] = CHANGE_KEY;
+ cmd[1] = keyno;
+
+ uint8_t newKey[16] = {0x00,0x11,0x22,0x33,0x44,0x55,0x66,0x77,0x00,0x11,0x22,0x33,0x44,0x55,0x66,0x77};
+
+ uint8_t first, second;
+ uint8_t buff1[8] = {0x00};
+ uint8_t buff2[8] = {0x00};
+ uint8_t buff3[8] = {0x00};
+
+ memcpy(buff1,newKey, 8);
+ memcpy(buff2,newKey + 8, 8);
+
+ ComputeCrc14443(CRC_14443_A, newKey, 16, &first, &second);
+ memcpy(buff3, &first, 1);
+ memcpy(buff3 + 1, &second, 1);
+
+ des_dec(&buff1, &buff1, skey->data);
+ memcpy(cmd+2,buff1,8);
+
+ for (int x = 0; x < 8; x++) {
+ buff2[x] = buff2[x] ^ buff1[x];
+ }
+ des_dec(&buff2, &buff2, skey->data);
+ memcpy(cmd+10,buff2,8);
+
+ for (int x = 0; x < 8; x++) {
+ buff3[x] = buff3[x] ^ buff2[x];
+ }
+ des_dec(&buff3, &buff3, skey->data);
+ memcpy(cmd+18,buff3,8);
+
+ // The command always times out on the first attempt, this will retry until a response
+ // is recieved.
+ len = 0;
+ while(!len) {
+ len = DesfireAPDU(cmd,26,resp);
+ }
+ */
+
+ OnSuccess();
+ cmd_send(CMD_ACK,1,0,0,skey->data,8);
+
+ } else {
+ DbpString("Authetication failed.");
+ OnError(6);
+ return;
+ }
+
+ }
+ }
+ break;
+ case 2:
+ //SendDesfireCommand(AUTHENTICATE_ISO, &keyno, resp);
+ break;
+ case 3:{
+
+ //defaultkey
+ uint8_t keybytes[16] = {0x00};
+ if (datain[1] == 0xff){
+ memcpy(keybytes,PICC_MASTER_KEY16,16);
+ } else{
+ memcpy(keybytes, datain+1, datalen);
+ }
+
+ struct desfire_key defaultkey = {0x00};
+ desfirekey_t key = &defaultkey;
+ Desfire_aes_key_new( keybytes, key);
+
+ AesCtx ctx;
+ if ( AesCtxIni(&ctx, IV, key->data, KEY128, CBC) < 0 ){
+ if( MF_DBGLEVEL >= 4) {
+ Dbprintf("AES context failed to init");
+ }
+ OnError(7);
+ return;
+ }
+
+ cmd[0] = AUTHENTICATE_AES;
+ cmd[1] = 0x00; //keynumber
+ len = DesfireAPDU(cmd, 2, resp);
+ if ( !len ) {
+ if (MF_DBGLEVEL >= MF_DBG_ERROR) {
+ DbpString("Authentication failed. Card timeout.");
+ }
+ OnError(3);
+ return;
+ }
+
+ memcpy( encRndB, resp+3, 16);
+
+ // dekryptera tagnonce.
+ AesDecrypt(&ctx, encRndB, decRndB, 16);
+ rol(decRndB,16);
+ memcpy(both, nonce,16);
+ memcpy(both+16, decRndB ,16 );
+ AesEncrypt(&ctx, both, encBoth, 32 );
+
+ cmd[0] = ADDITIONAL_FRAME;
+ memcpy(cmd+1, encBoth, 32 );
+
+ len = DesfireAPDU(cmd, 33, resp); // 1 + 32 == 33
+ if ( !len ) {
+ if (MF_DBGLEVEL >= MF_DBG_ERROR) {
+ DbpString("Authentication failed. Card timeout.");
+ }
+ OnError(3);
+ return;
+ }
+
+ if ( resp[2] == 0x00 ){
+ // Create AES Session key
+ struct desfire_key sessionKey = {0};
+ desfirekey_t skey = &sessionKey;
+ Desfire_session_key_new( nonce, decRndB , key, skey );
+ print_result("SESSION : ", skey->data, 16);
+ } else {
+ DbpString("Authetication failed.");
+ OnError(7);
+ return;
+ }
+ break;
+ }
+ }
+
+ OnSuccess();
+ cmd_send(CMD_ACK,1,len,0,resp,len);
+}
+
+// 3 olika ISO sätt att skicka data till DESFIRE (direkt, inkapslat, inkapslat ISO)
+// cmd = cmd bytes to send
+// cmd_len = length of cmd
+// dataout = pointer to response data array
+int DesfireAPDU(uint8_t *cmd, size_t cmd_len, uint8_t *dataout){
+
+ size_t len = 0;
+ size_t wrappedLen = 0;
+ uint8_t wCmd[USB_CMD_DATA_SIZE] = {0};
+
+ uint8_t *resp = ((uint8_t *)BigBuf) + RECV_RESP_OFFSET;
+ uint8_t *resp_par = ((uint8_t *)BigBuf) + RECV_RESP_PAR_OFFSET;
+
+ wrappedLen = CreateAPDU( cmd, cmd_len, wCmd);
+
+ if (MF_DBGLEVEL >= 4) {
+ print_result("WCMD <--: ", wCmd, wrappedLen);
+ }
+ ReaderTransmit( wCmd, wrappedLen, NULL);
+
+ len = ReaderReceive(resp, resp_par);
+
+ if( len == 0x00 ){
+ if (MF_DBGLEVEL >= 4) {
+ Dbprintf("fukked");
+ }
+ return FALSE; //DATA LINK ERROR
+ }
+ // if we received an I- or R(ACK)-Block with a block number equal to the
+ // current block number, toggle the current block number
+ else if (len >= 4 // PCB+CID+CRC = 4 bytes
+ && ((resp[0] & 0xC0) == 0 // I-Block
+ || (resp[0] & 0xD0) == 0x80) // R-Block with ACK bit set to 0
+ && (resp[0] & 0x01) == pcb_blocknum) // equal block numbers
+ {
+ pcb_blocknum ^= 1; //toggle next block
+ }
+
+ memcpy(dataout, resp, len);
+ return len;
+}
+
+// CreateAPDU
+size_t CreateAPDU( uint8_t *datain, size_t len, uint8_t *dataout){
+
+ size_t cmdlen = MIN(len+4, USB_CMD_DATA_SIZE-1);
+
+ uint8_t cmd[cmdlen];
+ memset(cmd, 0, cmdlen);
+
+ cmd[0] = 0x0A; // 0x0A = skicka cid, 0x02 = ingen cid. Särskilda bitar //
+ cmd[0] |= pcb_blocknum; // OR the block number into the PCB
+ cmd[1] = 0x00; // CID: 0x00 //TODO: allow multiple selected cards
+
+ memcpy(cmd+2, datain, len);
+ AppendCrc14443a(cmd, len+2);
+
+ memcpy(dataout, cmd, cmdlen);
+
+ return cmdlen;
+}
+
+ // crc_update(&desfire_crc32, 0, 1); /* CMD_WRITE */
+ // crc_update(&desfire_crc32, addr, addr_sz);
+ // crc_update(&desfire_crc32, byte, 8);
+ // uint32_t crc = crc_finish(&desfire_crc32);
+
+void OnSuccess(){
+ pcb_blocknum = 0;
+ ReaderTransmit(deselect_cmd, 3 , NULL);
+ FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
+ LEDsoff();
+}
+
+void OnError(uint8_t reason){
+ pcb_blocknum = 0;
+ ReaderTransmit(deselect_cmd, 3 , NULL);
+ FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
+ cmd_send(CMD_ACK,0,reason,0,0,0);
+ LEDsoff();
+}
--- /dev/null
+#ifndef __MIFAREDESFIRE_H
+#define __MIFAREDESFIRE_H
+
+#include "../include/proxmark3.h"
+#include "apps.h"
+#include "util.h"
+#include "string.h"
+
+#include "../common/iso14443crc.h"
+#include "iso14443a.h"
+#include "desfire_key.h"
+#include "mifareutil.h"
+#include "../include/common.h"
+
+#endif
#ifndef __MIFARESNIFF_H\r
#define __MIFARESNIFF_H\r
\r
-#include "proxmark3.h"\r
+#include "../include/proxmark3.h"\r
#include "apps.h"\r
#include "util.h"\r
#include "string.h"\r
\r
-#include "iso14443crc.h"\r
+#include "../common/iso14443crc.h"\r
#include "iso14443a.h"\r
#include "crapto1.h"\r
#include "mifareutil.h"\r
-#include "common.h"\r
+#include "../include/common.h"\r
\r
#define SNF_INIT 0\r
#define SNF_NO_FIELD 1\r
// send commands\r
int mifare_sendcmd_short(struct Crypto1State *pcs, uint8_t crypted, uint8_t cmd, uint8_t data, uint8_t* answer, uint8_t *answer_parity, uint32_t *timing)\r
{\r
- return mifare_sendcmd_shortex(pcs, crypted, cmd, data, answer, answer_parity, timing);
-}
-
-int mifare_sendcmd_short_special(struct Crypto1State *pcs, uint8_t crypted, uint8_t cmd, uint8_t* data, uint8_t* answer, uint8_t *answer_parity, uint32_t *timing)
-{
- uint8_t dcmd[8];
- dcmd[0] = cmd;
- dcmd[1] = data[0];
- dcmd[2] = data[1];
- dcmd[3] = data[2];
- dcmd[4] = data[3];
- dcmd[5] = data[4];
- AppendCrc14443a(dcmd, 6);
- ReaderTransmit(dcmd, sizeof(dcmd), NULL);
- int len = ReaderReceive(answer, answer_parity);
- if(!len) {
- if (MF_DBGLEVEL >= 1) Dbprintf("Authentication failed. Card timeout.");
- return 2;
+ return mifare_sendcmd_shortex(pcs, crypted, cmd, data, answer, answer_parity, timing);\r
+}\r
+\r
+int mifare_sendcmd_short_special(struct Crypto1State *pcs, uint8_t crypted, uint8_t cmd, uint8_t* data, uint8_t* answer, uint8_t *answer_parity, uint32_t *timing)\r
+{\r
+ uint8_t dcmd[8];\r
+ dcmd[0] = cmd;\r
+ dcmd[1] = data[0];\r
+ dcmd[2] = data[1];\r
+ dcmd[3] = data[2];\r
+ dcmd[4] = data[3];\r
+ dcmd[5] = data[4];\r
+ AppendCrc14443a(dcmd, 6);\r
+ ReaderTransmit(dcmd, sizeof(dcmd), NULL);\r
+ int len = ReaderReceive(answer, answer_parity);\r
+ if(!len) {\r
+ if (MF_DBGLEVEL >= 1) Dbprintf("Authentication failed. Card timeout.");\r
+ return 2;\r
}\r
return len;\r
}\r
if(len==1) {\r
if (MF_DBGLEVEL >= MF_DBG_ERROR) Dbprintf("NAK - Authentication failed.");\r
return 1;\r
- }
- return len;
-}
-
-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)
-{
- uint8_t dcmd[4], ecmd[4];
+ }\r
+ return len;\r
+}\r
+\r
+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)\r
+{\r
+ uint8_t dcmd[4], ecmd[4];\r
uint16_t pos, res;\r
uint8_t par[1]; // 1 Byte parity is enough here\r
dcmd[0] = cmd;\r
}\r
\r
memcpy(blockData, receivedAnswer, 16);\r
- return 0;
-}
-
+ return 0;\r
+}\r
+\r
// mifare ultralight commands\r
int mifare_ultra_auth1(uint32_t uid, uint8_t *blockData){\r
\r
return 0;\r
}\r
\r
-int mifare_ultra_readblock(uint32_t uid, uint8_t blockNo, uint8_t *blockData)
-{
- uint16_t len;
- uint8_t bt[2];
+int mifare_ultra_readblock(uint32_t uid, uint8_t blockNo, uint8_t *blockData)\r
+{\r
+ uint16_t len;\r
+ uint8_t bt[2];\r
uint8_t receivedAnswer[MAX_MIFARE_FRAME_SIZE];\r
uint8_t receivedAnswerPar[MAX_MIFARE_PARITY_SIZE];\r
-
\r
- // command MIFARE_CLASSIC_READBLOCK
- len = mifare_sendcmd_short(NULL, 1, 0x30, blockNo, receivedAnswer, receivedAnswerPar, NULL);
- if (len == 1) {
+ \r
+ // command MIFARE_CLASSIC_READBLOCK\r
+ len = mifare_sendcmd_short(NULL, 1, 0x30, blockNo, receivedAnswer, receivedAnswerPar, NULL);\r
+ if (len == 1) {\r
if (MF_DBGLEVEL >= MF_DBG_ERROR)\r
- Dbprintf("Cmd Error: %02x", receivedAnswer[0]);
- return 1;
- }
- if (len != 18) {
+ Dbprintf("Cmd Error: %02x", receivedAnswer[0]);\r
+ return 1;\r
+ }\r
+ if (len != 18) {\r
if (MF_DBGLEVEL >= MF_DBG_ERROR)\r
- Dbprintf("Cmd Error: card timeout. len: %x", len);
- return 2;
- }
-
- memcpy(bt, receivedAnswer + 16, 2);
- AppendCrc14443a(receivedAnswer, 16);
- if (bt[0] != receivedAnswer[16] || bt[1] != receivedAnswer[17]) {
+ Dbprintf("Cmd Error: card timeout. len: %x", len);\r
+ return 2;\r
+ }\r
+ \r
+ memcpy(bt, receivedAnswer + 16, 2);\r
+ AppendCrc14443a(receivedAnswer, 16);\r
+ if (bt[0] != receivedAnswer[16] || bt[1] != receivedAnswer[17]) {\r
if (MF_DBGLEVEL >= MF_DBG_ERROR)\r
- Dbprintf("Cmd CRC response error.");
- return 3;
- }
-
- memcpy(blockData, receivedAnswer, 14);
- return 0;
-}
-
-
-int mifare_classic_writeblock(struct Crypto1State *pcs, uint32_t uid, uint8_t blockNo, uint8_t *blockData)
-{
- // variables
+ Dbprintf("Cmd CRC response error.");\r
+ return 3;\r
+ }\r
+ \r
+ memcpy(blockData, receivedAnswer, 14);\r
+ return 0;\r
+}\r
+\r
+\r
+int mifare_classic_writeblock(struct Crypto1State *pcs, uint32_t uid, uint8_t blockNo, uint8_t *blockData) \r
+{\r
+ // variables\r
uint16_t len, i; \r
uint32_t pos;\r
uint8_t par[3] = {0}; // enough for 18 Bytes to send\r
return 2;\r
}\r
\r
- return 0;
-}
-
-int mifare_ultra_writeblock(uint32_t uid, uint8_t blockNo, uint8_t *blockData)
-{
- uint16_t len;
- uint8_t par[3] = {0}; // enough for 18 parity bits
- uint8_t d_block[18] = {0x00};
+ return 0;\r
+}\r
+\r
+int mifare_ultra_writeblock(uint32_t uid, uint8_t blockNo, uint8_t *blockData) \r
+{\r
+ uint16_t len; \r
+ uint8_t par[3] = {0}; // enough for 18 parity bits\r
+ uint8_t d_block[18] = {0x00};\r
uint8_t receivedAnswer[MAX_MIFARE_FRAME_SIZE];\r
uint8_t receivedAnswerPar[MAX_MIFARE_PARITY_SIZE];\r
-
- // command MIFARE_CLASSIC_WRITEBLOCK
- len = mifare_sendcmd_short(NULL, true, 0xA0, blockNo, receivedAnswer, receivedAnswerPar, NULL);
-
- if ((len != 1) || (receivedAnswer[0] != 0x0A)) { // 0x0a - ACK
+ \r
+ // command MIFARE_CLASSIC_WRITEBLOCK\r
+ len = mifare_sendcmd_short(NULL, true, 0xA0, blockNo, receivedAnswer, receivedAnswerPar, NULL);\r
+\r
+ if ((len != 1) || (receivedAnswer[0] != 0x0A)) { // 0x0a - ACK\r
if (MF_DBGLEVEL >= MF_DBG_ERROR)\r
- Dbprintf("Cmd Addr Error: %02x", receivedAnswer[0]);
- return 1;
- }
-
- memcpy(d_block, blockData, 16);
- AppendCrc14443a(d_block, 16);
-
- ReaderTransmitPar(d_block, sizeof(d_block), par, NULL);
-
- len = ReaderReceive(receivedAnswer, receivedAnswerPar);
-
- if ((len != 1) || (receivedAnswer[0] != 0x0A)) { // 0x0a - ACK
+ Dbprintf("Cmd Addr Error: %02x", receivedAnswer[0]); \r
+ return 1;\r
+ }\r
+\r
+ memcpy(d_block, blockData, 16);\r
+ AppendCrc14443a(d_block, 16);\r
+\r
+ ReaderTransmitPar(d_block, sizeof(d_block), par, NULL);\r
+\r
+ len = ReaderReceive(receivedAnswer, receivedAnswerPar); \r
+\r
+ if ((len != 1) || (receivedAnswer[0] != 0x0A)) { // 0x0a - ACK\r
if (MF_DBGLEVEL >= MF_DBG_ERROR)\r
- Dbprintf("Cmd Data Error: %02x %d", receivedAnswer[0],len);
- return 2;
- }
- return 0;
-}
-
-int mifare_ultra_special_writeblock(uint32_t uid, uint8_t blockNo, uint8_t *blockData)
-{
- uint16_t len;
- uint8_t d_block[8] = {0x00};
+ Dbprintf("Cmd Data Error: %02x %d", receivedAnswer[0],len);\r
+ return 2;\r
+ } \r
+ return 0;\r
+} \r
+\r
+int mifare_ultra_special_writeblock(uint32_t uid, uint8_t blockNo, uint8_t *blockData)\r
+{\r
+ uint16_t len;\r
+ uint8_t d_block[8] = {0x00};\r
uint8_t receivedAnswer[MAX_MIFARE_FRAME_SIZE];\r
uint8_t receivedAnswerPar[MAX_MIFARE_PARITY_SIZE];\r
-
- // command MIFARE_CLASSIC_WRITEBLOCK
- d_block[0]= blockNo;
- memcpy(d_block+1,blockData,4);
- AppendCrc14443a(d_block, 6);
-
- len = mifare_sendcmd_short_special(NULL, 1, 0xA2, d_block, receivedAnswer, receivedAnswerPar, NULL);
-
- if (receivedAnswer[0] != 0x0A) { // 0x0a - ACK
+\r
+ // command MIFARE_CLASSIC_WRITEBLOCK\r
+ d_block[0]= blockNo;\r
+ memcpy(d_block+1,blockData,4);\r
+ AppendCrc14443a(d_block, 6);\r
+\r
+ len = mifare_sendcmd_short_special(NULL, 1, 0xA2, d_block, receivedAnswer, receivedAnswerPar, NULL);\r
+\r
+ if (receivedAnswer[0] != 0x0A) { // 0x0a - ACK\r
if (MF_DBGLEVEL >= MF_DBG_ERROR)\r
- Dbprintf("Cmd Send Error: %02x %d", receivedAnswer[0],len);
- return 1;
- }
-\r return 0;
-}
-
-int mifare_classic_halt(struct Crypto1State *pcs, uint32_t uid)
-{
+ Dbprintf("Cmd Send Error: %02x %d", receivedAnswer[0],len);\r
+ return 1;\r
+ }\r
+ return 0;\r
+}\r
+\r
+int mifare_classic_halt(struct Crypto1State *pcs, uint32_t uid) \r
+{\r
uint16_t len; \r
uint8_t receivedAnswer[MAX_MIFARE_FRAME_SIZE];\r
uint8_t receivedAnswerPar[MAX_MIFARE_PARITY_SIZE];\r
return 1;\r
}\r
\r
- return 0;
-}
-
-int mifare_ultra_halt(uint32_t uid)
-{
- uint16_t len;
+ return 0;\r
+}\r
+\r
+int mifare_ultra_halt(uint32_t uid)\r
+{\r
+ uint16_t len;\r
uint8_t receivedAnswer[MAX_MIFARE_FRAME_SIZE];\r
uint8_t receivedAnswerPar[MAX_MIFARE_PARITY_SIZE];\r
-
- len = mifare_sendcmd_short(NULL, true, 0x50, 0x00, receivedAnswer, receivedAnswerPar, NULL);
- if (len != 0) {
+ \r
+ len = mifare_sendcmd_short(NULL, true, 0x50, 0x00, receivedAnswer, receivedAnswerPar, NULL);\r
+ if (len != 0) {\r
if (MF_DBGLEVEL >= MF_DBG_ERROR)\r
- Dbprintf("halt error. response len: %x", len);
- return 1;
- }
- return 0;
-}
-
+ Dbprintf("halt error. response len: %x", len);\r
+ return 1;\r
+ }\r
+ return 0;\r
+}\r
+\r
\r
// Mifare Memory Structure: up to 32 Sectors with 4 blocks each (1k and 2k cards),\r
// plus evtl. 8 sectors with 16 blocks each (4k cards)\r
}\r
\r
\r
-// work with emulator memory
-void emlSetMem(uint8_t *data, int blockNum, int blocksCount) {
- uint8_t* emCARD = BigBuf_get_EM_addr();
+// work with emulator memory\r
+void emlSetMem(uint8_t *data, int blockNum, int blocksCount) {\r
+ uint8_t* emCARD = BigBuf_get_EM_addr();\r
memcpy(emCARD + blockNum * 16, data, blocksCount * 16);\r
}\r
\r
return 0;\r
}\r
return 1;\r
-}
+}\r
// with the linker script.
//-----------------------------------------------------------------------------
-#include "proxmark3.h"
+#include "../include/proxmark3.h"
#include "apps.h"
extern char __data_start__, __data_src_start__, __data_end__, __bss_start__, __bss_end__;
// Utility functions used in many places, not specific to any piece of code.
//-----------------------------------------------------------------------------
-#include "proxmark3.h"
+#include "../include/proxmark3.h"
#include "util.h"
#include "string.h"
#include "apps.h"
if(!externally_entered && !BUTTON_PRESS()) {
/* Perform a reset to leave flash mode */
- usb_disable();
+ usb_disable();
LED_B_ON();
AT91C_BASE_RSTC->RSTC_RCR = RST_CONTROL_KEY | AT91C_RSTC_PROCRST;
for(;;);
VPATH = ../common
OBJDIR = obj
-LDLIBS = -L/opt/local/lib -L/usr/local/lib ../liblua/liblua.a -lreadline -lpthread -lm
+LDLIBS = -L/mingw/lib -L/opt/local/lib -L/usr/local/lib ../liblua/liblua.a -lm -lreadline -lpthread -lgdi32
LDFLAGS = $(COMMON_FLAGS)
-CFLAGS = -std=c99 -I. -I../include -I../common -I/opt/local/include -I../liblua -Wall $(COMMON_FLAGS) -g -O4
+CFLAGS = -std=c99 -I. -I../include -I../common -I/mingw/include -I/opt/local/include -I../liblua -Wall $(COMMON_FLAGS) -g -O4
LUAPLATFORM = generic
ifneq (,$(findstring MINGW,$(platform)))
CXXFLAGS = -I$(QTDIR)/include -I$(QTDIR)/include/QtCore -I$(QTDIR)/include/QtGui
LUAPLATFORM = linux
endif
+# QT version, 4 or 5
+qtplatform = $(shell $(MOC) -v)
+ifneq (, $(findstring moc 5,$(qtplatform)))
+ 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
+else
+ CXXFLAGS = -I$(QTDIR)/include -I$(QTDIR)/include/QtCore -I$(QTDIR)/include/QtGui
+ QTLDLIBS = -L$(QTDIR)/lib -lQtCore4 -lQtGui4
+endif
ifneq ($(QTLDLIBS),)
QTGUI = $(OBJDIR)/proxgui.o $(OBJDIR)/proxguiqt.o $(OBJDIR)/proxguiqt.moc.o
loclass/elite_crack.c\
loclass/fileutils.c\
mifarehost.c\
+ crc.c \
crc16.c \
+ crc64.c \
iso14443crc.c \
iso15693tools.c \
data.c \
tarbin: $(BINS)
$(TAR) $(TARFLAGS) ../proxmark3-$(platform)-bin.tar $(BINS:%=client/%)
+# must be run as root
+install_kext: Info.plist
+ mkdir -p /System/Library/Extensions/Proxmark3.kext/Contents
+ cp Info.plist /System/Library/Extensions/Proxmark3.kext/Contents
+ chown -R root:wheel /System/Library/Extensions/Proxmark3.kext
+ chmod 755 /System/Library/Extensions/Proxmark3.kext /System/Library/Extensions/Proxmark3.kext/Contents
+ chmod 644 /System/Library/Extensions/Proxmark3.kext/Contents/Info.plist
+ rm -rf /System/Library/Caches/com.apple.kext.caches
+ touch /System/Library/Extensions
+ @echo "*** You may need to reboot for the kext to take effect."
+
lua_build:
@echo Compiling liblua, using platform $(LUAPLATFORM)
cd ../liblua && make $(LUAPLATFORM)
//by marshmellow
void setDemodBuf(uint8_t *buff, size_t size, size_t startIdx)
{
+ if (buff == NULL)
+ return;
+
+ if ( size >= MAX_DEMOD_BUF_LEN)
+ size = MAX_DEMOD_BUF_LEN;
+
size_t i = 0;
for (; i < size; i++){
DemodBuffer[i]=buff[startIdx++];
if(size > (8*32)+2) size = (8*32)+2; //only output a max of 8 blocks of 32 bits most tags will have full bit stream inside that sample size
if (verbose) {
PrintAndLog("FSK decoded bitstream:");
- printBitStream(BitStream,size);
+ printBitStream(BitStream,size);
}
return 1;
if (g_debugMode==1 && verbose) PrintAndLog("no data found, clk: %d, invert: %d, numbits: %d, errCnt: %d",clk,invert,BitLen,errCnt);
return 0;
}
- PrintAndLog("Tried NRZ Demod using Clock: %d - invert: %d - Bits Found: %d",clk,invert,BitLen);
+ if (verbose)
+ PrintAndLog("Tried NRZ Demod using Clock: %d - invert: %d - Bits Found: %d",clk,invert,BitLen);
//prime demod buffer for output
setDemodBuf(BitStream,BitLen,0);
PrintAndLog("# Errors during Demoding (shown as 77 in bit stream): %d",errCnt);
}
if (verbose) {
- PrintAndLog("NRZ demoded bitstream:");
- // Now output the bitstream to the scrollback by line of 16 bits
- printDemodBuff();
+ PrintAndLog("NRZ demoded bitstream:");
+ // Now output the bitstream to the scrollback by line of 16 bits
+ printDemodBuff();
}
return 1;
}
void printDemodBuff(void);
void printBitStream(uint8_t BitStream[], uint32_t bitLen);
void setDemodBuf(uint8_t *buff, size_t size, size_t startIdx);
+
int CmdAmp(const char *Cmd);
int Cmdaskdemod(const char *Cmd);
int CmdAskEM410xDemod(const char *Cmd);
extern uint8_t DemodBuffer[MAX_DEMOD_BUF_LEN];
extern int DemodBufferLen;
+extern uint8_t g_debugMode;
#define BIGBUF_SIZE 40000
#endif
uint32_t temp;
if (strlen(cmd)<2) {
- PrintAndLog("Usage: hf 14a raw [-r] [-c] [-p] [-f] [-b] [-t] <number of bits> <0A 0B 0C ... hex>");
+ PrintAndLog("Usage: hf 14a raw [-r] [-c] [-p] [-a] [-t] <milliseconds> [-b] <number of bits> <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");
*/
int prepareHF15Cmd(char **cmd, UsbCommand *c, uint8_t iso15cmd[], int iso15cmdlen) {
int temp;
- uint8_t *req=c->d.asBytes;
+ uint8_t *req = c->d.asBytes;
uint8_t uid[8] = {0x00};
- uint32_t reqlen=0;
+ uint32_t reqlen = 0;
// strip
while (**cmd==' ' || **cmd=='\t') (*cmd)++;
UsbCommand resp;
uint8_t *recv;
UsbCommand c = {CMD_ISO_15693_COMMAND, {0, 1, 1}}; // len,speed,recv?
- uint8_t *req=c.d.asBytes;
- int reqlen=0;
+ uint8_t *req = c.d.asBytes;
+ int reqlen = 0;
char cmdbuf[100];
- char *cmd=cmdbuf;
+ char *cmd = cmdbuf;
char output[2048]="";
int i;
PrintAndLog(" s selected tag");
PrintAndLog(" u unaddressed mode");
PrintAndLog(" * scan for tag");
- PrintAndLog(" start#: page number to start 0-255");
- PrintAndLog(" count#: number of pages");
return 0;
}
prepareHF15Cmd(&cmd, &c,(uint8_t[]){ISO15_CMD_SYSINFO},1);
- reqlen=c.arg[0];
+ reqlen = c.arg[0];
reqlen=AddCrc(req,reqlen);
c.arg[0]=reqlen;
--- /dev/null
+//-----------------------------------------------------------------------------
+// Copyright (C) 2012 nuit
+//
+// This code is licensed to you under the terms of the GNU GPL, version 2 or,
+// at your option, any later version. See the LICENSE.txt file for the text of
+// the license.
+//-----------------------------------------------------------------------------
+// High frequency MIFARE DESfire commands
+//-----------------------------------------------------------------------------
+
+#include "cmdhfdes.h"
+#include "proxmark3.h"
+#include "cmdmain.h"
+
+static int CmdHelp(const char *Cmd);
+
+int CmdHFDESReader(const char *Cmd)
+{
+ UsbCommand c ={CMD_MIFARE_DES_READER, {3, 0x60, 0}};
+ SendCommand(&c);
+
+ UsbCommand resp;
+ WaitForResponseTimeout(CMD_ACK,&resp,2000);
+ return 0;
+}
+
+int CmdHFDESDbg(const char *Cmd)
+{
+ int dbgMode = param_get32ex(Cmd, 0, 0, 10);
+ if (dbgMode > 4) {
+ PrintAndLog("Max debud mode parameter is 4 \n");
+ }
+
+ if (strlen(Cmd) < 1 || !param_getchar(Cmd, 0) || dbgMode > 4) {
+ PrintAndLog("Usage: hf des dbg <debug level>");
+ PrintAndLog(" 0 - no debug messages");
+ PrintAndLog(" 1 - error messages");
+ PrintAndLog(" 2 - all messages");
+ PrintAndLog(" 4 - extended debug mode");
+ return 0;
+ }
+
+ UsbCommand c = {CMD_MIFARE_SET_DBGMODE, {dbgMode, 0, 0}};
+ SendCommand(&c);
+
+ return 0;
+}
+
+static command_t CommandTable[] =
+{
+ {"help", CmdHelp, 1, "This help"},
+ {"dbg", CmdHFDESDbg, 0, "Set default debug mode"},
+ {"reader", CmdHFDESReader, 0, "Reader"},
+ {NULL, NULL, 0, NULL}
+};
+
+int CmdHFDES(const char *Cmd)
+{
+ //flush
+ WaitForResponseTimeout(CMD_ACK,NULL,100);
+ CmdsParse(CommandTable, Cmd);
+ return 0;
+}
+
+int CmdHelp(const char *Cmd)
+{
+ CmdsHelp(CommandTable);
+ return 0;
+}
--- /dev/null
+//-----------------------------------------------------------------------------
+// Copyright (C) 2012 nuit
+//
+// This code is licensed to you under the terms of the GNU GPL, version 2 or,
+// at your option, any later version. See the LICENSE.txt file for the text of
+// the license.
+//-----------------------------------------------------------------------------
+// High frequency MIFARE DESfire commands
+//-----------------------------------------------------------------------------
+
+#ifndef CMDHFDES_H__
+#define CMDHFDES_H__
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <ctype.h>
+#include "proxmark3.h"
+#include "data.h"
+#include "ui.h"
+#include "cmdparser.h"
+#include "common.h"
+#include "util.h"
+int CmdHFDES(const char *Cmd);
+int CmdHFDESReader(const char *Cmd);
+int CmdHFDESDbg(const char *Cmd);
+#endif
#include "proxmark3.h"
#include "ui.h"
#include "cmdparser.h"
-#include "common.h"
+#include "../include/common.h"
#include "cmdmain.h"
#include "sleep.h"
#include "cmdhfepa.h"
PrintAndLog(" x (Optional) Crack, performs the 'reader attack', nr/ar attack against a legitimate reader, fishes out the key(s)");\r
PrintAndLog("");\r
PrintAndLog(" sample: hf mf sim u 0a0a0a0a ");\r
+ PrintAndLog(" : hf mf sim u 0a0a0a0a i x");\r
return 0;\r
}\r
uint8_t pnr = 0;\r
\r
int CmdHF14AMfCSetBlk(const char *Cmd)\r
{\r
- uint8_t uid[8] = {0x00};\r
+ //uint8_t uid[8] = {0x00};\r
uint8_t memBlock[16] = {0x00};\r
uint8_t blockNo = 0;\r
int res;\r
\r
PrintAndLog("--block number:%2d data:%s", blockNo, sprint_hex(memBlock, 16));\r
\r
- res = mfCSetBlock(blockNo, memBlock, uid, 0, CSETBLOCK_SINGLE_OPER);\r
+ //res = mfCSetBlock(blockNo, memBlock, uid, 0, CSETBLOCK_SINGLE_OPER);\r
+ res = mfCSetBlock(blockNo, memBlock, NULL, 0, CSETBLOCK_SINGLE_OPER);\r
if (res) {\r
PrintAndLog("Can't write block. error=%d", res);\r
return 1;\r
#include <string.h>\r
#include <ctype.h>\r
#include "proxmark3.h"\r
-#include "iso14443crc.h"\r
+#include "../common/iso14443crc.h"\r
#include "data.h"\r
#include "ui.h"\r
#include "cmdparser.h"\r
-#include "common.h"\r
+#include "../include/common.h"\r
#include "util.h"\r
#include "mifarehost.h"\r
\r
int CmdHF14AMfCGetSc(const char* cmd);\r
int CmdHF14AMfCLoad(const char* cmd);\r
int CmdHF14AMfCSave(const char* cmd);\r
-\r
+int GetCardSize();\r
#endif\r
--- /dev/null
+//-----------------------------------------------------------------------------
+// Copyright (C) 2014 Iceman
+//
+// This code is licensed to you under the terms of the GNU GPL, version 2 or,
+// at your option, any later version. See the LICENSE.txt file for the text of
+// the license.
+//-----------------------------------------------------------------------------
+// High frequency MIFARE Desfire commands
+//-----------------------------------------------------------------------------
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <ctype.h>
+#include <openssl/des.h>
+#include "cmdmain.h"
+#include "proxmark3.h"
+#include "../include/common.h"
+#include "../include/mifare.h"
+#include "../common/iso14443crc.h"
+#include "data.h"
+#include "ui.h"
+#include "cmdparser.h"
+#include "util.h"
+#include "cmdhfmfdes.h"
+
+uint8_t CMDPOS = 0;
+uint8_t LENPOS = 1;
+
+uint8_t key_zero_data[16] = { 0x00 };
+uint8_t key_ones_data[16] = { 0x01 };
+uint8_t key_defa_data[16] = { 0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f };
+uint8_t key_picc_data[16] = { 0x40,0x41,0x42,0x43,0x44,0x45,0x46,0x47,0x48,0x49,0x4a,0x4b,0x4c,0x4d,0x4e,0x4f };
+
+static int CmdHelp(const char *Cmd);
+static void xor(unsigned char * dst, unsigned char * src, size_t len);
+static int32_t le24toh (uint8_t data[3]);
+
+
+int CmdHF14ADesWb(const char *Cmd)
+{
+/* uint8_t blockNo = 0;
+ uint8_t keyType = 0;
+ uint8_t key[6] = {0, 0, 0, 0, 0, 0};
+ uint8_t bldata[16] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
+
+ char cmdp = 0x00;
+
+ if (strlen(Cmd)<3) {
+ PrintAndLog("Usage: hf mf wrbl <block number> <key A/B> <key (12 hex symbols)> <block data (32 hex symbols)>");
+ PrintAndLog(" sample: hf mf wrbl 0 A FFFFFFFFFFFF 000102030405060708090A0B0C0D0E0F");
+ return 0;
+ }
+
+ blockNo = param_get8(Cmd, 0);
+ cmdp = param_getchar(Cmd, 1);
+ if (cmdp == 0x00) {
+ PrintAndLog("Key type must be A or B");
+ return 1;
+ }
+ if (cmdp != 'A' && cmdp != 'a') keyType = 1;
+ if (param_gethex(Cmd, 2, key, 12)) {
+ PrintAndLog("Key must include 12 HEX symbols");
+ return 1;
+ }
+ if (param_gethex(Cmd, 3, bldata, 32)) {
+ PrintAndLog("Block data must include 32 HEX symbols");
+ return 1;
+ }
+ PrintAndLog("--block no:%02x key type:%02x key:%s", blockNo, keyType, sprint_hex(key, 6));
+ PrintAndLog("--data: %s", sprint_hex(bldata, 16));
+
+ UsbCommand c = {CMD_MIFARE_WRITEBL, {blockNo, keyType, 0}};
+ memcpy(c.d.asBytes, key, 6);
+ memcpy(c.d.asBytes + 10, bldata, 16);
+ SendCommand(&c);
+
+ UsbCommand resp;
+ if (WaitForResponseTimeout(CMD_ACK,&resp,1500)) {
+ uint8_t isOK = resp.arg[0] & 0xff;
+ PrintAndLog("isOk:%02x", isOK);
+ } else {
+ PrintAndLog("Command execute timeout");
+ }
+ */
+ return 0;
+}
+
+int CmdHF14ADesRb(const char *Cmd)
+{
+ // uint8_t blockNo = 0;
+ // uint8_t keyType = 0;
+ // uint8_t key[6] = {0, 0, 0, 0, 0, 0};
+
+ // char cmdp = 0x00;
+
+
+ // if (strlen(Cmd)<3) {
+ // PrintAndLog("Usage: hf mf rdbl <block number> <key A/B> <key (12 hex symbols)>");
+ // PrintAndLog(" sample: hf mf rdbl 0 A FFFFFFFFFFFF ");
+ // return 0;
+ // }
+
+ // blockNo = param_get8(Cmd, 0);
+ // cmdp = param_getchar(Cmd, 1);
+ // if (cmdp == 0x00) {
+ // PrintAndLog("Key type must be A or B");
+ // return 1;
+ // }
+ // if (cmdp != 'A' && cmdp != 'a') keyType = 1;
+ // if (param_gethex(Cmd, 2, key, 12)) {
+ // PrintAndLog("Key must include 12 HEX symbols");
+ // return 1;
+ // }
+ // PrintAndLog("--block no:%02x key type:%02x key:%s ", blockNo, keyType, sprint_hex(key, 6));
+
+ // UsbCommand c = {CMD_MIFARE_READBL, {blockNo, keyType, 0}};
+ // memcpy(c.d.asBytes, key, 6);
+ // SendCommand(&c);
+
+ // UsbCommand resp;
+ // if (WaitForResponseTimeout(CMD_ACK,&resp,1500)) {
+ // uint8_t isOK = resp.arg[0] & 0xff;
+ // uint8_t * data = resp.d.asBytes;
+
+ // if (isOK)
+ // PrintAndLog("isOk:%02x data:%s", isOK, sprint_hex(data, 16));
+ // else
+ // PrintAndLog("isOk:%02x", isOK);
+ // } else {
+ // PrintAndLog("Command execute timeout");
+ // }
+
+ return 0;
+}
+
+int CmdHF14ADesInfo(const char *Cmd){
+
+ UsbCommand c = {CMD_MIFARE_DESFIRE_INFO};
+ SendCommand(&c);
+ UsbCommand resp;
+
+ if ( !WaitForResponseTimeout(CMD_ACK,&resp,1500) ) {
+ PrintAndLog("Command execute timeout");
+ return 0;
+ }
+ uint8_t isOK = resp.arg[0] & 0xff;
+ if ( !isOK ){
+ PrintAndLog("Command unsuccessful");
+ return 0;
+ }
+ PrintAndLog("");
+ PrintAndLog("-- Desfire Information --------------------------------------");
+ PrintAndLog("-------------------------------------------------------------");
+ PrintAndLog(" UID : %s",sprint_hex(resp.d.asBytes, 7));
+ PrintAndLog(" Batch number : %s",sprint_hex(resp.d.asBytes+28,5));
+ PrintAndLog(" Production date : week %02x, 20%02x",resp.d.asBytes[33], resp.d.asBytes[34]);
+ PrintAndLog(" -----------------------------------------------------------");
+ PrintAndLog(" Hardware Information");
+ PrintAndLog(" Vendor Id : %s", GetVendorStr(resp.d.asBytes[7]));
+ PrintAndLog(" Type : 0x%02X",resp.d.asBytes[8]);
+ PrintAndLog(" Subtype : 0x%02X",resp.d.asBytes[9]);
+ PrintAndLog(" Version : %d.%d",resp.d.asBytes[10], resp.d.asBytes[11]);
+ PrintAndLog(" Storage size : %s",GetCardSizeStr(resp.d.asBytes[12]));
+ PrintAndLog(" Protocol : %s",GetProtocolStr(resp.d.asBytes[13]));
+ PrintAndLog(" -----------------------------------------------------------");
+ PrintAndLog(" Software Information");
+ PrintAndLog(" Vendor Id : %s",GetVendorStr(resp.d.asBytes[14]));
+ PrintAndLog(" Type : 0x%02X",resp.d.asBytes[15]);
+ PrintAndLog(" Subtype : 0x%02X",resp.d.asBytes[16]);
+ PrintAndLog(" Version : %d.%d",resp.d.asBytes[17], resp.d.asBytes[18]);
+ PrintAndLog(" storage size : %s", GetCardSizeStr(resp.d.asBytes[19]));
+ PrintAndLog(" Protocol : %s", GetProtocolStr(resp.d.asBytes[20]));
+ PrintAndLog("-------------------------------------------------------------");
+
+ // Master Key settings
+ GetKeySettings(NULL);
+
+ // Free memory on card
+ c.cmd = CMD_MIFARE_DESFIRE;
+ c.arg[0] = (INIT | DISCONNECT);
+ c.arg[1] = 0x01;
+ c.d.asBytes[0] = GET_FREE_MEMORY;
+ SendCommand(&c);
+ if ( !WaitForResponseTimeout(CMD_ACK,&resp,1500)) {
+ return 0;
+ }
+
+ uint8_t tmp[3];
+ memcpy(tmp, resp.d.asBytes+3,3);
+
+ PrintAndLog(" Available free memory on card : %d bytes", le24toh( tmp ));
+ PrintAndLog("-------------------------------------------------------------");
+
+ /*
+ Card Master key (CMK) 0x00 AID = 00 00 00 (card level)
+ Application Master Key (AMK) 0x00 AID != 00 00 00
+ Application keys (APK) 0x01-0x0D
+ Application free 0x0E
+ Application never 0x0F
+
+ ACCESS RIGHTS:
+ keys 0,1,2,3 C
+ keys 4,5,6,7 RW
+ keys 8,9,10,11 W
+ keys 12,13,14,15 R
+
+ */
+
+ return 1;
+}
+
+char * GetVendorStr( uint8_t id){
+ static char buf[30];
+ char *retStr = buf;
+
+ if ( id == 0x04 )
+ sprintf(retStr, "0x%02X (NXP)",id);
+ else
+ sprintf(retStr,"0x%02X (Unknown)",id);
+ return buf;
+}
+
+/*
+ The 7 MSBits (= n) code the storage size itself based on 2^n,
+ the LSBit is set to '0' if the size is exactly 2^n
+ and set to '1' if the storage size is between 2^n and 2^(n+1).
+ For this version of DESFire the 7 MSBits are set to 0x0C (2^12 = 4096) and the LSBit is '0'.
+*/
+char * GetCardSizeStr( uint8_t fsize ){
+
+ static char buf[30];
+ char *retStr = buf;
+
+ uint16_t usize = 1 << ((fsize >>1) + 1);
+ uint16_t lsize = 1 << (fsize >>1);
+
+ // is LSB set?
+ if ( fsize & (1 << 0 ) )
+ sprintf(retStr, "0x%02X (%d - %d bytes)",fsize, usize, lsize);
+ else
+ sprintf(retStr, "0x%02X (%d bytes)", fsize, lsize);
+ return buf;
+}
+
+char * GetProtocolStr(uint8_t id){
+
+ static char buf[30];
+ char *retStr = buf;
+
+ if ( id == 0x05)
+ sprintf(retStr,"0x%02X (ISO 14443-3, 14443-4)", id);
+ else
+ sprintf(retStr,"0x%02X", id);
+ return buf;
+}
+
+void GetKeySettings( uint8_t *aid){
+
+ char messStr[512] = {0x00};
+ char *str = messStr;
+ uint8_t isOK = 0;
+ uint32_t options = NONE;
+ UsbCommand c;
+ UsbCommand resp;
+
+ //memset(messStr, 0x00, 512);
+
+ c.cmd = CMD_MIFARE_DESFIRE;
+
+ if ( aid == NULL ){
+ PrintAndLog(" CMK - PICC, Card Master Key settings ");
+ PrintAndLog("");
+ c.arg[CMDPOS] = (INIT | DISCONNECT);
+ c.arg[LENPOS] = 0x01;
+ c.d.asBytes[0] = GET_KEY_SETTINGS; // 0x45
+ SendCommand(&c);
+ if ( !WaitForResponseTimeout(CMD_ACK,&resp,1000) ) {return;}
+ isOK = resp.arg[0] & 0xff;
+ if ( !isOK ){
+ PrintAndLog(" Can't select master application");
+ return;
+ }
+
+ str = (resp.d.asBytes[3] & (1 << 3 )) ? "YES":"NO";
+ PrintAndLog(" [0x08] Configuration changeable : %s", str);
+ str = (resp.d.asBytes[3] & (1 << 2 )) ? "NO":"YES";
+ PrintAndLog(" [0x04] CMK required for create/delete : %s",str);
+ str = (resp.d.asBytes[3] & (1 << 1 )) ? "NO":"YES";
+ PrintAndLog(" [0x02] Directory list access with CMK : %s",str);
+ str = (resp.d.asBytes[3] & (1 << 0 )) ? "YES" : "NO";
+ PrintAndLog(" [0x01] CMK is changeable : %s", str);
+
+ c.arg[LENPOS] = 0x02; //LEN
+ c.d.asBytes[0] = GET_KEY_VERSION; //0x64
+ c.d.asBytes[1] = 0x00;
+ SendCommand(&c);
+ if ( !WaitForResponseTimeout(CMD_ACK,&resp,1000) ) {
+ return;
+ }
+ isOK = resp.arg[0] & 0xff;
+ if ( !isOK ){
+ PrintAndLog(" Can't read key-version");
+ return;
+ }
+ PrintAndLog("");
+ PrintAndLog(" Max number of keys : %d", resp.d.asBytes[4]);
+ PrintAndLog(" Master key Version : %d (0x%02x)", resp.d.asBytes[3], resp.d.asBytes[3]);
+ PrintAndLog(" ----------------------------------------------------------");
+
+ c.arg[LENPOS] = 0x02; //LEN
+ c.d.asBytes[0] = AUTHENTICATE; //0x0A
+ c.d.asBytes[1] = 0x00; // KEY 0
+ SendCommand(&c);
+ if ( !WaitForResponseTimeout(CMD_ACK,&resp,1000) ) {return;}
+ isOK = resp.d.asBytes[2] & 0xff;
+ PrintAndLog(" [0x0A] Authenticate : %s", ( isOK==0xAE ) ? "NO":"YES");
+
+ c.d.asBytes[0] = AUTHENTICATE_ISO; //0x1A
+ SendCommand(&c);
+ if ( !WaitForResponseTimeout(CMD_ACK,&resp,1000) ) {return;}
+ isOK = resp.d.asBytes[2] & 0xff;
+ PrintAndLog(" [0x1A] Authenticate ISO : %s", ( isOK==0xAE ) ? "NO":"YES");
+
+ c.d.asBytes[0] = AUTHENTICATE_AES; //0xAA
+ SendCommand(&c);
+ if ( !WaitForResponseTimeout(CMD_ACK,&resp,1000) ) {return;}
+ isOK = resp.d.asBytes[2] & 0xff;
+ PrintAndLog(" [0xAA] Authenticate AES : %s", ( isOK==0xAE ) ? "NO":"YES");
+ PrintAndLog("");
+ PrintAndLog(" ----------------------------------------------------------");
+
+ } else {
+ PrintAndLog(" AMK - Application Master Key settings");
+
+ // SELECT AID
+ c.arg[0] = (INIT | CLEARTRACE);
+ c.arg[LENPOS] = 0x04;
+ c.d.asBytes[0] = SELECT_APPLICATION; // 0x5a
+ memcpy(c.d.asBytes+1, aid, 3);
+ SendCommand(&c);
+
+ if (!WaitForResponseTimeout(CMD_ACK,&resp,1500) ) {
+ PrintAndLog(" Timed-out");
+ return;
+ }
+ isOK = resp.arg[0] & 0xff;
+ if ( !isOK ){
+ PrintAndLog(" Can't select AID: %s",sprint_hex(aid,3));
+ return;
+ }
+
+ // KEY SETTINGS
+ options = NONE;
+ c.arg[0] = options;
+ c.arg[LENPOS] = 0x01;
+ c.d.asBytes[0] = GET_KEY_SETTINGS; // 0x45
+ SendCommand(&c);
+ if ( !WaitForResponseTimeout(CMD_ACK,&resp,1500) ) {
+ return;
+ }
+ isOK = resp.arg[0] & 0xff;
+ if ( !isOK ){
+ PrintAndLog(" Can't read Application Master key settings");
+ } else {
+ // Access rights.
+ uint8_t rights = (resp.d.asBytes[3] >> 4 && 0xff);
+ switch (rights){
+ case 0x00:
+ str = "AMK authentication is necessary to change any key (default)";
+ break;
+ case 0x0e:
+ str = "Authentication with the key to be changed (same KeyNo) is necessary to change a key";
+ break;
+ case 0x0f:
+ str = "All keys (except AMK,see Bit0) within this application are frozen";
+ break;
+ default:
+ str = "Authentication with the specified key is necessary to change any ley. A change key and a PICC master key (CMK) can only be changed after authentication with the master key. For keys other then the master or change key, an authentication with the same key is needed.";
+ break;
+ }
+ PrintAndLog("Changekey Access rights");
+ PrintAndLog("-- %s",str);
+ PrintAndLog("");
+ // same as CMK
+ str = (resp.d.asBytes[3] & (1 << 3 )) ? "YES":"NO";
+ PrintAndLog(" 0x08 Configuration changeable : %s", str);
+ str = (resp.d.asBytes[3] & (1 << 2 )) ? "NO":"YES";
+ PrintAndLog(" 0x04 AMK required for create/delete : %s",str);
+ str = (resp.d.asBytes[3] & (1 << 1 )) ? "NO":"YES";
+ PrintAndLog(" 0x02 Directory list access with AMK : %s",str);
+ str = (resp.d.asBytes[3] & (1 << 0 )) ? "YES" : "NO";
+ PrintAndLog(" 0x01 AMK is changeable : %s", str);
+ }
+
+ // KEY VERSION - AMK
+ c.arg[0] = NONE;
+ c.arg[LENPOS] = 0x02;
+ c.d.asBytes[0] = GET_KEY_VERSION; //0x64
+ c.d.asBytes[1] = 0x00;
+ SendCommand(&c);
+ if ( !WaitForResponseTimeout(CMD_ACK,&resp,1500) ) {
+ PrintAndLog(" Timed-out");
+ return;
+ }
+
+ int numOfKeys;
+
+ isOK = resp.arg[0] & 0xff;
+ if ( !isOK ){
+ PrintAndLog(" Can't read Application Master key version. Trying all keys");
+ numOfKeys = MAX_NUM_KEYS;
+ }
+ else{
+ numOfKeys = resp.d.asBytes[4];
+ PrintAndLog("");
+ PrintAndLog(" Max number of keys : %d", numOfKeys );
+ PrintAndLog(" Application Master key Version : %d (0x%02x)", resp.d.asBytes[3], resp.d.asBytes[3]);
+ PrintAndLog("-------------------------------------------------------------");
+ }
+
+ // LOOP over numOfKeys that we got before.
+ // From 0x01 to numOfKeys. We already got 0x00. (AMK)
+ for(int i=0x01; i<=0x0f; ++i){
+
+ }
+
+
+ }
+}
+
+int CmdHF14ADesEnumApplications(const char *Cmd){
+
+ uint8_t isOK = 0x00;
+ uint8_t aid[3];
+ uint32_t options = (INIT | DISCONNECT);
+
+ UsbCommand c = {CMD_MIFARE_DESFIRE, {options , 0x01 }};
+ c.d.asBytes[0] = GET_APPLICATION_IDS; //0x6a
+
+ SendCommand(&c);
+ UsbCommand resp;
+
+ if ( !WaitForResponseTimeout(CMD_ACK,&resp,1500) ) {
+ return 0;
+ }
+ isOK = resp.arg[0] & 0xff;
+ if ( !isOK ){
+ PrintAndLog("Command unsuccessful");
+ return 0;
+ }
+ PrintAndLog("");
+ PrintAndLog("-- Desfire Enumerate Applications ---------------------------");
+ PrintAndLog("-------------------------------------------------------------");
+
+ UsbCommand respAid;
+ UsbCommand respFiles;
+
+ uint8_t num = 0;
+ int max = resp.arg[1] -3 -2;
+
+ for(int i=3; i<=max; i+=3){
+ PrintAndLog(" Aid %d : %02X %02X %02X ",num ,resp.d.asBytes[i],resp.d.asBytes[i+1],resp.d.asBytes[i+2]);
+ num++;
+
+ aid[0] = resp.d.asBytes[i];
+ aid[1] = resp.d.asBytes[i+1];
+ aid[2] = resp.d.asBytes[i+2];
+ GetKeySettings(aid);
+
+ // Select Application
+ c.arg[CMDPOS] = INIT;
+ c.arg[LENPOS] = 0x04;
+ c.d.asBytes[0] = SELECT_APPLICATION; // 0x5a
+ c.d.asBytes[1] = resp.d.asBytes[i];
+ c.d.asBytes[2] = resp.d.asBytes[i+1];
+ c.d.asBytes[3] = resp.d.asBytes[i+2];
+ SendCommand(&c);
+
+ if (!WaitForResponseTimeout(CMD_ACK,&respAid,1500) ) {
+ PrintAndLog(" Timed-out");
+ continue;
+ }
+ isOK = respAid.d.asBytes[2] & 0xff;
+ if ( isOK != 0x00 ){
+ PrintAndLog(" Can't select AID: %s",sprint_hex(resp.d.asBytes+i,3));
+ continue;
+ }
+
+ // Get File IDs
+ c.arg[CMDPOS] = NONE;
+ c.arg[LENPOS] = 0x01;
+ c.d.asBytes[0] = GET_FILE_IDS; // 0x6f
+ SendCommand(&c);
+
+ if ( !WaitForResponseTimeout(CMD_ACK,&respFiles,1500) ) {
+ PrintAndLog(" Timed-out");
+ continue;
+ } else {
+ isOK = respFiles.d.asBytes[2] & 0xff;
+ if ( !isOK ){
+ PrintAndLog(" Can't get file ids ");
+ } else {
+ int respfileLen = resp.arg[1]-3-2;
+ for (int j=0; j< respfileLen; ++j){
+ PrintAndLog(" Fileid %d :", resp.d.asBytes[j+3]);
+ }
+ }
+ }
+
+ // Get ISO File IDs
+ c.arg[CMDPOS] = DISCONNECT;
+ c.arg[LENPOS] = 0x01;
+ c.d.asBytes[0] = GET_ISOFILE_IDS; // 0x61
+ SendCommand(&c);
+
+ if ( !WaitForResponseTimeout(CMD_ACK,&respFiles,1500) ) {
+ PrintAndLog(" Timed-out");
+ continue;
+ } else {
+ isOK = respFiles.d.asBytes[2] & 0xff;
+ if ( !isOK ){
+ PrintAndLog(" Can't get ISO file ids ");
+ } else {
+ int respfileLen = resp.arg[1]-3-2;
+ for (int j=0; j< respfileLen; ++j){
+ PrintAndLog(" ISO Fileid %d :", resp.d.asBytes[j+3]);
+ }
+ }
+ }
+
+
+ }
+ PrintAndLog("-------------------------------------------------------------");
+
+
+ return 1;
+}
+
+// MIAFRE DesFire Authentication
+//
+#define BUFSIZE 256
+int CmdHF14ADesAuth(const char *Cmd){
+
+ // NR DESC KEYLENGHT
+ // ------------------------
+ // 1 = DES 8
+ // 2 = 3DES 16
+ // 3 = 3K 3DES 24
+ // 4 = AES 16
+
+ uint8_t keylength = 8;
+ unsigned char key[24];
+
+ if (strlen(Cmd)<3) {
+ PrintAndLog("Usage: hf mfdes auth <1|2|3> <1|2|3|4> <keyno> <key> ");
+ PrintAndLog(" Auth modes");
+ PrintAndLog(" 1 = normal, 2 = iso, 3 = aes");
+ PrintAndLog(" Crypto");
+ PrintAndLog(" 1 = DES 2 = 3DES 3 = 3K3DES 4 = AES");
+ PrintAndLog("");
+ PrintAndLog(" sample: hf mfdes auth 1 1 0 11223344");
+ PrintAndLog(" sample: hf mfdes auth 3 4 0 404142434445464748494a4b4c4d4e4f");
+ return 0;
+ }
+ uint8_t cmdAuthMode = param_get8(Cmd,0);
+ uint8_t cmdAuthAlgo = param_get8(Cmd,1);
+ uint8_t cmdKeyNo = param_get8(Cmd,2);
+
+ switch (cmdAuthMode)
+ {
+ case 1:
+ if ( cmdAuthAlgo != 1 && cmdAuthAlgo != 2) {
+ PrintAndLog("Crypto algo not valid for the auth mode");
+ return 1;
+ }
+ break;
+ case 2:
+ if ( cmdAuthAlgo != 1 && cmdAuthAlgo != 2 && cmdAuthAlgo != 3) {
+ PrintAndLog("Crypto algo not valid for the auth mode");
+ return 1;
+ }
+ break;
+ case 3:
+ if ( cmdAuthAlgo != 4) {
+ PrintAndLog("Crypto algo not valid for the auth mode");
+ return 1;
+ }
+ break;
+ default:
+ PrintAndLog("Wrong Auth mode");
+ return 1;
+ break;
+ }
+
+ switch (cmdAuthAlgo){
+ case 2:
+ keylength = 16;
+ PrintAndLog("3DES selected");
+ break;
+ case 3:
+ keylength = 24;
+ PrintAndLog("3 key 3DES selected");
+ break;
+ case 4:
+ keylength = 16;
+ PrintAndLog("AES selected");
+ break;
+ default:
+ cmdAuthAlgo = 1;
+ keylength = 8;
+ PrintAndLog("DES selected");
+ break;
+ }
+
+ // key
+ if (param_gethex(Cmd, 3, key, keylength*2)) {
+ PrintAndLog("Key must include %d HEX symbols", keylength);
+ return 1;
+ }
+ // algo, nyckellängd,
+ UsbCommand c = {CMD_MIFARE_DESFIRE_AUTH1, { cmdAuthMode, cmdAuthAlgo, cmdKeyNo }};
+
+ c.d.asBytes[0] = keylength;
+ memcpy(c.d.asBytes+1, key, keylength);
+
+ SendCommand(&c);
+ UsbCommand resp;
+
+ if (!WaitForResponseTimeout(CMD_ACK,&resp,3000)) {
+ PrintAndLog("Client command execute timeout");
+ return 0;
+ }
+
+ uint8_t isOK = resp.arg[0] & 0xff;
+ if ( isOK) {
+ uint8_t * data= resp.d.asBytes;
+
+ PrintAndLog(" Key :%s",sprint_hex(key, keylength));
+ PrintAndLog(" SESSION :%s",sprint_hex(data, keylength));
+ PrintAndLog("-------------------------------------------------------------");
+ //PrintAndLog(" Expected :B5 21 9E E8 1A A7 49 9D 21 96 68 7E 13 97 38 56");
+ } else{
+ PrintAndLog("Client command failed.");
+ }
+ PrintAndLog("-------------------------------------------------------------");
+ return 1;
+}
+
+
+static void xor(unsigned char * dst, unsigned char * src, size_t len) {
+ for( ; len > 0; len--,dst++,src++)
+ *dst ^= *src;
+}
+
+static int32_t le24toh (uint8_t data[3]) {
+ return (data[2] << 16) | (data[1] << 8) | data[0];
+}
+
+static command_t CommandTable[] =
+{
+ {"help", CmdHelp, 1, "This help"},
+ {"auth", CmdHF14ADesAuth, 0, "Tries a MIFARE DesFire Authentication"},
+ {"rb", CmdHF14ADesRb, 0, "Read MIFARE DesFire block"},
+ {"wb", CmdHF14ADesWb, 0, "write MIFARE DesFire block"},
+ {"info", CmdHF14ADesInfo, 0, "Get MIFARE DesFire information"},
+ {"enum", CmdHF14ADesEnumApplications,0, "Tries enumerate all applications"},
+ {NULL, NULL, 0, NULL}
+};
+
+int CmdHFMFDes(const char *Cmd)
+{
+ // flush
+ WaitForResponseTimeout(CMD_ACK,NULL,100);
+ CmdsParse(CommandTable, Cmd);
+ return 0;
+}
+
+int CmdHelp(const char *Cmd)
+{
+ CmdsHelp(CommandTable);
+ return 0;
+}
+
+
--- /dev/null
+//-----------------------------------------------------------------------------
+// Copyright (C) 2014 Iceman
+//
+// This code is licensed to you under the terms of the GNU GPL, version 2 or,
+// at your option, any later version. See the LICENSE.txt file for the text of
+// the license.
+//-----------------------------------------------------------------------------
+// High frequency MIFARE Desfire commands
+//-----------------------------------------------------------------------------
+
+int CmdHFMFDes(const char *Cmd);
+int CmdHF14ADesAuth(const char* cmd);
+int CmdHF14ADesRb(const char* cmd);
+int CmdHF14ADesWb(const char* cmd);
+int CmdHF14ADesInfo(const char *Cmd);
+int CmdHF14ADesEnumApplications(const char *Cmd);
+
+char * GetCardSizeStr( uint8_t fsize );
+char * GetVendorStr( uint8_t id);
+char * GetProtocolStr(uint8_t id);
+void GetKeySettings( uint8_t * aid);
+
+// Command options for Desfire behavior.
+enum {
+ NONE = 0x00,
+ INIT = 0x01,
+ DISCONNECT = 0x02,
+ CLEARTRACE = 0x04,
+ BAR = 0x08,
+} CmdOptions ;
+
+
+#define CREATE_APPLICATION 0xca
+#define DELETE_APPLICATION 0xda
+#define GET_APPLICATION_IDS 0x6a
+#define SELECT_APPLICATION 0x5a
+#define FORMAT_PICC 0xfc
+#define GET_VERSION 0x60
+#define READ_DATA 0xbd
+#define WRITE_DATA 0x3d
+#define GET_VALUE 0x6c
+#define CREDIT 0x0c
+#define DEBIT 0xdc
+#define LIMITED_CREDIT 0x1c
+#define WRITE_RECORD 0x3b
+#define READ_RECORDS 0xbb
+#define CLEAR_RECORD_FILE 0xeb
+#define COMMIT_TRANSACTION 0xc7
+#define ABORT_TRANSACTION 0xa7
+#define GET_FREE_MEMORY 0x6e
+#define GET_FILE_IDS 0x6f
+#define GET_ISOFILE_IDS 0x61
+#define GET_FILE_SETTINGS 0xf5
+#define CHANGE_FILE_SETTINGS 0x5f
+#define CREATE_STD_DATA_FILE 0xcd
+#define CREATE_BACKUP_DATA_FILE 0xcb
+#define CREATE_VALUE_FILE 0xcc
+#define CREATE_LINEAR_RECORD_FILE 0xc1
+#define CREATE_CYCLIC_RECORD_FILE 0xc0
+#define DELETE_FILE 0xdf
+#define AUTHENTICATE 0x0a // AUTHENTICATE_NATIVE
+#define AUTHENTICATE_ISO 0x1a // AUTHENTICATE_STANDARD
+#define AUTHENTICATE_AES 0xaa
+#define CHANGE_KEY_SETTINGS 0x54
+#define GET_KEY_SETTINGS 0x45
+#define CHANGE_KEY 0xc4
+#define GET_KEY_VERSION 0x64
+#define AUTHENTICATION_FRAME 0xAF
+
+#define MAX_NUM_KEYS 0x0F
+#define MAX_APPLICATION_COUNT 28
+#define MAX_FILE_COUNT 32
+#define MAX_FRAME_SIZE 60
+#define NOT_YET_AUTHENTICATED 255
+#define FRAME_PAYLOAD_SIZE (MAX_FRAME_SIZE - 5)
\ No newline at end of file
--- /dev/null
+//-----------------------------------------------------------------------------
+// Copyright (C) 2014 Andy Davies
+//
+// This code is licensed to you under the terms of the GNU GPL, version 2 or,
+// at your option, any later version. See the LICENSE.txt file for the text of
+// the license.
+//-----------------------------------------------------------------------------
+// High frequency MIFARE commands
+//-----------------------------------------------------------------------------
+
+#include "cmdhfmf.h"
+#include "util.h"
+#include <openssl/des.h>
+#include <openssl/aes.h>
+
+static int CmdHelp(const char *Cmd);
+
+//DESFIRE
+// Reader 2 Card : 020A, key (1 byte), CRC1 CRC2 ; auth (020a00)
+// Card 2 Reader : 02AF, 8 Bytes(b0), CRC1 CRC2
+// Reader 2 Card : 03AF, 8 Bytes(b1),8 bytes(b2), CRC1 CRC2
+// Card 2 Reader : 0300, 8 bytes(b3), CRC1 CRC2 ; success
+
+//send 020A00, receive enc(nc)
+
+//02AE = error
+//receive b3=enc(r4)
+//r5=dec(b3)
+//n'r=rol(r5)
+//verify n'r=nr
+
+int CmdHF14AMfDESAuth(const char *Cmd){
+
+ uint8_t blockNo = 0;
+ //keyNo=0;
+ uint32_t cuid=0;
+ uint8_t reply[16];
+ //DES_cblock r1_b1;
+ uint8_t b1[8]={ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
+ uint8_t b2[8]={ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
+ DES_cblock nr, b0, r1, r0;
+
+
+ uint8_t key[8]={ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
+ //DES_cblock iv={0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
+ DES_key_schedule ks1;
+ DES_cblock key1;
+
+ if (strlen(Cmd)<1) {
+ PrintAndLog("Usage: hf desfire des-auth k <key number>");
+ PrintAndLog(" sample: hf desfire des-auth k 0");
+ return 0;
+ }
+
+ //Change key to user defined one
+
+ memcpy(key1,key,8);
+ //memcpy(key2,key+8,8);
+ DES_set_key((DES_cblock *)key1,&ks1);
+ //DES_set_key((DES_cblock *)key2,&ks2);
+
+ //Auth1
+ UsbCommand c = {CMD_MIFARE_DES_AUTH1, {blockNo}};
+ SendCommand(&c);
+ UsbCommand resp;
+ if (WaitForResponseTimeout(CMD_ACK,&resp,1500)) {
+ uint8_t isOK = resp.arg[0] & 0xff;
+ cuid = resp.arg[1];
+ uint8_t * data= resp.d.asBytes;
+
+ if (isOK){
+ PrintAndLog("enc(nc)/b0:%s", sprint_hex(data+2,8));
+ memcpy(b0,data+2,8);
+ }
+ } else {
+ PrintAndLog("Command execute timeout");
+ }
+
+ //Do crypto magic
+ DES_random_key(&nr);
+ //b1=dec(nr)
+ //r0=dec(b0)
+ DES_ecb_encrypt(&nr,&b1,&ks1,0);
+ DES_ecb_encrypt(&b0,&r0,&ks1,0);
+ //PrintAndLog("b1:%s",sprint_hex(b1, 8));
+ PrintAndLog("r0:%s",sprint_hex(r0, 8));
+ //r1=rol(r0)
+ memcpy(r1,r0,8);
+ rol(r1,8);
+ PrintAndLog("r1:%s",sprint_hex(r1, 8));
+ for(int i=0;i<8;i++){
+ b2[i]=(r1[i] ^ b1[i]);
+ }
+ DES_ecb_encrypt(&b2,&b2,&ks1,0);
+ //PrintAndLog("b1:%s",sprint_hex(b1, 8));
+ PrintAndLog("b2:%s",sprint_hex(b2, 8));
+
+ //Auth2
+ UsbCommand d = {CMD_MIFARE_DES_AUTH2, {cuid}};
+ memcpy(reply,b1,8);
+ memcpy(reply+8,b2,8);
+ memcpy(d.d.asBytes,reply, 16);
+ SendCommand(&d);
+
+ UsbCommand respb;
+ if (WaitForResponseTimeout(CMD_ACK,&respb,1500)) {
+ uint8_t isOK = respb.arg[0] & 0xff;
+ uint8_t * data2= respb.d.asBytes;
+
+ if (isOK){
+ PrintAndLog("b3:%s", sprint_hex(data2+2, 8));
+ }
+
+ } else {
+ PrintAndLog("Command execute timeout");
+ }
+ return 1;
+}
+
+//EV1
+// Reader 2 Card : 02AA, key (1 byte), CRC1 CRC2 ; auth
+// Card 2 Reader : 02AF, 16 Bytes(b0), CRC1 CRC2
+// Reader 2 Card : 03AF, 16 Bytes(b1),16Bytes(b2) CRC1 CRC2
+// Card 2 Reader : 0300, 16 bytes(b3), CRC1 CRC2 ; success
+int CmdHF14AMfAESAuth(const char *Cmd){
+
+ uint8_t blockNo = 0;
+ //keyNo=0;
+ uint32_t cuid=0;
+ uint8_t reply[32];
+ //DES_cblock r1_b1;
+ //unsigned char * b1, b2, nr, b0, r0, r1;
+
+ uint8_t b1[16]={ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
+ uint8_t b2[16]={ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
+ uint8_t nr[16]={ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
+ uint8_t b0[16]={ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
+ uint8_t r0[16]={ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
+ uint8_t r1[16]={ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
+ //
+ uint8_t key[16]={ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
+ uint8_t iv[16]={ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
+ AES_KEY key_e;
+ AES_KEY key_d;
+
+ if (strlen(Cmd)<1) {
+ PrintAndLog("Usage: hf desfire aes-auth k <key number>");
+ PrintAndLog(" sample: hf desfire aes-auth k 0");
+ return 0;
+ }
+
+ //Change key to user defined one
+ //
+ // int private_AES_set_encrypt_key(const unsigned char *userKey, const int bits,AES_KEY *key);
+ //int private_AES_set_decrypt_key(const unsigned char *userKey, const int bits,AES_KEY *key);
+ //
+ //memcpy(key1,key,16);
+ //memcpy(key2,key+8,8);
+ AES_set_encrypt_key(key,128,&key_e);
+ AES_set_decrypt_key(key,128,&key_d);
+
+ //Auth1
+ UsbCommand c = {CMD_MIFARE_DES_AUTH1, {blockNo}};
+ SendCommand(&c);
+ UsbCommand resp;
+ if (WaitForResponseTimeout(CMD_ACK,&resp,1500)) {
+ uint8_t isOK = resp.arg[0] & 0xff;
+ cuid = resp.arg[1];
+ uint8_t * data= resp.d.asBytes;
+
+ if (isOK){
+ PrintAndLog("enc(nc)/b0:%s", sprint_hex(data+2,16));
+ memcpy(b0,data+2,16);
+ }
+ } else {
+ PrintAndLog("Command execute timeout");
+ }
+ //
+ // void AES_cbc_encrypt(const unsigned char *in, unsigned char *out,
+ //size_t length, const AES_KEY *key,
+ //unsigned char *ivec, const int enc);
+
+ //Do crypto magic
+ //DES_random_key(&nr);
+ //b1=dec(nr)
+ //r0=dec(b0)
+ //AES_cbc_encrypt(&nr,&b1,16,&key,0);
+ AES_cbc_encrypt(&b0,&r0,16,&key_d,iv,0);
+ //PrintAndLog("b1:%s",sprint_hex(b1, 8));
+ PrintAndLog("r0:%s",sprint_hex(r0, 16));
+ //r1=rol(r0)
+ memcpy(r1,r0,16);
+ rol(r1,8);
+ PrintAndLog("r1:%s",sprint_hex(r1, 16));
+ for(int i=0;i<16;i++){
+ b1[i]=(nr[i] ^ b0[i]);
+ b2[i]=(r1[i] ^ b1[i]);
+ }
+ PrintAndLog("nr:%s",sprint_hex(nr, 16));
+ AES_cbc_encrypt(&b1,&b1,16,&key_e,iv,1);
+ AES_cbc_encrypt(&b2,&b2,16,&key_e,iv,1);
+ PrintAndLog("b1:%s",sprint_hex(b1, 16));
+ PrintAndLog("b2:%s",sprint_hex(b2, 16));
+
+ //Auth2
+ UsbCommand d = {CMD_MIFARE_DES_AUTH2, {cuid}};
+ memcpy(reply,b1,16);
+ memcpy(reply+16,b2,16);
+ memcpy(d.d.asBytes,reply, 32);
+ SendCommand(&d);
+
+ UsbCommand respb;
+ if (WaitForResponseTimeout(CMD_ACK,&respb,1500)) {
+ uint8_t isOK = respb.arg[0] & 0xff;
+ uint8_t * data2= respb.d.asBytes;
+
+ if (isOK){
+ PrintAndLog("b3:%s", sprint_hex(data2+2, 16));
+ }
+
+ } else {
+ PrintAndLog("Command execute timeout");
+ }
+ return 1;
+}
+
+
+//------------------------------------
+// Menu Stuff
+//------------------------------------
+static command_t CommandTable[] =
+{
+ {"help", CmdHelp, 1,"This help"},
+ {"dbg", CmdHF14AMfDbg, 0,"Set default debug mode"},
+ {"des-auth",CmdHF14AMfDESAuth, 0,"Desfire Authentication"},
+ {"ev1-auth",CmdHF14AMfAESAuth, 0,"EV1 Authentication"},
+ {NULL, NULL, 0, NULL}
+};
+
+int CmdHFMFDesfire(const char *Cmd){
+ // flush
+ WaitForResponseTimeout(CMD_ACK,NULL,100);
+ CmdsParse(CommandTable, Cmd);
+ return 0;
+}
+
+int CmdHelp(const char *Cmd){
+ CmdsHelp(CommandTable);
+ return 0;
+}
--- /dev/null
+
+static int CmdHelp(const char *Cmd);
+int CmdHF14AMfDESAuth(const char *Cmd);
+int CmdHFMFDesfire(const char *Cmd);
+int CmdHelp(const char *Cmd);
\ No newline at end of file
#include "ui.h"
#include "proxmark3.h"
#include "cmdparser.h"
+#include "cmddata.h"
#include "cmdhw.h"
#include "cmdmain.h"
#include "cmddata.h"
//And ship it to device
UsbCommand c = {CMD_ACQUIRE_RAW_ADC_SAMPLES_125K};
SendCommand(&c);
- WaitForResponse(CMD_ACK,NULL);
+ //WaitForResponse(CMD_ACK,NULL);
+ if ( !WaitForResponseTimeout(CMD_ACK,NULL,2500) ) {
+ PrintAndLog("command execution time out");
+ return 1;
+ }
+
return 0;
}
static command_t CommandTable[] =
{
{"help", CmdHelp, 1, "This help"},
- {"cmdread", CmdLFCommandRead, 0, "<off period> <'0' period> <'1' period> <command> ['h'] -- Modulate LF reader field to send command before read (all periods in microseconds) (option 'h' for 134)"},
{"em4x", CmdLFEM4X, 1, "{ EM4X RFIDs... }"},
+ {"hid", CmdLFHID, 1, "{ HID RFIDs... }"},
+ {"hitag", CmdLFHitag, 1, "{ HITAG RFIDs... }"},
+ {"io", CmdLFIO, 1, "{ IOPROX RFIDs... }"},
+ {"pcf7931", CmdLFPCF7931, 1, "{ PCF7931 RFIDs... }"},
+ {"ti", CmdLFTI, 1, "{ TI RFIDs... }"},
+ {"t55xx", CmdLFT55XX, 1, "{ T55X7 RFIDs... }"},
+
{"config", CmdLFSetConfig, 0, "Set config for LF sampling, bit/sample, decimation, frequency"},
+
+ {"cmdread", CmdLFCommandRead, 0, "<off period> <'0' period> <'1' period> <command> ['h'] -- Modulate LF reader field to send command before read (all periods in microseconds) (option 'h' for 134)"},
{"flexdemod", CmdFlexdemod, 1, "Demodulate samples for FlexPass"},
- {"hid", CmdLFHID, 1, "{ HID RFIDs... }"},
- {"io", CmdLFIO, 1, "{ ioProx tags... }"},
{"indalademod", CmdIndalaDemod, 1, "['224'] -- Demodulate samples for Indala 64 bit UID (option '224' for 224 bit)"},
{"indalaclone", CmdIndalaClone, 0, "<UID> ['l']-- Clone Indala to T55x7 (tag must be in antenna)(UID in HEX)(option 'l' for 224 UID"},
{"read", CmdLFRead, 0, "Read 125/134 kHz LF ID-only tag. Do 'lf read h' for help"},
{"simbidir", CmdLFSimBidir, 0, "Simulate LF tag (with bidirectional data transmission between reader and tag)"},
//{"simman", CmdLFSimManchester, 0, "<Clock> <Bitstream> [GAP] Simulate arbitrary Manchester LF tag"},
{"snoop", CmdLFSnoop, 0, "['l'|'h'|<divisor>] [trigger threshold]-- Snoop LF (l:125khz, h:134khz)"},
- {"ti", CmdLFTI, 1, "{ TI RFIDs... }"},
- {"hitag", CmdLFHitag, 1, "{ Hitag tags and transponders... }"},
{"vchdemod", CmdVchDemod, 1, "['clone'] -- Demodulate samples for VeriChip"},
- {"t55xx", CmdLFT55XX, 1, "{ T55xx RFIDs... }"},
- {"pcf7931", CmdLFPCF7931, 1, "{PCF7931 RFIDs...}"},
{NULL, NULL, 0, NULL}
};
--- /dev/null
+//-----------------------------------------------------------------------------
+//
+// This code is licensed to you under the terms of the GNU GPL, version 2 or,
+// at your option, any later version. See the LICENSE.txt file for the text of
+// the license.
+//-----------------------------------------------------------------------------
+// Low frequency AWID26 commands
+//-----------------------------------------------------------------------------
+
+#include <stdio.h>
+#include <string.h>
+#include <inttypes.h>
+#include <stdbool.h>
+#include "proxmark3.h"
+#include "ui.h"
+//#include "graph.h"
+#include "cmdmain.h"
+#include "cmdparser.h"
+//#include "cmddata.h"
+#include "cmdlf.h"
+#include "cmdlfawid26.h"
+#include "util.h"
+//#include "data.h"
+
+
+static int CmdHelp(const char *Cmd);
+
+int CmdClone(const char *Cmd)
+{
+ char cmdp = param_getchar(Cmd, 0);
+
+ if (strlen(Cmd) < 1 || cmdp == 'h' || cmdp == 'H') {
+ PrintAndLog("Usage: lf awid26 clone <facility> <id>");
+ PrintAndLog(" [], ");
+ PrintAndLog("");
+ PrintAndLog(" sample: lf awid26 clone 15 2233");
+ return 0;
+ }
+
+ //sscanf(Cmd, "%d %d", &facilitycode, &cardno);
+
+ // char block0 = "00107060";
+ // char block1 = "00107060";
+ // char block2 = "00107060";
+ // char block3 = "00107060";
+
+ unsigned char buf[10] = {0x00};
+ unsigned char *resp = buf;
+
+
+ awid26_hex_to_uid(resp, "");
+ // PrintAndLog("Writing block %d with data %08X", Block, Data);
+ return 0;
+}
+
+
+// convert 96 bit AWID FSK data to 8 digit BCD UID
+bool awid26_hex_to_uid(unsigned char *response, char *awid26)
+{
+ //uint8_t i, tmp[96], tmp1[7];
+ //uint8_t tmp[96] = {0x00};
+ //int site;
+ //int id;
+
+ //if(!hextobinarray(tmp, awid26))
+ return false;
+
+ // // data is in blocks of 4 bits - every 4th bit is parity, except the first
+ // // block which is all zeros
+ // for(i= 0 ; i < 4 ; ++i)
+ // if(tmp[i] != 0x00)
+ // return false;
+
+ // // discard 1st block
+ // memcpy(tmp, tmp + 4, 92);
+
+ // // check and strip parity on the rest
+ // for(i= 1 ; i < 23 ; ++i)
+ // if(tmp[(i * 4) - 1] != GetParity(tmp + (i - 1) * 4, ODD, 3))
+ // return false;
+ // else
+ // memcpy((tmp + (i - 1) * 3), tmp + (i - 1) * 4, 3);
+
+ // // discard the rest of the header - 1 more 3 bit block
+ // memcpy(tmp, tmp + 3, 66);
+
+ // // next 8 bits is data length - should be 26: 0x1A
+ // binarraytohex(tmp1, tmp, 8);
+ // if(strcmp(tmp1, "1A") != 0)
+ // return false;
+ // memcpy(tmp, tmp +8, 58);
+
+ // // standard wiegand parity check - even for 1st 12 bits, odd for 2nd 12
+ // if(tmp[0] != GetParity(tmp + 1, EVEN, 12))
+ // return false;
+ // if(tmp[25] != GetParity(tmp + 13, ODD, 12))
+ // return false;
+
+ // // convert to hex, ignoring parity bits
+ // if(!binarraytohex(tmp1, tmp + 1, 24))
+ // return false;
+
+ // // convert hex to site/id
+ // sscanf(tmp1,"%2X%4X", &site, &id);
+
+ // // final output 8 byte BCD
+ // sprintf(response,"%03d%05d", site, id);
+
+ return true;
+}
+
+// convert null-terminated BCD UID (8 digits) to 96 bit awid26 encoded binary array
+bool bcd_to_awid26_bin(unsigned char *awid26, unsigned char *bcd)
+{
+ // char i, p, tmp1[8], tmp2[26];
+ // int tmpint;
+
+ // if(strlen(bcd) != 8)
+ // return false;
+
+ // // convert BCD site code to HEX
+ // sscanf(bcd, "%03d", &tmpint);
+ // sprintf(tmp2, "%02x", tmpint);
+ // memcpy(tmp1, tmp2, 2);
+
+ // // convert BCD ID to HEX
+ // sscanf(bcd + 3, "%05d", &tmpint);;
+ // sprintf(tmp2, "%04x", tmpint);
+
+ // // copy with trailing NULL
+ // memcpy(tmp1 + 2, tmp2, 5);
+
+ // // convert full HEX to binary, leaving room for parity prefix
+ // hextobinarray(tmp2 + 1, tmp1);
+
+ // wiegand_add_parity(tmp2, tmp2 + 1, 24);
+
+ // memset(awid26, '\x0', 96);
+
+ // // magic 18 bit awid26 header (we will overwrite the last two bits)
+ // hextobinarray(awid26, "011D8");
+
+ // // copy to target leaving space for parity bits
+ // for(i= 0, p= 18 ; i < 26 ; ++i, ++p)
+ // {
+ // // skip target bit if this is a parity location
+ // if(!((p + 1) % 4))
+ // p += 1;
+ // awid26[p]= tmp2[i];
+ // }
+
+ // // add parity bits
+ // for(i= 1 ; i < 24 ; ++i)
+ // awid26[((i + 1) * 4) - 1]= GetParity(&awid26[i * 4], ODD, 3);
+
+ return false;
+}
+
+// int CmdReadTrace(const char *Cmd)
+// {
+
+ // uint8_t bits[LF_BITSSTREAM_LEN] = {0x00};
+ // uint8_t * bitstream = bits;
+
+ // uint8_t si = 5;
+ // uint32_t bl0 = PackBits(si, 32, bitstream);
+ // uint32_t bl1 = PackBits(si+32, 32, bitstream);
+
+ // uint32_t acl = PackBits(si, 8, bitstream); si += 8;
+ // uint32_t mfc = PackBits(si, 8, bitstream); si += 8;
+ // uint32_t cid = PackBits(si, 5, bitstream); si += 5;
+ // uint32_t icr = PackBits(si, 3, bitstream); si += 3;
+ // uint32_t year = PackBits(si, 4, bitstream); si += 4;
+ // uint32_t quarter = PackBits(si, 2, bitstream); si += 2;
+ // uint32_t lotid = PackBits(si, 12, bitstream); si += 12;
+ // uint32_t wafer = PackBits(si, 5, bitstream); si += 5;
+ // uint32_t dw = PackBits(si, 15, bitstream);
+
+ // PrintAndLog("");
+ // PrintAndLog("-- T55xx Trace Information ----------------------------------");
+ // PrintAndLog("-------------------------------------------------------------");
+ // PrintAndLog(" ACL Allocation class (ISO/IEC 15963-1) : 0x%02X (%d)", acl, acl);
+ // PrintAndLog(" MFC Manufacturer ID (ISO/IEC 7816-6) : 0x%02X (%d)", mfc, mfc);
+ // PrintAndLog(" CID : 0x%02X (%d)", cid, cid);
+ // PrintAndLog(" ICR IC Revision : %d",icr );
+
+
+ // return 0;
+// }
+
+static command_t CommandTable[] =
+{
+ {"help", CmdHelp, 1, "This help"},
+ {"clone", CmdClone, 1, "<facility> <id> -- clone AWID26 to t55xx tag"},
+ {NULL, NULL, 0, NULL}
+};
+
+int CmdLFAWID26(const char *Cmd)
+{
+ CmdsParse(CommandTable, Cmd);
+ return 0;
+}
+
+int CmdHelp(const char *Cmd)
+{
+ CmdsHelp(CommandTable);
+ return 0;
+}
--- /dev/null
+//-----------------------------------------------------------------------------
+//
+// This code is licensed to you under the terms of the GNU GPL, version 2 or,
+// at your option, any later version. See the LICENSE.txt file for the text of
+// the license.
+//-----------------------------------------------------------------------------
+// Low frequency AWID 26 commands
+//-----------------------------------------------------------------------------
+
+#ifndef CMDLFAWID26_H__
+#define CMDLFAWID26_H__
+
+int CmdLFAWID26(const char *Cmd);
+
+int CmdClone(const char *Cmd);
+bool awid26_hex_to_uid(unsigned char *response, char *awid26);
+bool bcd_to_awid26_bin(unsigned char *awid26, unsigned char *bcd);
+#endif
int CmdReadWordPWD(const char *Cmd);
int CmdWriteWord(const char *Cmd);
int CmdWriteWordPWD(const char *Cmd);
+int MWRem4xReplay(const char* Cmd);
#endif
#include "proxmark3.h"\r
#include "ui.h"\r
#include "graph.h"\r
+#include "cmdmain.h"\r
#include "cmdparser.h"\r
#include "cmddata.h"\r
#include "cmdlf.h"\r
#include "cmdlft55xx.h"\r
+#include "util.h"\r
+#include "data.h"\r
+#include "lfdemod.h"\r
+#include "../common/crc.h"\r
+\r
+#define LF_TRACE_BUFF_SIZE 20000 // 32 x 32 x 10 (32 bit times numofblock (7), times clock skip..)\r
+#define LF_BITSSTREAM_LEN 1000 // more then 1000 bits shouldn't happend.. 8block * 4 bytes * 8bits = \r
+\r
+// 0 = FSK\r
+// 1 = ASK\r
+// 2 = PSK\r
+// 4 = NZR (direct)\r
+typedef struct {\r
+ uint8_t modulation;\r
+ bool inversed;\r
+ uint32_t block0;\r
+} t55xx_conf_block;\r
+\r
+// Default configuration: FSK, not inversed.\r
+t55xx_conf_block config = {0x00, FALSE, 0x00};\r
+\r
+ // FSK\r
+ // FSK inverted\r
+ //FSKrawDemod("", FALSE)\r
+ //FSKrawDemod("1", FALSE)\r
+\r
+ // ASK/MAN\r
+ // ASK/MAN inverted\r
+ //ASKmanDemod("", FALSE, FALSE)\r
+ \r
+ // NZR (autoclock, normal, maxerrors 1)\r
+ // NZR (autoclock, inverse, maxerrors 1)\r
+ //NRZrawDemod("0 0 1", FALSE) ) {\r
+ \r
+ // PSK (autoclock, normal, maxerrors 1)\r
+ // PSK (autoclock, inverse, maxerrors 1)\r
+ //PSKDemod("0 0 1", FALSE)\r
+\r
+int usage_t55xx_config(){\r
+ PrintAndLog("Usage: lf t55xx config [d <demodulation>] [i 0|1]");\r
+ PrintAndLog("Options: ");\r
+ PrintAndLog(" h This help");\r
+ PrintAndLog(" d <> Set demodulation FSK / ASK / PSK / NZR");\r
+ PrintAndLog(" i [0|1] Inverse data signal, Default: 0");\r
+ PrintAndLog("Examples:");\r
+ PrintAndLog(" lf t55xx config d FSK ");\r
+ PrintAndLog(" FSK demodulation");\r
+ PrintAndLog(" lf t55xx config d FSK i 1");\r
+ PrintAndLog(" FSK demodulation, inverse data");\r
+ PrintAndLog(" lf dump");\r
+ PrintAndLog(" Dumps all block from tag");\r
+ PrintAndLog(" lf trace");\r
+ PrintAndLog(" Read trace block and decode it");\r
+ PrintAndLog(" lf info");\r
+ PrintAndLog(" Read configuration and decode it");\r
+ return 0;\r
+}\r
+int usage_t55xx_read(){\r
+ PrintAndLog("Usage: lf t55xx read <block> <password>");\r
+ PrintAndLog(" <block>, block number to read. Between 0-7");\r
+ PrintAndLog(" <password>, OPTIONAL password (8 hex characters)");\r
+ PrintAndLog("");\r
+ PrintAndLog(" sample: lf t55xx read 0 = try reading data from block 0");\r
+ PrintAndLog(" : lf t55xx read 0 feedbeef = try reading data from block 0 using password");\r
+ PrintAndLog("");\r
+ return 0;\r
+}\r
+int usage_t55xx_write(){\r
+ PrintAndLog("Usage: lf t55xx wr <block> <data> [password]");\r
+ PrintAndLog(" <block>, block number to read. Between 0-7");\r
+ PrintAndLog(" <data>, 4 bytes of data to write (8 hex characters)");\r
+ PrintAndLog(" [password], OPTIONAL password 4bytes (8 hex characters)");\r
+ PrintAndLog("");\r
+ PrintAndLog(" sample: lf t55xx wd 3 11223344 = try writing data 11223344 to block 3");\r
+ PrintAndLog(" : lf t55xx wd 3 11223344 feedbeef = try writing data 11223344 to block 3 using password feedbeef");\r
+ PrintAndLog("");\r
+ return 0;\r
+}\r
+int usage_t55xx_trace() {\r
+ PrintAndLog("Usage: lf t55xx trace [graph buffer data]");\r
+ PrintAndLog(" [graph buffer data], if set, use Graphbuffer otherwise read data from tag.");\r
+ PrintAndLog("");\r
+ PrintAndLog(" sample: lf t55xx trace");\r
+ PrintAndLog(" : lf t55xx trace 1");\r
+ PrintAndLog("");\r
+ return 0;\r
+}\r
+int usage_t55xx_info() {\r
+ PrintAndLog("Usage: lf t55xx info [graph buffer data]");\r
+ PrintAndLog(" [graph buffer data], if set, use Graphbuffer otherwise read data from tag.");\r
+ PrintAndLog("");\r
+ PrintAndLog(" sample: lf t55xx info");\r
+ PrintAndLog(" : lf t55xx info 1");\r
+ PrintAndLog("");\r
+ return 0;\r
+}\r
+int usage_t55xx_dump(){\r
+ PrintAndLog("Usage: lf t55xx dump <password>");\r
+ PrintAndLog(" <password>, OPTIONAL password 4bytes (8 hex characters)");\r
+ PrintAndLog("");\r
+ PrintAndLog(" sample: lf t55xx dump");\r
+ PrintAndLog(" : lf t55xx dump feedbeef");\r
+ PrintAndLog("");\r
+ return 0;\r
+}\r
\r
static int CmdHelp(const char *Cmd);\r
\r
+int CmdT55xxSetConfig(const char *Cmd){\r
+ \r
+ uint8_t paramNum =0;\r
+ if(param_getchar(Cmd, paramNum) == 'h')\r
+ {\r
+ return usage_t55xx_config();\r
+ }\r
+\r
+ uint8_t buff[] = { 0x01, 0x01, 0x01, 0x01,\r
+ 0x01, 0x01, 0x01, 0x01,\r
+ 0x01, 0x40, 0x01, 0x01, 0x04 };\r
+ PrintAndLog("CRC-8: %x",CRC8Maxim(buff, 13));\r
+\r
+ //config = { 0, FALSE};\r
+ return 0;\r
+}\r
+\r
+// detect configuration?\r
\r
int CmdReadBlk(const char *Cmd)\r
{\r
- int Block = 8; //default to invalid block\r
- UsbCommand c;\r
+ int block = -1;\r
+ int password = 0xFFFFFFFF; //default to blank Block 7\r
\r
- sscanf(Cmd, "%d", &Block);\r
+ char cmdp = param_getchar(Cmd, 0);\r
+ if (cmdp == 'h' || cmdp == 'H')\r
+ return usage_t55xx_read();\r
\r
- if (Block > 7) {\r
- PrintAndLog("Block must be between 0 and 7");\r
- return 1;\r
- } \r
+ int res = sscanf(Cmd, "%d %x", &block, &password);\r
\r
- PrintAndLog("Reading block %d", Block);\r
+ if ( res < 1 || res > 2 ){\r
+ usage_t55xx_read();\r
+ return 1;\r
+ }\r
+ \r
+ if ((block < 0) | (block > 7)) {\r
+ PrintAndLog("Block must be between 0 and 7");\r
+ return 1;\r
+ } \r
\r
- c.cmd = CMD_T55XX_READ_BLOCK;\r
- c.d.asBytes[0] = 0x0; //Normal mode\r
- c.arg[0] = 0;\r
- c.arg[1] = Block;\r
- c.arg[2] = 0;\r
- SendCommand(&c);\r
- return 0;\r
-}\r
+ UsbCommand c = {CMD_T55XX_READ_BLOCK, {0, block, 0}};\r
+ c.d.asBytes[0] = 0x0; \r
\r
-int CmdReadBlkPWD(const char *Cmd)\r
-{\r
- int Block = 8; //default to invalid block\r
- int Password = 0xFFFFFFFF; //default to blank Block 7\r
- UsbCommand c;\r
+ //Password mode\r
+ if ( res == 2 ) {\r
+ c.arg[2] = password;\r
+ c.d.asBytes[0] = 0x1; \r
+ }\r
\r
- sscanf(Cmd, "%d %x", &Block, &Password);\r
+ SendCommand(&c);\r
+ if ( !WaitForResponseTimeout(CMD_ACK,NULL,2500) ) {\r
+ PrintAndLog("command execution time out");\r
+ return 2;\r
+ }\r
+ \r
+ uint8_t got[12000];\r
+ GetFromBigBuf(got,sizeof(got),0);\r
+ WaitForResponse(CMD_ACK,NULL);\r
\r
- if (Block > 7) {\r
- PrintAndLog("Block must be between 0 and 7");\r
- return 1;\r
- } \r
+ setGraphBuf(got, 12000);\r
\r
- PrintAndLog("Reading block %d with password %08X", Block, Password);\r
+ if (block == 0){\r
+ // try a detection.\r
+ \r
+ }\r
+ \r
+ if (CmdDetectClockRate("f")){ //wave is almost certainly FSK\r
+ //call FSK DEMOD\r
+ // FSK\r
+ if ( FSKrawDemod("", FALSE))\r
+ printT55xx("FSK");\r
+ // FSK inverted\r
+ if ( FSKrawDemod("1", FALSE)) \r
+ printT55xx("FSK inv");\r
+ } else {\r
+ // ASK/MAN (autoclock, normal, maxerrors 1)\r
+ if ( ASKmanDemod("0 0 1", FALSE, FALSE) )\r
+ printT55xx("ASK/MAN");\r
+ \r
+ // ASK/MAN (autoclock, inverted, maxerrors 1)\r
+ if ( ASKmanDemod("0 1 1", FALSE, FALSE) )\r
+ printT55xx("ASK/MAN Inv");\r
\r
- c.cmd = CMD_T55XX_READ_BLOCK;\r
- c.d.asBytes[0] = 0x1; //Password mode\r
- c.arg[0] = 0;\r
- c.arg[1] = Block;\r
- c.arg[2] = Password;\r
- SendCommand(&c);\r
- return 0;\r
+ // NZR (autoclock, normal, maxerrors 1)\r
+ if ( NRZrawDemod("0 0 1", FALSE) )\r
+ printT55xx("NZR");\r
+ // NZR (autoclock, inverted, maxerrors 1)\r
+ if ( NRZrawDemod("0 1 1", FALSE) )\r
+ printT55xx("NZR inv");\r
+ \r
+ // PSK (autoclock, normal, maxerrors 1)\r
+ if (!PSKDemod("0 0 1", FALSE))\r
+ printT55xx("PSK");\r
+\r
+ // PSK (autoclock, inverted, maxerrors 1)\r
+ if (!PSKDemod("0 1 1", FALSE))\r
+ printT55xx("PSK inv");\r
+ }\r
+ return 0;\r
}\r
\r
+void printT55xx(const char *demodStr){\r
+ \r
+ uint32_t blockData = 0;\r
+ uint8_t bits[MAX_GRAPH_TRACE_LEN] = {0x00};\r
+ \r
+ if ( !DemodBufferLen) \r
+ return;\r
+ \r
+ int i =0;\r
+ for (;i<DemodBufferLen;++i)\r
+ bits[i]=DemodBuffer[i];\r
+ \r
+ blockData = PackBits(1, 32, bits);\r
+ PrintAndLog("0x%08X %s [%s]", blockData, sprint_bin(bits+1,32), demodStr );\r
+}\r
+\r
+/*\r
+FSK1 / FSK1a\r
+size = fskdemod(dest, size, 32, 0, 8, 10); // fsk1 RF/32 \r
+size = fskdemod(dest, size, 32, 1, 8, 10); // fsk1a RF/32 \r
+\r
+FSK2 / FSK2a\r
+size = fskdemod(dest, size, 32, 0, 10, 8); // fsk2 RF/32 \r
+size = fskdemod(dest, size, 32, 1, 10, 8); // fsk2a RF/32 \r
+size = fskdemod(dest, size, 50, 1, 10, 8); // fsk2a RF/50 \r
+size = fskdemod(dest, size, 64, 1, 10, 8); // FSK2a RF/64 \r
+\r
+PSK1\r
+errCnt = pskRawDemod(bits, &bitlen, 32, 0);\r
+*/\r
int CmdWriteBlk(const char *Cmd)\r
{\r
- int Block = 8; //default to invalid block\r
- int Data = 0xFFFFFFFF; //default to blank Block \r
- UsbCommand c;\r
-\r
- sscanf(Cmd, "%x %d", &Data, &Block);\r
+ int block = 8; //default to invalid block\r
+ int data = 0xFFFFFFFF; //default to blank Block \r
+ int password = 0xFFFFFFFF; //default to blank Block 7\r
+ \r
+ char cmdp = param_getchar(Cmd, 0);\r
+ if (cmdp == 'h' || cmdp == 'H') {\r
+ usage_t55xx_write();\r
+ return 0;\r
+ }\r
+ \r
+ int res = sscanf(Cmd, "%d %x %x",&block, &data, &password);\r
+ \r
+ if ( res < 2 || res > 3) {\r
+ usage_t55xx_write();\r
+ return 1;\r
+ }\r
\r
- if (Block > 7) {\r
- PrintAndLog("Block must be between 0 and 7");\r
- return 1;\r
- } \r
+ if (block > 7) {\r
+ PrintAndLog("Block must be between 0 and 7");\r
+ return 1;\r
+ }\r
+ \r
+ UsbCommand c = {CMD_T55XX_WRITE_BLOCK, {data, block, 0}};\r
+ c.d.asBytes[0] = 0x0; \r
\r
- PrintAndLog("Writting block %d with data %08X", Block, Data);\r
+ PrintAndLog("Writing to T55x7");\r
+ PrintAndLog("block : %d", block);\r
+ PrintAndLog("data : 0x%08X", data);\r
\r
- c.cmd = CMD_T55XX_WRITE_BLOCK;\r
- c.d.asBytes[0] = 0x0; //Normal mode\r
- c.arg[0] = Data;\r
- c.arg[1] = Block;\r
- c.arg[2] = 0;\r
- SendCommand(&c);\r
- return 0;\r
+ //Password mode\r
+ if (res == 3) {\r
+ c.arg[2] = password;\r
+ c.d.asBytes[0] = 0x1; \r
+ PrintAndLog("pwd : 0x%08X", password);\r
+ }\r
+ SendCommand(&c);\r
+ return 0;\r
}\r
\r
-int CmdWriteBlkPWD(const char *Cmd)\r
+int CmdReadTrace(const char *Cmd)\r
{\r
- int Block = 8; //default to invalid block\r
- int Data = 0xFFFFFFFF; //default to blank Block \r
- int Password = 0xFFFFFFFF; //default to blank Block 7\r
- UsbCommand c;\r
-\r
- sscanf(Cmd, "%x %d %x", &Data, &Block, &Password);\r
-\r
- if (Block > 7) {\r
- PrintAndLog("Block must be between 0 and 7");\r
- return 1;\r
- } \r
-\r
- PrintAndLog("Writting block %d with data %08X and password %08X", Block, Data, Password);\r
-\r
- c.cmd = CMD_T55XX_WRITE_BLOCK;\r
- c.d.asBytes[0] = 0x1; //Password mode\r
- c.arg[0] = Data;\r
- c.arg[1] = Block;\r
- c.arg[2] = Password;\r
- SendCommand(&c);\r
+ uint8_t bits[MAX_GRAPH_TRACE_LEN] = {0x00};\r
+\r
+ char cmdp = param_getchar(Cmd, 0);\r
+ \r
+ if (strlen(Cmd) > 1 || cmdp == 'h' || cmdp == 'H') {\r
+ usage_t55xx_trace();\r
+ return 0;\r
+ }\r
+\r
+ if ( strlen(Cmd)==0){\r
+ \r
+ UsbCommand c = {CMD_T55XX_READ_TRACE, {0, 0, 0}};\r
+ SendCommand(&c);\r
+ if ( !WaitForResponseTimeout(CMD_ACK,NULL,2500) ) {\r
+ PrintAndLog("command execution time out");\r
+ return 1;\r
+ }\r
+ //darn\r
+ //CmdSamples("12000");\r
+ }\r
+ \r
+ size_t bitlen = getFromGraphBuf(bits);\r
+ if ( bitlen == 0 )\r
+ return 2;\r
+ \r
+ RepaintGraphWindow();\r
+\r
+ uint8_t si = 5;\r
+ uint32_t bl0 = PackBits(si, 32, bits);\r
+ uint32_t bl1 = PackBits(si+32, 32, bits);\r
+ \r
+ uint32_t acl = PackBits(si, 8, bits); si += 8;\r
+ uint32_t mfc = PackBits(si, 8, bits); si += 8;\r
+ uint32_t cid = PackBits(si, 5, bits); si += 5;\r
+ uint32_t icr = PackBits(si, 3, bits); si += 3;\r
+ uint32_t year = PackBits(si, 4, bits); si += 4;\r
+ uint32_t quarter = PackBits(si, 2, bits); si += 2;\r
+ uint32_t lotid = PackBits(si, 12, bits); si += 12;\r
+ uint32_t wafer = PackBits(si, 5, bits); si += 5;\r
+ uint32_t dw = PackBits(si, 15, bits); \r
+ \r
+ PrintAndLog("");\r
+ PrintAndLog("-- T55xx Trace Information ----------------------------------");\r
+ PrintAndLog("-------------------------------------------------------------");\r
+ PrintAndLog(" ACL Allocation class (ISO/IEC 15963-1) : 0x%02X (%d)", acl, acl);\r
+ PrintAndLog(" MFC Manufacturer ID (ISO/IEC 7816-6) : 0x%02X (%d)", mfc, mfc);\r
+ PrintAndLog(" CID : 0x%02X (%d)", cid, cid);\r
+ PrintAndLog(" ICR IC Revision : %d",icr );\r
+ PrintAndLog(" Manufactured");\r
+ PrintAndLog(" Year/Quarter : %d/%d",2000+year, quarter );\r
+ PrintAndLog(" Lot ID : %d", lotid );\r
+ PrintAndLog(" Wafer number : %d", wafer);\r
+ PrintAndLog(" Die Number : %d", dw);\r
+ PrintAndLog("-------------------------------------------------------------");\r
+ PrintAndLog(" Raw Data - Page 1");\r
+ PrintAndLog(" Block 0 : 0x%08X %s", bl0, sprint_bin(bits+5,32) );\r
+ PrintAndLog(" Block 0 : 0x%08X %s", bl1, sprint_bin(bits+37,32) );\r
+ PrintAndLog("-------------------------------------------------------------");\r
+ /*\r
+ TRACE - BLOCK O\r
+ Bits Definition HEX\r
+ 1-8 ACL Allocation class (ISO/IEC 15963-1) 0xE0 \r
+ 9-16 MFC Manufacturer ID (ISO/IEC 7816-6) 0x15 Atmel Corporation\r
+ 17-21 CID 0x1 = Atmel ATA5577M1 0x2 = Atmel ATA5577M2 \r
+ 22-24 ICR IC revision\r
+ 25-28 YEAR (BCD encoded) 9 (= 2009)\r
+ 29-30 QUARTER 1,2,3,4 \r
+ 31-32 LOT ID\r
+ \r
+ TRACE - BLOCK 1\r
+ 1-12 LOT ID \r
+ 13-17 Wafer number\r
+ 18-32 DW, die number sequential\r
+ */\r
+ \r
return 0;\r
}\r
\r
-int CmdReadTrace(const char *Cmd)\r
-{\r
+int CmdInfo(const char *Cmd){\r
+ /*\r
+ Page 0 Block 0 Configuration data.\r
+ Normal mode\r
+ Extended mode\r
+ */\r
+ char cmdp = param_getchar(Cmd, 0);\r
\r
- PrintAndLog("Reading traceability data");\r
+ if (cmdp == 'h' || cmdp == 'H') {\r
+ return usage_t55xx_info();\r
+ } else {\r
+ CmdReadBlk("0");\r
+ } \r
\r
- UsbCommand c = {CMD_T55XX_READ_TRACE, {0, 0, 0}};\r
- SendCommand(&c);\r
- return 0;\r
+ // config\r
+ \r
+ uint8_t bits[LF_BITSSTREAM_LEN] = {0x00};\r
+\r
+ uint8_t si = 1;\r
+ uint32_t bl0 = PackBits(si, 32, bits);\r
+ \r
+ uint32_t safer = PackBits(si, 4, bits); si += 4; \r
+ uint32_t resv = PackBits(si, 7, bits); si += 7;\r
+ uint32_t dbr = PackBits(si, 3, bits); si += 3;\r
+ uint32_t extend = PackBits(si, 1, bits); si += 1;\r
+ uint32_t datamodulation = PackBits(si, 5, bits); si += 5;\r
+ uint32_t pskcf = PackBits(si, 2, bits); si += 2;\r
+ uint32_t aor = PackBits(si, 1, bits); si += 1; \r
+ uint32_t otp = PackBits(si, 1, bits); si += 1; \r
+ uint32_t maxblk = PackBits(si, 3, bits); si += 3;\r
+ uint32_t pwd = PackBits(si, 1, bits); si += 1; \r
+ uint32_t sst = PackBits(si, 1, bits); si += 1; \r
+ uint32_t fw = PackBits(si, 1, bits); si += 1;\r
+ uint32_t inv = PackBits(si, 1, bits); si += 1; \r
+ uint32_t por = PackBits(si, 1, bits); si += 1;\r
+ \r
+ PrintAndLog("");\r
+ PrintAndLog("-- T55xx Configuration & Tag Information --------------------");\r
+ PrintAndLog("-------------------------------------------------------------");\r
+ PrintAndLog(" Safer key : %s", GetSaferStr(safer));\r
+ PrintAndLog(" reserved : %d", resv);\r
+ PrintAndLog(" Data bit rate : %s", GetBitRateStr(dbr));\r
+ PrintAndLog(" eXtended mode : %s", (extend) ? "Yes - Warning":"No");\r
+ PrintAndLog(" Modulation : %s", GetModulationStr(datamodulation) );\r
+ PrintAndLog(" PSK clock freq : %d", pskcf);\r
+ PrintAndLog(" AOR - Answer on Request : %s", (aor) ? "Yes":"No");\r
+ PrintAndLog(" OTP - One Time Pad : %s", (otp) ? "Yes - Warning":"No" );\r
+ PrintAndLog(" Max block : %d", maxblk);\r
+ PrintAndLog(" Password mode : %s", (pwd) ? "Yes":"No");\r
+ PrintAndLog(" Sequence Start Terminator : %s", (sst) ? "Yes":"No");\r
+ PrintAndLog(" Fast Write : %s", (fw) ? "Yes":"No");\r
+ PrintAndLog(" Inverse data : %s", (inv) ? "Yes":"No");\r
+ PrintAndLog(" POR-Delay : %s", (por) ? "Yes":"No");\r
+ PrintAndLog("-------------------------------------------------------------");\r
+ PrintAndLog(" Raw Data - Page 0");\r
+ PrintAndLog(" Block 0 : 0x%08X %s", bl0, sprint_bin(bits+5,32) );\r
+ PrintAndLog("-------------------------------------------------------------");\r
+ \r
+ return 0;\r
+}\r
+\r
+int CmdDump(const char *Cmd){\r
+\r
+ char s[20] = {0x00};\r
+ uint8_t pwd[4] = {0x00};\r
+\r
+ char cmdp = param_getchar(Cmd, 0);\r
+ if ( cmdp == 'h' || cmdp == 'H') {\r
+ usage_t55xx_dump();\r
+ return 0;\r
+ }\r
+\r
+ bool hasPwd = ( strlen(Cmd) > 0); \r
+ if ( hasPwd ){\r
+ if (param_gethex(Cmd, 0, pwd, 8)) {\r
+ PrintAndLog("password must include 8 HEX symbols");\r
+ return 1;\r
+ }\r
+ }\r
+ \r
+ for ( int i = 0; i <8; ++i){\r
+ memset(s,0,sizeof(s));\r
+ if ( hasPwd ) {\r
+ sprintf(s,"%d %02x%02x%02x%02x", i, pwd[0],pwd[1],pwd[2],pwd[3]);\r
+ } else {\r
+ sprintf(s,"%d", i);\r
+ }\r
+ CmdReadBlk(s);\r
+ }\r
+ return 0;\r
+}\r
+\r
+char * GetBitRateStr(uint32_t id){\r
+ static char buf[40];\r
+ char *retStr = buf;\r
+ switch (id){\r
+ case 0: \r
+ sprintf(retStr,"%d - RF/8",id);\r
+ break;\r
+ case 1:\r
+ sprintf(retStr,"%d - RF/16",id);\r
+ break;\r
+ case 2: \r
+ sprintf(retStr,"%d - RF/32",id);\r
+ break;\r
+ case 3:\r
+ sprintf(retStr,"%d - RF/40",id);\r
+ break;\r
+ case 4:\r
+ sprintf(retStr,"%d - RF/50",id);\r
+ break;\r
+ case 5:\r
+ sprintf(retStr,"%d - RF/64",id);\r
+ break;\r
+ case 6:\r
+ sprintf(retStr,"%d - RF/100",id);\r
+ break;\r
+ case 7:\r
+ sprintf(retStr,"%d - RF/128",id);\r
+ break;\r
+ default:\r
+ sprintf(retStr,"%d - (Unknown)",id);\r
+ break;\r
+ }\r
+\r
+ return buf;\r
+}\r
+\r
+char * GetSaferStr(uint32_t id){\r
+ static char buf[40];\r
+ char *retStr = buf;\r
+ \r
+ sprintf(retStr,"%d",id);\r
+ if (id == 6) {\r
+ sprintf(retStr,"%d - pasdwd",id);\r
+ }\r
+ if (id == 9 ){\r
+ sprintf(retStr,"%d - testmode ",id);\r
+ }\r
+ \r
+ return buf;\r
+}\r
+char * GetModulationStr( uint32_t id){\r
+ static char buf[40];\r
+ char *retStr = buf;\r
+ \r
+ switch (id){\r
+ case 0: \r
+ sprintf(retStr,"%d - DIRECT (ASK/NRZ)",id);\r
+ break;\r
+ case 1:\r
+ sprintf(retStr,"%d - PSK 1 phase change when input changes",id);\r
+ break;\r
+ case 2: \r
+ sprintf(retStr,"%d - PSK 2 phase change on bitclk if input high",id);\r
+ break;\r
+ case 3:\r
+ sprintf(retStr,"%d - PSK 3 phase change on rising edge of input",id);\r
+ break;\r
+ case 4:\r
+ sprintf(retStr,"%d - FSK 1 RF/8 RF/5",id);\r
+ break;\r
+ case 5:\r
+ sprintf(retStr,"%d - FSK 2 RF/8 RF/10",id);\r
+ break;\r
+ case 6:\r
+ sprintf(retStr,"%d - FSK 1a RF/5 RF/8",id);\r
+ break;\r
+ case 7:\r
+ sprintf(retStr,"%d - FSK 2a RF/10 RF/8",id);\r
+ break;\r
+ case 8:\r
+ sprintf(retStr,"%d - Manschester",id);\r
+ break;\r
+ case 16:\r
+ sprintf(retStr,"%d - Biphase",id);\r
+ break;\r
+ case 17:\r
+ sprintf(retStr,"%d - Reserved",id);\r
+ break;\r
+ default:\r
+ sprintf(retStr,"0x%02X (Unknown)",id);\r
+ break;\r
+ }\r
+ return buf;\r
+}\r
+\r
+uint32_t PackBits(uint8_t start, uint8_t len, uint8_t* bits){\r
+ \r
+ int i = start;\r
+ int j = len-1;\r
+ if (len > 32) {\r
+ return 0;\r
+ }\r
+ uint32_t tmp = 0;\r
+ for (; j >= 0; --j, ++i){\r
+ tmp |= bits[i] << j;\r
+ }\r
+ return tmp;\r
}\r
\r
static command_t CommandTable[] =\r
{\r
- {"help", CmdHelp, 1, "This help"},\r
- {"readblock", CmdReadBlk, 1, "<Block> -- Read T55xx block data (page 0)"},\r
- {"readblockPWD", CmdReadBlkPWD, 1, "<Block> <Password> -- Read T55xx block data in password mode(page 0)"},\r
- {"writeblock", CmdWriteBlk, 1, "<Data> <Block> -- Write T55xx block data (page 0)"},\r
- {"writeblockPWD", CmdWriteBlkPWD, 1, "<Data> <Block> <Password> -- Write T55xx block data in password mode(page 0)"},\r
- {"readtrace", CmdReadTrace, 1, "Read T55xx traceability data (page 1)"},\r
+ {"help", CmdHelp, 1, "This help"},\r
+ {"config", CmdT55xxSetConfig, 1, "Set T55XX config for modulation, inversed data"},\r
+ {"read", CmdReadBlk, 0, "<block> [password] -- Read T55xx block data (page 0) [optional password]"},\r
+ {"write", CmdWriteBlk, 0, "<block> <data> [password] -- Write T55xx block data (page 0) [optional password]"},\r
+ {"trace", CmdReadTrace, 0, "[1] Read T55xx traceability data (page 1/ blk 0-1)"},\r
+ {"info", CmdInfo, 0, "[1] Read T55xx configuration data (page 0/ blk 0)"},\r
+ {"dump", CmdDump, 0, "[password] Dump T55xx card block 0-7. [optional password]"},\r
{NULL, NULL, 0, NULL}\r
};\r
\r
#define CMDLFT55XX_H__\r
\r
int CmdLFT55XX(const char *Cmd);\r
-\r
+int CmdT55xxSetConfig(const char *Cmd);\r
int CmdReadBlk(const char *Cmd);\r
-int CmdReadBlkPWD(const char *Cmd);\r
int CmdWriteBlk(const char *Cmd);\r
-int CmdWriteBLkPWD(const char *Cmd);\r
int CmdReadTrace(const char *Cmd);\r
+int CmdInfo(const char *Cmd);\r
\r
+char * GetBitRateStr(uint32_t id);\r
+char * GetSaferStr(uint32_t id);\r
+char * GetModulationStr( uint32_t id);\r
+uint32_t PackBits(uint8_t start, uint8_t len, uint8_t* bitstream);\r
+void printT55xx(const char *demodStr);\r
#endif\r
#ifndef CMDMAIN_H__
#define CMDMAIN_H__
-#include "usb_cmd.h"
+#include "../include/usb_cmd.h"
#include "cmdparser.h"
void UsbCommandReceived(UsbCommand *UC);
void CommandReceived(char *Cmd);
#include "proxmark3.h"
#include "flash.h"
#include "uart.h"
-#include "usb_cmd.h"
+#include "../include/usb_cmd.h"
#ifdef _WIN32
# define unlink(x)
BitstreamIn input_32_zeroes = {zeroes_32,sizeof(zeroes_32)*8,0};
State initState = suc(k,init(k),&input);
output(k,initState,&input_32_zeroes,&out);
-}
+}
void doMAC(uint8_t *cc_nr_p, uint8_t *div_key_p, uint8_t mac[4])
{
memcpy(cc_nr,cc_nr_p,12);
memcpy(div_key,div_key_p,8);
-
+
reverse_arraybytes(cc_nr,12);
BitstreamIn bitstream = {cc_nr,12 * 8,0};
- uint8_t dest []= {0,0,0,0,0,0,0,0};
- BitstreamOut out = { dest, sizeof(dest)*8, 0 };
- MAC(div_key,bitstream, out);
- //The output MAC must also be reversed
- reverse_arraybytes(dest, sizeof(dest));
- memcpy(mac, dest, 4);
+ uint8_t dest []= {0,0,0,0,0,0,0,0};
+ BitstreamOut out = { dest, sizeof(dest)*8, 0 };
+ MAC(div_key,bitstream, out);
+ //The output MAC must also be reversed
+ reverse_arraybytes(dest, sizeof(dest));
+ memcpy(mac,dest,4);
//free(cc_nr);
return;
}
prnlog("[+] FAILED: MAC calculation failed:");
printarr(" Calculated_MAC", calculated_mac, 4);
printarr(" Correct_MAC ", correct_MAC, 4);
- return 1;
- }
+ return 1;
+}
return 0;
}
* @return 0 for ok, 1 for failz
*/
int saveFile(const char *preferredName, const char *suffix, const void* data, size_t datalen);
+/**
+ * @brief Utility function to save load binary data from a a file. This method takes a filename,
+ * Should only be used for fixed-size binary files
+ * @param fileName the name of the file
+ * @param data a buffer to place data in
+ * @param datalen the length of the data/data.
+ * @return
+ */
int fileExists(const char *filename);
#endif //ON_DEVICE
--- /dev/null
+#include <stdio.h>
+#include "cipherutils.h"
+#include <stdint.h>
+#include <stdbool.h>
+#include <string.h>
+#include <unistd.h>
+#include <ctype.h>
+#include "elite_crack.h"
+
+void calc_score(uint8_t* csn, uint8_t* k)
+{
+ uint8_t score =0 ;
+ uint8_t i;
+ uint8_t goodvals[16] = {0};
+ uint8_t uniq_vals[8] = {0};
+ memset(goodvals, 0x00, 16);
+ memset(uniq_vals, 0x00, 8);
+ uint8_t badval = 0;
+ int badscore =0;
+ for(i=0; i < 8 ; i++)
+ {
+ if(k[i] == 0x01) continue;
+ if(k[i] == 0x00) continue;
+ if(k[i] == 0x45) continue;
+ if(k[i] < 16){
+ goodvals[k[i]] = 1;
+ }
+// if(k[i] ==9 || k[i]==2){
+// goodvals[k[i]] = 1;
+// }
+
+ else if(k[i]>=16){
+ badscore++;
+ badval = k[i];
+ }
+ }
+ for(i =0; i < 16; i++)
+ {
+ if(goodvals[i])
+ {
+ uniq_vals[score] = i;
+ score +=1;
+ }
+ }
+ if(score >=2 && badscore < 2)
+ {
+ printf("CSN\t%02x%02x%02x%02x%02x%02x%02x%02x\t%02x %02x %02x %02x %02x %02x %02x %02x\t"
+ ,csn[0],csn[1],csn[2],csn[3],csn[4],csn[5],csn[6],csn[7]
+ ,k[0],k[1],k[2],k[3],k[4],k[5],k[6],k[7]
+ );
+ for(i =0 ; i < score; i++)
+ {
+ printf("%d,", uniq_vals[i]);
+ }
+ printf("\tbadscore: %d (%02x)", badscore, badval);
+ printf("\r\n");
+
+ }
+
+}
+
+void brute_hash1(){
+ uint8_t csn[8] = {0,0,0,0,0xf7,0xff,0x12,0xe0};
+ uint8_t k[8]= {0,0,0,0,0,0,0,0};
+ uint16_t a,b,c,d;
+ uint8_t testcsn[8] ={0x00,0x0d,0x0f,0xfd,0xf7,0xff,0x12,0xe0} ;
+ uint8_t testkey[8] ={0x05 ,0x01 ,0x00 ,0x10 ,0x45 ,0x08 ,0x45,0x56} ;
+ calc_score(testcsn,testkey);
+ printf("Brute forcing hashones\n");
+ //exit(1);
+ for(a=0;a < 256;a++)
+ {
+ //if(a > 0)printf("%d/256 done...\n", a);
+ for(b=0;b < 256 ; b++)
+ for(c=0;c < 256;c++)
+ for(d=0;d < 256;d++)
+ {
+ csn[0] = a;
+ csn[1] = b;
+ csn[2] = c;
+ csn[3] = d;
+ csn[4] = 0xf7;
+ csn[5] = 0xff;
+ csn[6] = 0x12;
+ csn[7] = 0xe0;
+ hash1(csn, k);
+ calc_score(csn,k);
+ }
+ }
+
+}
+
--- /dev/null
+#ifndef HASH1_BRUTE_H
+#define HASH1_BRUTE_H
+void brute_hash1();
+
+#endif // HASH1_BRUTE_H
local _reverse_lookup,k,v = {}
-for k, v in pairs(_commands) do
- _reverse_lookup[v] = k
-end
-_commands.tostring = function(command)
+ for k, v in pairs(_commands) do
+ _reverse_lookup[v] = k
+ end
+ _commands.tostring = function(command)
if(type(command) == 'number') then
return ("%s (%d)"):format(_reverse_lookup[command]or "ERROR UNDEFINED!", command)
end
local data = self.data
local cmd = self.cmd
local arg1, arg2, arg3 = self.arg1, self.arg2, self.arg3
-
return bin.pack("LLLLH",cmd, arg1, arg2, arg3,data);
end
return _commands
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,
+ SaveAsText = save_TEXT,
SaveAsBinary = save_BIN,
SaveAsText = save_TEXT,
}
--- /dev/null
+local md5 = {
+ _VERSION = "md5.lua 0.5.0",
+ _DESCRIPTION = "MD5 computation in Lua (5.1)",
+ _URL = "https://github.com/kikito/md5.lua",
+ _LICENSE = [[
+ MIT LICENSE
+
+ Copyright (c) 2013 Enrique GarcÃa Cota + Adam Baldwin + hanzao + Equi 4 Software
+
+ Permission is hereby granted, free of charge, to any person obtaining a
+ copy of this software and associated documentation files (the
+ "Software"), to deal in the Software without restriction, including
+ without limitation the rights to use, copy, modify, merge, publish,
+ distribute, sublicense, and/or sell copies of the Software, and to
+ permit persons to whom the Software is furnished to do so, subject to
+ the following conditions:
+
+ The above copyright notice and this permission notice shall be included
+ in all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+ CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ ]]
+}
+
+-- bit lib implementions
+
+local floor, abs, max = math.floor, math.abs, math.max
+local char, byte, format, rep, sub =
+ string.char, string.byte, string.format, string.rep, string.sub
+
+local function check_int(n)
+ -- checking not float
+ if(n - floor(n) > 0) then
+ error("trying to use bitwise operation on non-integer!")
+ end
+end
+
+local function tbl2number(tbl)
+ local n = #tbl
+
+ local rslt = 0
+ local power = 1
+ for i = 1, n do
+ rslt = rslt + tbl[i]*power
+ power = power*2
+ end
+
+ return rslt
+end
+
+local function expand(tbl_m, tbl_n)
+ local big = {}
+ local small = {}
+ if(#tbl_m > #tbl_n) then
+ big = tbl_m
+ small = tbl_n
+ else
+ big = tbl_n
+ small = tbl_m
+ end
+ -- expand small
+ for i = #small + 1, #big do
+ small[i] = 0
+ end
+
+end
+
+local to_bits -- needs to be declared before bit_not
+
+local function bit_not(n)
+ local tbl = to_bits(n)
+ local size = max(#tbl, 32)
+ for i = 1, size do
+ if(tbl[i] == 1) then
+ tbl[i] = 0
+ else
+ tbl[i] = 1
+ end
+ end
+ return tbl2number(tbl)
+end
+
+-- defined as local above
+to_bits = function (n)
+ check_int(n)
+ if(n < 0) then
+ -- negative
+ return to_bits(bit_not(abs(n)) + 1)
+ end
+ -- to bits table
+ local tbl = {}
+ local cnt = 1
+ while (n > 0) do
+ local last = math.fmod(n,2)
+ if(last == 1) then
+ tbl[cnt] = 1
+ else
+ tbl[cnt] = 0
+ end
+ n = (n-last)/2
+ cnt = cnt + 1
+ end
+
+ return tbl
+end
+
+local function bit_or(m, n)
+ local tbl_m = to_bits(m)
+ local tbl_n = to_bits(n)
+ expand(tbl_m, tbl_n)
+
+ local tbl = {}
+ local rslt = max(#tbl_m, #tbl_n)
+ for i = 1, rslt do
+ if(tbl_m[i]== 0 and tbl_n[i] == 0) then
+ tbl[i] = 0
+ else
+ tbl[i] = 1
+ end
+ end
+
+ return tbl2number(tbl)
+end
+
+local function bit_and(m, n)
+ local tbl_m = to_bits(m)
+ local tbl_n = to_bits(n)
+ expand(tbl_m, tbl_n)
+
+ local tbl = {}
+ local rslt = max(#tbl_m, #tbl_n)
+ for i = 1, rslt do
+ if(tbl_m[i]== 0 or tbl_n[i] == 0) then
+ tbl[i] = 0
+ else
+ tbl[i] = 1
+ end
+ end
+
+ return tbl2number(tbl)
+end
+
+local function bit_xor(m, n)
+ local tbl_m = to_bits(m)
+ local tbl_n = to_bits(n)
+ expand(tbl_m, tbl_n)
+
+ local tbl = {}
+ local rslt = max(#tbl_m, #tbl_n)
+ for i = 1, rslt do
+ if(tbl_m[i] ~= tbl_n[i]) then
+ tbl[i] = 1
+ else
+ tbl[i] = 0
+ end
+ end
+
+ return tbl2number(tbl)
+end
+
+local function bit_rshift(n, bits)
+ check_int(n)
+
+ local high_bit = 0
+ if(n < 0) then
+ -- negative
+ n = bit_not(abs(n)) + 1
+ high_bit = 2147483648 -- 0x80000000
+ end
+
+ for i=1, bits do
+ n = n/2
+ n = bit_or(floor(n), high_bit)
+ end
+ return floor(n)
+end
+
+local function bit_lshift(n, bits)
+ check_int(n)
+
+ if(n < 0) then
+ -- negative
+ n = bit_not(abs(n)) + 1
+ end
+
+ for i=1, bits do
+ n = n*2
+ end
+ return bit_and(n, 4294967295) -- 0xFFFFFFFF
+end
+
+-- convert little-endian 32-bit int to a 4-char string
+local function lei2str(i)
+ local f=function (s) return char( bit_and( bit_rshift(i, s), 255)) end
+ return f(0)..f(8)..f(16)..f(24)
+end
+
+-- convert raw string to big-endian int
+local function str2bei(s)
+ local v=0
+ for i=1, #s do
+ v = v * 256 + byte(s, i)
+ end
+ return v
+end
+
+-- convert raw string to little-endian int
+local function str2lei(s)
+ local v=0
+ for i = #s,1,-1 do
+ v = v*256 + byte(s, i)
+ end
+ return v
+end
+
+-- cut up a string in little-endian ints of given size
+local function cut_le_str(s,...)
+ local o, r = 1, {}
+ local args = {...}
+ for i=1, #args do
+ table.insert(r, str2lei(sub(s, o, o + args[i] - 1)))
+ o = o + args[i]
+ end
+ return r
+end
+
+local swap = function (w) return str2bei(lei2str(w)) end
+
+local function hex2binaryaux(hexval)
+ return char(tonumber(hexval, 16))
+end
+
+local function hex2binary(hex)
+ local result, _ = hex:gsub('..', hex2binaryaux)
+ return result
+end
+
+-- An MD5 mplementation in Lua, requires bitlib (hacked to use LuaBit from above, ugh)
+-- 10/02/2001 jcw@equi4.com
+
+local FF = 0xffffffff
+local CONSTS = {
+ 0xd76aa478, 0xe8c7b756, 0x242070db, 0xc1bdceee,
+ 0xf57c0faf, 0x4787c62a, 0xa8304613, 0xfd469501,
+ 0x698098d8, 0x8b44f7af, 0xffff5bb1, 0x895cd7be,
+ 0x6b901122, 0xfd987193, 0xa679438e, 0x49b40821,
+ 0xf61e2562, 0xc040b340, 0x265e5a51, 0xe9b6c7aa,
+ 0xd62f105d, 0x02441453, 0xd8a1e681, 0xe7d3fbc8,
+ 0x21e1cde6, 0xc33707d6, 0xf4d50d87, 0x455a14ed,
+ 0xa9e3e905, 0xfcefa3f8, 0x676f02d9, 0x8d2a4c8a,
+ 0xfffa3942, 0x8771f681, 0x6d9d6122, 0xfde5380c,
+ 0xa4beea44, 0x4bdecfa9, 0xf6bb4b60, 0xbebfbc70,
+ 0x289b7ec6, 0xeaa127fa, 0xd4ef3085, 0x04881d05,
+ 0xd9d4d039, 0xe6db99e5, 0x1fa27cf8, 0xc4ac5665,
+ 0xf4292244, 0x432aff97, 0xab9423a7, 0xfc93a039,
+ 0x655b59c3, 0x8f0ccc92, 0xffeff47d, 0x85845dd1,
+ 0x6fa87e4f, 0xfe2ce6e0, 0xa3014314, 0x4e0811a1,
+ 0xf7537e82, 0xbd3af235, 0x2ad7d2bb, 0xeb86d391,
+ 0x67452301, 0xefcdab89, 0x98badcfe, 0x10325476
+}
+
+local f=function (x,y,z) return bit_or(bit_and(x,y),bit_and(-x-1,z)) end
+local g=function (x,y,z) return bit_or(bit_and(x,z),bit_and(y,-z-1)) end
+local h=function (x,y,z) return bit_xor(x,bit_xor(y,z)) end
+local i=function (x,y,z) return bit_xor(y,bit_or(x,-z-1)) end
+local z=function (f,a,b,c,d,x,s,ac)
+ a=bit_and(a+f(b,c,d)+x+ac,FF)
+ -- be *very* careful that left shift does not cause rounding!
+ return bit_or(bit_lshift(bit_and(a,bit_rshift(FF,s)),s),bit_rshift(a,32-s))+b
+end
+
+local function transform(A,B,C,D,X)
+ local a,b,c,d=A,B,C,D
+ local t=CONSTS
+
+ a=z(f,a,b,c,d,X[ 0], 7,t[ 1])
+ d=z(f,d,a,b,c,X[ 1],12,t[ 2])
+ c=z(f,c,d,a,b,X[ 2],17,t[ 3])
+ b=z(f,b,c,d,a,X[ 3],22,t[ 4])
+ a=z(f,a,b,c,d,X[ 4], 7,t[ 5])
+ d=z(f,d,a,b,c,X[ 5],12,t[ 6])
+ c=z(f,c,d,a,b,X[ 6],17,t[ 7])
+ b=z(f,b,c,d,a,X[ 7],22,t[ 8])
+ a=z(f,a,b,c,d,X[ 8], 7,t[ 9])
+ d=z(f,d,a,b,c,X[ 9],12,t[10])
+ c=z(f,c,d,a,b,X[10],17,t[11])
+ b=z(f,b,c,d,a,X[11],22,t[12])
+ a=z(f,a,b,c,d,X[12], 7,t[13])
+ d=z(f,d,a,b,c,X[13],12,t[14])
+ c=z(f,c,d,a,b,X[14],17,t[15])
+ b=z(f,b,c,d,a,X[15],22,t[16])
+
+ a=z(g,a,b,c,d,X[ 1], 5,t[17])
+ d=z(g,d,a,b,c,X[ 6], 9,t[18])
+ c=z(g,c,d,a,b,X[11],14,t[19])
+ b=z(g,b,c,d,a,X[ 0],20,t[20])
+ a=z(g,a,b,c,d,X[ 5], 5,t[21])
+ d=z(g,d,a,b,c,X[10], 9,t[22])
+ c=z(g,c,d,a,b,X[15],14,t[23])
+ b=z(g,b,c,d,a,X[ 4],20,t[24])
+ a=z(g,a,b,c,d,X[ 9], 5,t[25])
+ d=z(g,d,a,b,c,X[14], 9,t[26])
+ c=z(g,c,d,a,b,X[ 3],14,t[27])
+ b=z(g,b,c,d,a,X[ 8],20,t[28])
+ a=z(g,a,b,c,d,X[13], 5,t[29])
+ d=z(g,d,a,b,c,X[ 2], 9,t[30])
+ c=z(g,c,d,a,b,X[ 7],14,t[31])
+ b=z(g,b,c,d,a,X[12],20,t[32])
+
+ a=z(h,a,b,c,d,X[ 5], 4,t[33])
+ d=z(h,d,a,b,c,X[ 8],11,t[34])
+ c=z(h,c,d,a,b,X[11],16,t[35])
+ b=z(h,b,c,d,a,X[14],23,t[36])
+ a=z(h,a,b,c,d,X[ 1], 4,t[37])
+ d=z(h,d,a,b,c,X[ 4],11,t[38])
+ c=z(h,c,d,a,b,X[ 7],16,t[39])
+ b=z(h,b,c,d,a,X[10],23,t[40])
+ a=z(h,a,b,c,d,X[13], 4,t[41])
+ d=z(h,d,a,b,c,X[ 0],11,t[42])
+ c=z(h,c,d,a,b,X[ 3],16,t[43])
+ b=z(h,b,c,d,a,X[ 6],23,t[44])
+ a=z(h,a,b,c,d,X[ 9], 4,t[45])
+ d=z(h,d,a,b,c,X[12],11,t[46])
+ c=z(h,c,d,a,b,X[15],16,t[47])
+ b=z(h,b,c,d,a,X[ 2],23,t[48])
+
+ a=z(i,a,b,c,d,X[ 0], 6,t[49])
+ d=z(i,d,a,b,c,X[ 7],10,t[50])
+ c=z(i,c,d,a,b,X[14],15,t[51])
+ b=z(i,b,c,d,a,X[ 5],21,t[52])
+ a=z(i,a,b,c,d,X[12], 6,t[53])
+ d=z(i,d,a,b,c,X[ 3],10,t[54])
+ c=z(i,c,d,a,b,X[10],15,t[55])
+ b=z(i,b,c,d,a,X[ 1],21,t[56])
+ a=z(i,a,b,c,d,X[ 8], 6,t[57])
+ d=z(i,d,a,b,c,X[15],10,t[58])
+ c=z(i,c,d,a,b,X[ 6],15,t[59])
+ b=z(i,b,c,d,a,X[13],21,t[60])
+ a=z(i,a,b,c,d,X[ 4], 6,t[61])
+ d=z(i,d,a,b,c,X[11],10,t[62])
+ c=z(i,c,d,a,b,X[ 2],15,t[63])
+ b=z(i,b,c,d,a,X[ 9],21,t[64])
+
+ return A+a,B+b,C+c,D+d
+end
+
+----------------------------------------------------------------
+
+function md5.sumhexa(s)
+ local msgLen = #s
+ local padLen = 56 - msgLen % 64
+
+ if msgLen % 64 > 56 then padLen = padLen + 64 end
+
+ if padLen == 0 then padLen = 64 end
+
+ s = s .. char(128) .. rep(char(0),padLen-1) .. lei2str(8*msgLen) .. lei2str(0)
+
+ assert(#s % 64 == 0)
+
+ local t = CONSTS
+ local a,b,c,d = t[65],t[66],t[67],t[68]
+
+ for i=1,#s,64 do
+ local X = cut_le_str(sub(s,i,i+63),4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4)
+ assert(#X == 16)
+ X[0] = table.remove(X,1) -- zero based!
+ a,b,c,d = transform(a,b,c,d,X)
+ end
+
+ return format("%08x%08x%08x%08x",swap(a),swap(b),swap(c),swap(d))
+end
+
+function md5.sum(s)
+ return hex2binary(md5.sumhexa(s))
+end
+
+return md5
'644672bd4afe',
'b5ff67cba951',
- }
+}
---
-- The keys above have just been pasted in, for completeness sake. They contain duplicates.
--- /dev/null
+--[[
+ This is an experimental lib.
+--]]
+local utils = require('utils')
+
+-- LOOKUP Tables
+local perm = {}
+perm [1]= { 0x0, 0x1, 0x3, 0x2, 0x7, 0x6, 0x4, 0x5, 0xF, 0xE, 0xC, 0xD, 0x8, 0x9, 0xB, 0xA }
+perm [2]= { 0x1, 0x0, 0x2, 0x3, 0x6, 0x7, 0x5, 0x4, 0xE, 0xF, 0xD, 0xC, 0x9, 0x8, 0xA, 0xB }
+perm [3]= { 0x2, 0x3, 0x1, 0x0, 0x5, 0x4, 0x6, 0x7, 0xD, 0xC, 0xE, 0xF, 0xA, 0xB, 0x9, 0x8 }
+perm [4]= { 0x3, 0x2, 0x0, 0x1, 0x4, 0x5, 0x7, 0x6, 0xC, 0xD, 0xF, 0xE, 0xB, 0xA, 0x8, 0x9 }
+perm [5]= { 0x4, 0x5, 0x7, 0x6, 0x3, 0x2, 0x0, 0x1, 0xB, 0xA, 0x8, 0x9, 0xC, 0xD, 0xF, 0xE }
+perm [6]= { 0x5, 0x4, 0x6, 0x7, 0x2, 0x3, 0x1, 0x0, 0xA, 0xB, 0x9, 0x8, 0xD, 0xC, 0xE, 0xF }
+perm [7]= { 0x6, 0x7, 0x5, 0x4, 0x1, 0x0, 0x2, 0x3, 0x9, 0x8, 0xA, 0xB, 0xE, 0xF, 0xD, 0xC }
+perm [8]= { 0x7, 0x6, 0x4, 0x5, 0x0, 0x1, 0x3, 0x2, 0x8, 0x9, 0xB, 0xA, 0xF, 0xE, 0xC, 0xD }
+perm [9]= { 0x8, 0x9, 0xB, 0xA, 0xF, 0xE, 0xC, 0xD, 0x7, 0x6, 0x4, 0x5, 0x0, 0x1, 0x3, 0x2 }
+perm [10]= { 0x9, 0x8, 0xA, 0xB, 0xE, 0xF, 0xD, 0xC, 0x6, 0x7, 0x5, 0x4, 0x1, 0x0, 0x2, 0x3 }
+perm [11]= { 0xA, 0xB, 0x9, 0x8, 0xD, 0xC, 0xE, 0xF, 0x5, 0x4, 0x6, 0x7, 0x2, 0x3, 0x1, 0x0 }
+perm [12]= { 0xB, 0xA, 0x8, 0x9, 0xC, 0xD, 0xF, 0xE, 0x4, 0x5, 0x7, 0x6, 0x3, 0x2, 0x0, 0x1 }
+perm [13]= { 0xC, 0xD, 0xF, 0xE, 0xB, 0xA, 0x8, 0x9, 0x3, 0x2, 0x0, 0x1, 0x4, 0x5, 0x7, 0x6 }
+perm [14]= { 0xD, 0xC, 0xE, 0xF, 0xA, 0xB, 0x9, 0x8, 0x2, 0x3, 0x1, 0x0, 0x5, 0x4, 0x6, 0x7 }
+perm [15]= { 0xE, 0xF, 0xD, 0xC, 0x9, 0x8, 0xA, 0xB, 0x1, 0x0, 0x2, 0x3, 0x6, 0x7, 0x5, 0x4 }
+perm [16]= { 0xF, 0xE, 0xC, 0xD, 0x8, 0x9, 0xB, 0xA, 0x0, 0x1, 0x3, 0x2, 0x7, 0x6, 0x4, 0x5 }
+
+local shifts = {}
+shifts[1]= { 0x4, 0x5, 0x7, 0x6, 0x3, 0x2, 0x0, 0x1, 0xB, 0xA, 0x8, 0x9, 0xC, 0xD, 0xF, 0xE }
+shifts[2]= { 0x4, 0xB, 0xB, 0x4, 0xB, 0x4, 0x4, 0xB, 0xA, 0x5, 0x5, 0xA, 0x5, 0xA, 0xA, 0x5 }
+shifts[3]= { 0xB, 0x6, 0x0, 0xD, 0xD, 0x0, 0x6, 0xB, 0x6, 0xB, 0xD, 0x0, 0x0, 0xD, 0xB, 0x6 }
+shifts[4]= { 0xE, 0x5, 0x9, 0x2, 0x0, 0xB, 0x7, 0xC, 0x3, 0x8, 0x4, 0xF, 0xD, 0x6, 0xA, 0x1 }
+shifts[5]= { 0x4, 0xE, 0x1, 0xB, 0xF, 0x5, 0xA, 0x0, 0x3, 0x9, 0x6, 0xC, 0x8, 0x2, 0xD, 0x7 }
+shifts[6]= { 0xA, 0x4, 0x7, 0x9, 0x0, 0xE, 0xD, 0x3, 0xE, 0x0, 0x3, 0xD, 0x4, 0xA, 0x9, 0x7 }
+shifts[7]= { 0xE, 0x6, 0xE, 0x6, 0xF, 0x7, 0xF, 0x7, 0xD, 0x5, 0xD, 0x5, 0xC, 0x4, 0xC, 0x4 }
+shifts[8]= { 0x7, 0x1, 0xB, 0xD, 0xE, 0x8, 0x2, 0x4, 0x4, 0x2, 0x8, 0xE, 0xD, 0xB, 0x1, 0x7 }
+shifts[9]= { 0xD, 0xB, 0x0, 0x6, 0x6, 0x0, 0xB, 0xD, 0xA, 0xC, 0x7, 0x1, 0x1, 0x7, 0xC, 0xA }
+shifts[10]= { 0xe, 0x1, 0x1, 0xe, 0x1, 0xe, 0xe, 0x1, 0x1, 0xe, 0xe, 0x1, 0xe, 0x1, 0x1, 0xe }
+
+local function ApplyPermutationAndShifts( pos, value, nibble)
+ local el2bytes = shifts[pos]
+ local el2 = el2bytes[nibble+1] --one indexed
+ local shiftInit = el2bytes[1]
+ local permrow = perm[shiftInit+1]
+ local j = 1
+ for i = 1,16 do
+ if permrow[i] == el2 then
+ j = i
+ break
+ end
+ end
+ local rsbytes = perm[value+1]
+ local rs = rsbytes[j]
+ return rs
+end
+
+local function GetOne( uid, block )
+
+ if uid == nil then return nil, 'empty uid string' end
+ if #uid == 0 then return nil, 'empty uid string' end
+ if #uid ~= 8 then return nil, 'uid wrong length. Should be 4 hex bytes' end
+ if type(block) ~= 'number' then return nil, 'block is not number' end
+ if block > 16 or block < 0 then return nil, 'block is out-of-range' end
+
+ local s = ('%s%02X'):format(uid,block)
+ local nibble1 = tonumber(s:sub(1,1),16) + 1
+
+ local permuted = ''
+ for i = 1, #s do
+ local el_row = shifts[i]
+ local el_value = el_row[nibble1]
+ j = 1
+ while j <= i do
+ if i-j > 0 then
+ local nibble = tonumber(s:sub(j+1,j+1),16)
+ el_value = ApplyPermutationAndShifts(i-j, el_value, nibble)
+ end
+ j = j+1
+ end
+ permuted =('%s%X'):format(permuted,el_value)
+ end
+
+ permuted = 'C2'..permuted
+ local crc64numStr = utils.Crc64(permuted)
+ local keybytes = utils.ConvertAsciiToBytes(crc64numStr, true)
+ local key = utils.ConvertBytesToHex(keybytes)
+ return key:sub(1,12)
+end
+
+local PreCalc =
+{
+ GetAll = function(id)
+ if id == nil then return nil, 'empty string' end
+ if #id == 0 then return nil, 'empty string' end
+ if #id ~= 8 then return nil, 'wrong length. Should be 4 hex bytes' end
+
+ local list = '4b0b20107ccb'
+ for i = 1,15 do
+ local key, err = GetOne(id,i)
+ if not key then return oops(err) end
+ list = list..key
+ end
+ return list
+ end,
+}
+return PreCalc
\ No newline at end of file
return outResults\r
end,\r
\r
- ------------ CRC-16 ccitt checksums\r
\r
+ ------------ CRC-16 ccitt checksums\r
-- Takes a hex string and calculates a crc16\r
Crc16 = function(s)\r
if s == nil then return nil end\r
end\r
return nil\r
end,\r
-\r
+ \r
+ ------------ CRC-64 ecma checksums\r
+ -- Takes a hex string and calculates a crc64 ecma\r
+ Crc64 = function(s)\r
+ if s == nil then return nil end\r
+ if #s == 0 then return nil end\r
+ if type(s) == 'string' then\r
+ local utils = require('utils')\r
+ local asc = utils.ConvertHexToAscii(s)\r
+ local hash = core.crc64(asc)\r
+ return hash\r
+ end\r
+ return nil\r
+ end,\r
+ \r
+ \r
-- input parameter is a string\r
-- Swaps the endianess and returns a number, \r
-- IE: 'cd7a' -> '7acd' -> 0x7acd\r
while IN>0 do\r
I=I+1\r
IN , D = math.floor(IN/B), math.modf(IN,B)+1\r
- OUT=string.sub(K,D,D)..OUT\r
+ OUT = string.sub(K,D,D)..OUT\r
end\r
return OUT\r
end,\r
end\r
local s={}\r
for i = 1, #(bytes) do\r
- s[i] = string.format("%02X",bytes[i]) \r
+ s[i] = string.format("%02X",bytes[i]) \r
end\r
return table.concat(s)\r
end, \r
end\r
return t\r
end,\r
- ConvertAsciiToBytes = function(s)\r
- local t={}\r
+ ConvertAsciiToBytes = function(s, reverse)\r
+ local t = {}\r
if s == nil then return t end\r
if #s == 0 then return t end\r
\r
for k in s:gmatch"(.)" do\r
table.insert(t, string.byte(k))\r
end\r
- return t\r
+ \r
+ if not reverse then\r
+ return t\r
+ end\r
+ \r
+ local rev = {}\r
+ if reverse then\r
+ for i = #t, 1,-1 do\r
+ table.insert(rev, t[i] )\r
+ end\r
+ end\r
+ return rev\r
end,\r
+ \r
ConvertHexToAscii = function(s)\r
local t={}\r
if s == nil then return t end\r
return table.concat(t) \r
end,\r
\r
+ Chars2num = function(s)\r
+ return (s:byte(1)*16777216)+(s:byte(2)*65536)+(s:byte(3)*256)+(s:byte(4))\r
+ end,\r
+ \r
+ -- use length of string to determine 8,16,32,64 bits\r
+ bytes_to_int = function(str,endian,signed) \r
+ local t={str:byte(1,-1)}\r
+ if endian=="big" then --reverse bytes\r
+ local tt={}\r
+ for k=1,#t do\r
+ tt[#t-k+1]=t[k]\r
+ end\r
+ t=tt\r
+ end\r
+ local n=0\r
+ for k=1,#t do\r
+ n=n+t[k]*2^((k-1)*8)\r
+ end\r
+ if signed then\r
+ n = (n > 2^(#t*8-1) -1) and (n - 2^(#t*8)) or n -- if last bit set, negative.\r
+ end\r
+ return n\r
+ end,\r
+ \r
-- function convertStringToBytes(str)\r
-- local bytes = {}\r
-- local strLength = string.len(str)\r
uint16_t i, len;\r
uint32_t uid;\r
UsbCommand resp;\r
-\r
StateList_t statelists[2];\r
struct Crypto1State *p1, *p2, *p3, *p4;\r
\r
UsbCommand c = {CMD_MIFARE_EML_MEMGET, {blockNum, blocksCount, 0}};\r
SendCommand(&c);\r
\r
- UsbCommand resp;\r
+ UsbCommand resp;\r
if (!WaitForResponseTimeout(CMD_ACK,&resp,1500)) return 1;\r
memcpy(data, resp.d.asBytes, blocksCount * 16);\r
return 0;\r
memcpy(c.d.asBytes, data, 16); \r
SendCommand(&c);\r
\r
- UsbCommand resp;\r
+ UsbCommand resp;\r
if (WaitForResponseTimeout(CMD_ACK,&resp,1500)) {\r
isOK = resp.arg[0] & 0xff;\r
if (uid != NULL) \r
\r
memset(buf, 0, sizeof(buf));\r
if (fgets(buf, sizeof(buf), f) == NULL) {\r
- PrintAndLog("File reading error.");\r
+ PrintAndLog("File reading error.");\r
fclose(f);\r
return 2;\r
- }\r
+ }\r
\r
if (strlen(buf) < 32){\r
if (feof(f)) break;\r
}\r
\r
// AUTHENTICATION\r
- if ((len ==4) && ((data[0] == 0x60) || (data[0] == 0x61))) {\r
+ if ((len == 4) && ((data[0] == 0x60) || (data[0] == 0x61))) {\r
traceState = TRACE_AUTH1;\r
traceCurBlock = data[1];\r
traceCurKey = data[0] == 60 ? 1:0;\r
/* crapto1.c\r
\r
- This program is free software; you can redistribute it and/or\r
- modify it under the terms of the GNU General Public License\r
- as published by the Free Software Foundation; either version 2\r
- of the License, or (at your option) any later version.\r
-\r
- This program is distributed in the hope that it will be useful,\r
- but WITHOUT ANY WARRANTY; without even the implied warranty of\r
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\r
- GNU General Public License for more details.\r
-\r
- You should have received a copy of the GNU General Public License\r
- along with this program; if not, write to the Free Software\r
- Foundation, Inc., 51 Franklin Street, Fifth Floor,\r
- Boston, MA 02110-1301, US$\r
-\r
- Copyright (C) 2008-2008 bla <blapost@gmail.com>\r
+ This program is free software; you can redistribute it and/or\r
+ modify it under the terms of the GNU General Public License\r
+ as published by the Free Software Foundation; either version 2\r
+ of the License, or (at your option) any later version.\r
+\r
+ This program is distributed in the hope that it will be useful,\r
+ but WITHOUT ANY WARRANTY; without even the implied warranty of\r
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\r
+ GNU General Public License for more details.\r
+\r
+ You should have received a copy of the GNU General Public License\r
+ along with this program; if not, write to the Free Software\r
+ Foundation, Inc., 51 Franklin Street, Fifth Floor,\r
+ Boston, MA 02110-1301, US$\r
+\r
+ Copyright (C) 2008-2008 bla <blapost@gmail.com>\r
*/\r
#include "crapto1.h"\r
#include <stdlib.h>\r
static uint8_t filterlut[1 << 20];\r
static void __attribute__((constructor)) fill_lut()\r
{\r
- uint32_t i;\r
- for(i = 0; i < 1 << 20; ++i)\r
- filterlut[i] = filter(i);\r
+ uint32_t i;\r
+ for(i = 0; i < 1 << 20; ++i)\r
+ filterlut[i] = filter(i);\r
}\r
#define filter(x) (filterlut[(x) & 0xfffff])\r
#endif\r
*p ^= in;\r
} else { // drop\r
*p-- = *(*end)--;\r
- }\r
+ }\r
}\r
\r
}\r
\r
for (int i = bucket_info.numbuckets - 1; i >= 0; i--) {\r
sl = recover(bucket_info.bucket_info[1][i].head, bucket_info.bucket_info[1][i].tail, oks,\r
- bucket_info.bucket_info[0][i].head, bucket_info.bucket_info[0][i].tail, eks,\r
+ bucket_info.bucket_info[0][i].head, bucket_info.bucket_info[0][i].tail, eks,\r
rem, sl, in, bucket);\r
}\r
\r
*/\r
static struct Crypto1State*\r
brute_top(uint32_t prefix, uint32_t rresp, unsigned char parities[8][8],\r
- uint32_t odd, uint32_t even, struct Crypto1State* sl, uint8_t no_chk)\r
+ uint32_t odd, uint32_t even, struct Crypto1State* sl, uint8_t no_chk)\r
{\r
struct Crypto1State s;\r
uint32_t ks1, nr, ks2, rr, ks3, good, c;\r
void SendCommand(UsbCommand *c) {
#if 0
- printf("Sending %d bytes\n", sizeof(UsbCommand));
+ printf("Sending %d bytes\n", sizeof(UsbCommand));
#endif
if (offline) {
or disconnected. The main console thread is alive, but comm thread just spins here.
Not good.../holiman
**/
- while(txcmd_pending);
- txcmd = *c;
- txcmd_pending = true;
+ while(txcmd_pending);
+ txcmd = *c;
+ txcmd_pending = true;
}
struct receiver_arg {
- int run;
+ int run;
};
struct main_loop_arg {
- int usb_present;
- char *script_cmds_file;
+ int usb_present;
+ char *script_cmds_file;
};
byte_t rx[0x1000000];
byte_t* prx = rx;
static void *uart_receiver(void *targ) {
- struct receiver_arg *arg = (struct receiver_arg*)targ;
- size_t rxlen;
- size_t cmd_count;
+ struct receiver_arg *arg = (struct receiver_arg*)targ;
+ size_t rxlen;
+ size_t cmd_count;
- while (arg->run) {
- rxlen = sizeof(UsbCommand);
+ while (arg->run) {
+ rxlen = sizeof(UsbCommand);
if (uart_receive(sp, prx, &rxlen)) {
- prx += rxlen;
- if (((prx-rx) % sizeof(UsbCommand)) != 0) {
- continue;
- }
- cmd_count = (prx-rx) / sizeof(UsbCommand);
+ prx += rxlen;
+ if (((prx-rx) % sizeof(UsbCommand)) != 0) {
+ continue;
+ }
+ cmd_count = (prx-rx) / sizeof(UsbCommand);
for (size_t i = 0; i < cmd_count; i++) {
- UsbCommandReceived((UsbCommand*)(rx+(i*sizeof(UsbCommand))));
- }
- }
- prx = rx;
+ UsbCommandReceived((UsbCommand*)(rx+(i*sizeof(UsbCommand))));
+ }
+ }
+ prx = rx;
- if(txcmd_pending) {
+ if(txcmd_pending) {
if (!uart_send(sp, (byte_t*) &txcmd, sizeof(UsbCommand))) {
- PrintAndLog("Sending bytes to proxmark failed");
- }
- txcmd_pending = false;
- }
- }
+ PrintAndLog("Sending bytes to proxmark failed");
+ }
+ txcmd_pending = false;
+ }
+ }
- pthread_exit(NULL);
- return NULL;
+ pthread_exit(NULL);
+ return NULL;
}
static void *main_loop(void *targ) {
- struct main_loop_arg *arg = (struct main_loop_arg*)targ;
- struct receiver_arg rarg;
- char *cmd = NULL;
- pthread_t reader_thread;
+ struct main_loop_arg *arg = (struct main_loop_arg*)targ;
+ struct receiver_arg rarg;
+ char *cmd = NULL;
+ pthread_t reader_thread;
- if (arg->usb_present == 1) {
+ if (arg->usb_present == 1) {
rarg.run = 1;
- pthread_create(&reader_thread, NULL, &uart_receiver, &rarg);
- }
+ pthread_create(&reader_thread, NULL, &uart_receiver, &rarg);
+ }
- FILE *script_file = NULL;
+ FILE *script_file = NULL;
char script_cmd_buf[256]; // iceman, needs lua script the same file_path_buffer as the rest
if (arg->script_cmds_file) {
- script_file = fopen(arg->script_cmds_file, "r");
+ script_file = fopen(arg->script_cmds_file, "r");
if (script_file) {
- printf("using 'scripting' commands file %s\n", arg->script_cmds_file);
- }
- }
+ printf("using 'scripting' commands file %s\n", arg->script_cmds_file);
+ }
+ }
read_history(".history");
while(1) {
- // If there is a script file
- if (script_file)
- {
+ // If there is a script file
+ if (script_file)
+ {
if (!fgets(script_cmd_buf, sizeof(script_cmd_buf), script_file)) {
- fclose(script_file);
- script_file = NULL;
+ fclose(script_file);
+ script_file = NULL;
} else {
- char *nl;
- nl = strrchr(script_cmd_buf, '\r');
- if (nl) *nl = '\0';
+ char *nl;
+ nl = strrchr(script_cmd_buf, '\r');
+ if (nl) *nl = '\0';
- nl = strrchr(script_cmd_buf, '\n');
- if (nl) *nl = '\0';
+ nl = strrchr(script_cmd_buf, '\n');
+ if (nl) *nl = '\0';
if ((cmd = (char*) malloc(strlen(script_cmd_buf) + 1)) != NULL) {
- memset(cmd, 0, strlen(script_cmd_buf));
- strcpy(cmd, script_cmd_buf);
- printf("%s\n", cmd);
- }
- }
- }
+ memset(cmd, 0, strlen(script_cmd_buf));
+ strcpy(cmd, script_cmd_buf);
+ printf("%s\n", cmd);
+ }
+ }
+ }
if (!script_file) {
- cmd = readline(PROXPROMPT);
+ cmd = readline(PROXPROMPT);
}
if (cmd) {
while(cmd[strlen(cmd) - 1] == ' ')
- cmd[strlen(cmd) - 1] = 0x00;
+ cmd[strlen(cmd) - 1] = 0x00;
if (cmd[0] != 0x00) {
if (strncmp(cmd, "quit", 4) == 0) {
write_history(".history");
- if (arg->usb_present == 1) {
- rarg.run = 0;
- pthread_join(reader_thread, NULL);
- }
+ if (arg->usb_present == 1) {
+ rarg.run = 0;
+ pthread_join(reader_thread, NULL);
+ }
if (script_file) {
- fclose(script_file);
- script_file = NULL;
- }
+ fclose(script_file);
+ script_file = NULL;
+ }
- ExitGraphics();
- pthread_exit(NULL);
- return NULL;
+ ExitGraphics();
+ pthread_exit(NULL);
+ return NULL;
}
static void dumpAllHelp(int markdown)
#include "usb_cmd.h"
-#define PROXPROMPT "proxmark3> "
+#define PROXPROMPT "pm3 --> "
void SendCommand(UsbCommand *c);
#include "nonce2key/nonce2key.h"
#include "../common/iso15693tools.h"
#include "../common/crc16.h"
+#include "../common/crc64.h"
#include "aes.h"
/**
* The following params expected:
return 1;
}
+static int l_crc64(lua_State *L)
+{
+ size_t size;
+ uint64_t crc = 0;
+ unsigned char outdata[8] = {0x00};
+
+ const char *p_str = luaL_checklstring(L, 1, &size);
+
+ crc64( (uint8_t*) p_str, size, &crc);
+
+ outdata[0] = (uint8_t)(crc >> 56) & 0xff;
+ outdata[1] = (uint8_t)(crc >> 48) & 0xff;
+ outdata[2] = (uint8_t)(crc >> 40) & 0xff;
+ outdata[3] = (uint8_t)(crc >> 32) & 0xff;
+ outdata[4] = (uint8_t)(crc >> 24) & 0xff;
+ outdata[5] = (uint8_t)(crc >> 16) & 0xff;
+ outdata[6] = (uint8_t)(crc >> 8) & 0xff;
+ outdata[7] = crc & 0xff;
+ lua_pushlstring(L,(const char *)&outdata, sizeof(outdata));
+ return 1;
+}
+
/**
* @brief Sets the lua path to include "./lualibs/?.lua", in order for a script to be
* able to do "require('foobar')" if foobar.lua is within lualibs folder.
{"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},
{"aes", l_aes},
{"crc16", l_crc16},
+ {"crc64", l_crc64},
{NULL, NULL}
};
\r
core.clearCommandBuffer()\r
\r
- if 0x18 == result.sak then --NXP MIFARE Classic 4k | Plus 4k\r
+ if 0x18 == result.sak then -- NXP MIFARE Classic 4k | Plus 4k\r
-- IFARE Classic 4K offers 4096 bytes split into forty sectors, \r
-- of which 32 are same size as in the 1K with eight more that are quadruple size sectors. \r
numSectors = 40\r
- elseif 0x08 == result.sak then -- NXP MIFARE CLASSIC 1k | Plus 2k\r
+ elseif 0x08 == result.sak then -- NXP MIFARE CLASSIC 1k | Plus 2k\r
-- 1K offers 1024 bytes of data storage, split into 16 sector\r
numSectors = 16\r
- elseif 0x09 == result.sak then -- NXP MIFARE Mini 0.3k\r
+ elseif 0x09 == result.sak then -- NXP MIFARE Mini 0.3k\r
-- MIFARE Classic mini offers 320 bytes split into five sectors.\r
numSectors = 5\r
elseif 0x10 == result.sak then -- NXP MIFARE Plus 2k\r
+++ /dev/null
-local foo = "This shows how to use some standard libraries"
-print(foo)
-local answer
-repeat
- io.write("Continue with this operation (y/n)? ")
- io.flush()
- answer=io.read()
-until answer=="y" or answer=="n"
-local x = "Ok then, %s"
-print (x:format("whatever"))
\ No newline at end of file
local dumplib = require('html_dumplib')
local toyNames = require('default_toys')
+
example =[[
- 1. script run tnp3dump
- 2. script run tnp3dump -n
- 3. script run tnp3dump -k aabbccddeeff
- 4. script run tnp3dump -k aabbccddeeff -n
- 5. script run tnp3dump -o myfile
- 6. script run tnp3dump -n -o myfile
- 7. script run tnp3dump -k aabbccddeeff -n -o myfile
+ script run tnp3dump
+ script run tnp3dump -n
+ script run tnp3dump -p
+ script run tnp3dump -k aabbccddeeff
+ script run tnp3dump -k aabbccddeeff -n
+ script run tnp3dump -o myfile
+ script run tnp3dump -n -o myfile
+ script run tnp3dump -p -o myfile
+ script run tnp3dump -k aabbccddeeff -n -o myfile
]]
author = "Iceman"
-usage = "script run tnp3dump -k <key> -n -o <filename>"
+usage = "script run tnp3dump -k <key> -n -p -o <filename>"
desc =[[
This script will try to dump the contents of a Mifare TNP3xxx card.
It will need a valid KeyA in order to find the other keys and decode the card.
-h : this help
-k <key> : Sector 0 Key A.
-n : Use the nested cmd to find all keys
+ -p : Use the precalc to find all keys
-o : filename for the saved dumps
]]
local cmd
local err
local useNested = false
+ local usePreCalc = false
local cmdReadBlockString = 'hf mf rdbl %d A %s'
local input = "dumpkeys.bin"
local outputTemplate = os.date("toydump_%Y-%m-%d_%H%M%S");
-- Arguments for the script
- for o, a in getopt.getopt(args, 'hk:no:') do
+ for o, a in getopt.getopt(args, 'hk:npo:') do
if o == "h" then return help() end
if o == "k" then keyA = a end
if o == "n" then useNested = true end
+ if o == "p" then usePreCalc = true end
if o == "o" then outputTemplate = a end
end
end
-- Show tag info
- print((' Found tag : %s'):format(result.name))
- print(('Using keyA : %s'):format(keyA))
+ print((' Found tag %s'):format(result.name))
+
+ dbg(('Using keyA : %s'):format(keyA))
--Trying to find the other keys
if useNested then
core.console( ('hf mf nested 1 0 A %s d'):format(keyA) )
end
-
+
core.clearCommandBuffer()
- -- Loading keyfile
- print('Loading dumpkeys.bin')
- local hex, err = utils.ReadDumpFile(input)
- if not hex then
- return oops(err)
+ local akeys = ''
+ if usePreCalc then
+ local pre = require('precalc')
+ akeys = pre.GetAll(result.uid)
+ else
+ print('Loading dumpkeys.bin')
+ local hex, err = utils.ReadDumpFile(input)
+ if not hex then
+ return oops(err)
+ end
+ akeys = hex:sub(0,12*16)
end
-
- local akeys = hex:sub(0,12*16)
-
+
-- Read block 0
cmd = Command:new{cmd = cmds.CMD_MIFARE_READBL, arg1 = 0,arg2 = 0,arg3 = 0, data = keyA}
err = core.SendCommand(cmd:getBytes())
core.clearCommandBuffer()
-- main loop
- io.write('Decrypting blocks > ')
+ io.write('Reading blocks > ')
for blockNo = 0, numBlocks-1, 1 do
if core.ukbhit() then
end
end
-
local uid = block0:sub(1,8)
local itemtype = block1:sub(1,4)
+ local cardidLsw = block1:sub(9,16)
+ local cardidMsw = block1:sub(16,24)
local cardid = block1:sub(9,24)
local traptype = block1:sub(25,28)
-- Write dump to files
if not DEBUG then
local foo = dumplib.SaveAsBinary(bindata, outputTemplate..'_uid_'..uid..'.bin')
- print(("Wrote a BIN dump to the file %s"):format(foo))
+ print(("Wrote a BIN dump to: %s"):format(foo))
local bar = dumplib.SaveAsText(emldata, outputTemplate..'_uid_'..uid..'.eml')
- print(("Wrote a EML dump to the file %s"):format(bar))
+ print(("Wrote a EML dump to: %s"):format(bar))
end
+ local itemtypename = toyNames[itemtype]
+ if itemtypename == nil then
+ itemtypename = toyNames[utils.SwapEndiannessStr(itemtype,16)]
+ end
-- Show info
print( string.rep('--',20) )
- print( (' ITEM TYPE : 0x%s - %s'):format(itemtype, toyNames[itemtype]) )
+ print( (' ITEM TYPE : 0x%s - %s'):format(itemtype, itemtypename) )
print( (' Alter ego / traptype : 0x%s'):format(traptype) )
print( (' UID : 0x%s'):format(uid) )
print( (' CARDID : 0x%s'):format(cardid ) )
]]
local TIMEOUT = 2000 -- Shouldn't take longer than 2 seconds
-local DEBUG = true -- the debug flag
+local DEBUG = false -- the debug flag
+
+
+local band = bit32.band
+local bor = bit32.bor
+local lshift = bit32.lshift
+local rshift = bit32.rshift
+local byte = string.byte
+local char = string.char
+local sub = string.sub
+local format = string.format
+
---
-- A debug printout-function
function dbg(args)
print()
end
-
local function writedumpfile(infile)
t = infile:read("*all")
len = string.len(t)
io.write( ('TYPE 3 area 2: %04x = %04x -- %s\n'):format(crc,calc,isOk))
end
-
local function LoadEmulator(blocks)
local HASHCONSTANT = '20436F707972696768742028432920323031302041637469766973696F6E2E20416C6C205269676874732052657365727665642E20'
local cmd
io.write('\n')
end
+local function Num2Card(m, l)
+
+ local k = {
+ 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39,0x42, 0x43, 0x44, 0x46, 0x47, 0x48, 0x4A, 0x4B,
+ 0x4C, 0x4D, 0x4E, 0x50, 0x51, 0x52, 0x53, 0x54,0x56, 0x57, 0x58, 0x59, 0x5A, 0x00
+ }
+ local msw = tonumber(utils.SwapEndiannessStr(m,32),16)
+ local lsw = tonumber(utils.SwapEndiannessStr(l,32),16)
+
+ if msw > 0x17ea1 then
+ return "too big"
+ end
+
+ if msw == 0x17ea1 and lsw > 0x8931fee8 then
+ return "out of range"
+ end
+
+ local s = ""
+ local index
+ for i = 1,10 do
+ index, msw, lsw = DivideByK( msw, lsw)
+ if ( index <= 1 ) then
+ s = char(k[index]) .. s
+ else
+ s = char(k[index-1]) .. s
+ end
+ print (index-1, msw, lsw)
+ end
+ return s
+end
+--33LRT-LM9Q9
+--7, 122, 3474858630
+--20, 4, 1008436634
+--7, 0, 627182959
+--17, 0, 21626998
+--16, 0, 745758
+--23, 0, 25715
+--21, 0, 886
+--16, 0, 30
+--1, 0, 1
+--1, 0, 0
+
+function DivideByK(msw, lsw)
+
+ local lowLSW
+ local highLSW
+ local remainder = 0
+ local RADIX = 29
+
+ --local num = 0 | band( rshift(msw,16), 0xffff)
+ local num = band( rshift(msw, 16), 0xffff)
+
+ --highLSW = 0 | lshift( (num / RADIX) , 16)
+ highLSW = lshift( (num / RADIX) , 16)
+ remainder = num % RADIX
+
+ num = bor( lshift(remainder,16), band(msw, 0xffff))
+
+ --highLSW |= num / RADIX
+ highLSW = highLSW or (num / RADIX)
+ remainder = num % RADIX
+
+ num = bor( lshift(remainder,16), ( band(rshift(lsw,16), 0xffff)))
+
+ --lowLSW = 0 | (num / RADIX) << 16
+ lowLSW = 0 or (lshift( (num / RADIX), 16))
+ remainder = num % RADIX
+
+ num = bor( lshift(remainder,16) , band(lsw, 0xffff) )
+
+ lowLSW = bor(lowLSW, (num / RADIX))
+ remainder = num % RADIX
+ return remainder, highLSW, lowLSW
+
+ uint num = 0 | (msw >> 16) & 0xffff;
+
+ highLSW = 0 | (num / RADIX) << 16;
+ remainder = num % RADIX;
+
+ num = (remainder << 16) | (msw & 0xffff);
+
+ highLSW |= num / RADIX;
+ remainder = num % RADIX;
+
+ num = (remainder << 16) | ((lsw >> 16) & 0xffff);
+
+ lowLSW = 0 | (num / RADIX) << 16;
+ remainder = num % RADIX;
+
+ num = (remainder << 16) | (lsw & 0xffff);
+
+ lowLSW |= num / RADIX;
+ remainder = num % RADIX;
+
+end
+
local function main(args)
print( string.rep('--',20) )
print(' Gathering info')
local uid = blocks[0]:sub(1,8)
local itemtype = blocks[1]:sub(1,4)
- local cardid = blocks[1]:sub(9,24)
+ local cardidLsw = blocks[1]:sub(9,16)
+ local cardidMsw = blocks[1]:sub(17,24)
+ local itemtypename = toyNames[itemtype]
+ if itemtypename == nil then
+ itemtypename = toyNames[utils.SwapEndiannessStr(itemtype,16)]
+ end
+
-- Show info
print( string.rep('--',20) )
- print( (' ITEM TYPE : 0x%s - %s'):format(itemtype, toyNames[itemtype]) )
+ print( (' ITEM TYPE : 0x%s - %s'):format(itemtype, itemtypename) )
print( (' UID : 0x%s'):format(uid) )
- print( (' CARDID : 0x%s'):format(cardid ) )
+ print( (' CARDID : 0x%s %s [%s]'):format(
+ cardidMsw,cardidLsw,
+ Num2Card(cardidMsw, cardidLsw))
+ )
print( string.rep('--',20) )
+
-- lets do something.
--
local experience = blocks[8]:sub(1,6)
#include <stdarg.h>
#include <stdlib.h>
#include <stdio.h>
+#include <stdbool.h>
#include <time.h>
#include <readline/readline.h>
#include <pthread.h>
-
+#include "loclass/cipherutils.h"
#include "ui.h"
+#include "cmdmain.h"
+#include "cmddata.h"
+#include "graph.h"
+//#include <liquid/liquid.h>
+#define M_PI 3.14159265358979323846264338327
double CursorScaleFactor;
int PlotGridX, PlotGridY, PlotGridXdefault= 64, PlotGridYdefault= 64;
int offline;
-int flushAfterWrite = 0; //buzzy
+int flushAfterWrite = 0;
extern pthread_mutex_t print_lock;
static char *logfilename = "proxmark3.log";
int saved_point;
va_list argptr, argptr2;
static FILE *logfile = NULL;
- static int logging=1;
+ static int logging = 1;
// lock this section to avoid interlacing prints from different threats
pthread_mutex_lock(&print_lock);
if (logging && !logfile) {
- logfile=fopen(logfilename, "a");
+ logfile = fopen(logfilename, "a");
if (!logfile) {
fprintf(stderr, "Can't open logfile, logging disabled!\n");
logging=0;
}
va_end(argptr2);
- if (flushAfterWrite == 1) //buzzy
- {
+ if (flushAfterWrite == 1) {
fflush(NULL);
}
//release lock
pthread_mutex_unlock(&print_lock);
}
-
void SetLogFilename(char *fn)
{
logfilename = fn;
}
+
+int manchester_decode( int * data, const size_t len, uint8_t * dataout, size_t dataoutlen){
+
+ int bitlength = 0;
+ int clock, high, low, startindex;
+ low = startindex = 0;
+ high = 1;
+ uint8_t * bitStream = (uint8_t* ) malloc(sizeof(uint8_t) * dataoutlen);
+ memset(bitStream, 0x00, dataoutlen);
+
+ /* Detect high and lows */
+ DetectHighLowInGraph(&high, &low, TRUE);
+
+ /* get clock */
+ clock = GetAskClock("",false, false);
+
+ startindex = DetectFirstTransition(data, len, high);
+
+ if (high != 1)
+ // decode "raw"
+ bitlength = ManchesterConvertFrom255(data, len, bitStream, dataoutlen, high, low, clock, startindex);
+ else
+ // decode manchester
+ bitlength = ManchesterConvertFrom1(data, len, bitStream, dataoutlen, clock, startindex);
+
+ memcpy(dataout, bitStream, bitlength);
+ free(bitStream);
+ return bitlength;
+}
+
+ int DetectFirstTransition(const int * data, const size_t len, int threshold){
+
+ int i = 0;
+ /* now look for the first threshold */
+ for (; i < len; ++i) {
+ if (data[i] == threshold) {
+ break;
+ }
+ }
+ return i;
+ }
+
+ int ManchesterConvertFrom255(const int * data, const size_t len, uint8_t * dataout, int dataoutlen, int high, int low, int clock, int startIndex){
+
+ int i, j, z, hithigh, hitlow, bitIndex, startType;
+ i = 0;
+ bitIndex = 0;
+
+ int isDamp = 0;
+ int damplimit = (int)((high / 2) * 0.3);
+ int dampHi = (high/2)+damplimit;
+ int dampLow = (high/2)-damplimit;
+ int firstST = 0;
+
+ // i = clock frame of data
+ for (; i < (int)(len/clock); i++)
+ {
+ hithigh = 0;
+ hitlow = 0;
+ startType = -1;
+ z = startIndex + (i*clock);
+ isDamp = 0;
+
+ /* Find out if we hit both high and low peaks */
+ for (j = 0; j < clock; j++)
+ {
+ if (data[z+j] == high){
+ hithigh = 1;
+ if ( startType == -1)
+ startType = 1;
+ }
+
+ if (data[z+j] == low ){
+ hitlow = 1;
+ if ( startType == -1)
+ startType = 0;
+ }
+
+ if (hithigh && hitlow)
+ break;
+ }
+
+ // No high value found, are we in a dampening field?
+ if ( !hithigh ) {
+ //PrintAndLog(" # Entering damp test at index : %d (%d)", z+j, j);
+ for (j = 0; j < clock; j++) {
+ if (
+ (data[z+j] <= dampHi && data[z+j] >= dampLow)
+ ){
+ isDamp++;
+ }
+ }
+ }
+
+ /* Manchester Switching..
+ 0: High -> Low
+ 1: Low -> High
+ */
+ if (startType == 0)
+ dataout[bitIndex++] = 1;
+ else if (startType == 1)
+ dataout[bitIndex++] = 0;
+ else
+ dataout[bitIndex++] = 2;
+
+ if ( isDamp > clock/2 ) {
+ firstST++;
+ }
+
+ if ( firstST == 4)
+ break;
+ if ( bitIndex >= dataoutlen-1 )
+ break;
+ }
+ return bitIndex;
+ }
+
+ int ManchesterConvertFrom1(const int * data, const size_t len, uint8_t * dataout,int dataoutlen, int clock, int startIndex){
+
+ int i,j, bitindex, lc, tolerance, warnings;
+ warnings = 0;
+ int upperlimit = len*2/clock+8;
+ i = startIndex;
+ j = 0;
+ tolerance = clock/4;
+ uint8_t decodedArr[len];
+
+ /* Detect duration between 2 successive transitions */
+ for (bitindex = 1; i < len; i++) {
+
+ if (data[i-1] != data[i]) {
+ lc = i - startIndex;
+ startIndex = i;
+
+ // Error check: if bitindex becomes too large, we do not
+ // have a Manchester encoded bitstream or the clock is really wrong!
+ if (bitindex > upperlimit ) {
+ PrintAndLog("Error: the clock you gave is probably wrong, aborting.");
+ return 0;
+ }
+ // Then switch depending on lc length:
+ // Tolerance is 1/4 of clock rate (arbitrary)
+ if (abs((lc-clock)/2) < tolerance) {
+ // Short pulse : either "1" or "0"
+ decodedArr[bitindex++] = data[i-1];
+ } else if (abs(lc-clock) < tolerance) {
+ // Long pulse: either "11" or "00"
+ decodedArr[bitindex++] = data[i-1];
+ decodedArr[bitindex++] = data[i-1];
+ } else {
+ ++warnings;
+ PrintAndLog("Warning: Manchester decode error for pulse width detection.");
+ if (warnings > 10) {
+ PrintAndLog("Error: too many detection errors, aborting.");
+ return 0;
+ }
+ }
+ }
+ }
+
+ /*
+ * We have a decodedArr of "01" ("1") or "10" ("0")
+ * parse it into final decoded dataout
+ */
+ for (i = 0; i < bitindex; i += 2) {
+
+ if ((decodedArr[i] == 0) && (decodedArr[i+1] == 1)) {
+ dataout[j++] = 1;
+ } else if ((decodedArr[i] == 1) && (decodedArr[i+1] == 0)) {
+ dataout[j++] = 0;
+ } else {
+ i++;
+ warnings++;
+ PrintAndLog("Unsynchronized, resync...");
+ PrintAndLog("(too many of those messages mean the stream is not Manchester encoded)");
+
+ if (warnings > 10) {
+ PrintAndLog("Error: too many decode errors, aborting.");
+ return 0;
+ }
+ }
+ }
+
+ PrintAndLog("%s", sprint_hex(dataout, j));
+ return j;
+ }
+
+ void ManchesterDiffDecodedString(const uint8_t* bitstream, size_t len, uint8_t invert){
+ /*
+ * We have a bitstream of "01" ("1") or "10" ("0")
+ * parse it into final decoded bitstream
+ */
+ int i, j, warnings;
+ uint8_t decodedArr[(len/2)+1];
+
+ j = warnings = 0;
+
+ uint8_t lastbit = 0;
+
+ for (i = 0; i < len; i += 2) {
+
+ uint8_t first = bitstream[i];
+ uint8_t second = bitstream[i+1];
+
+ if ( first == second ) {
+ ++i;
+ ++warnings;
+ if (warnings > 10) {
+ PrintAndLog("Error: too many decode errors, aborting.");
+ return;
+ }
+ }
+ else if ( lastbit != first ) {
+ decodedArr[j++] = 0 ^ invert;
+ }
+ else {
+ decodedArr[j++] = 1 ^ invert;
+ }
+ lastbit = second;
+ }
+
+ PrintAndLog("%s", sprint_hex(decodedArr, j));
+}
+
+void PrintPaddedManchester( uint8_t* bitStream, size_t len, size_t blocksize){
+
+ PrintAndLog(" Manchester decoded : %d bits", len);
+
+ uint8_t mod = len % blocksize;
+ uint8_t div = len / blocksize;
+ int i;
+
+ // Now output the bitstream to the scrollback by line of 16 bits
+ for (i = 0; i < div*blocksize; i+=blocksize) {
+ PrintAndLog(" %s", sprint_bin(bitStream+i,blocksize) );
+ }
+
+ if ( mod > 0 )
+ PrintAndLog(" %s", sprint_bin(bitStream+i, mod) );
+}
+
+/* Sliding DFT
+ Smooths out
+*/
+void iceFsk2(int * data, const size_t len){
+
+ int i, j;
+ int * output = (int* ) malloc(sizeof(int) * len);
+ memset(output, 0x00, len);
+
+ // for (i=0; i<len-5; ++i){
+ // for ( j=1; j <=5; ++j) {
+ // output[i] += data[i*j];
+ // }
+ // output[i] /= 5;
+ // }
+ int rest = 127;
+ int tmp =0;
+ for (i=0; i<len; ++i){
+ if ( data[i] < 127)
+ output[i] = 0;
+ else {
+ tmp = (100 * (data[i]-rest)) / rest;
+ output[i] = (tmp > 60)? 100:0;
+ }
+ }
+
+ for (j=0; j<len; ++j)
+ data[j] = output[j];
+
+ free(output);
+}
+
+void iceFsk3(int * data, const size_t len){
+
+ int i,j;
+
+ int * output = (int* ) malloc(sizeof(int) * len);
+ memset(output, 0x00, len);
+ float fc = 0.1125f; // center frequency
+ size_t adjustedLen = len;
+
+ // create very simple low-pass filter to remove images (2nd-order Butterworth)
+ float complex iir_buf[3] = {0,0,0};
+ float b[3] = {0.003621681514929, 0.007243363029857, 0.003621681514929};
+ float a[3] = {1.000000000000000, -1.822694925196308, 0.837181651256023};
+
+ float sample = 0; // input sample read from file
+ float complex x_prime = 1.0f; // save sample for estimating frequency
+ float complex x;
+
+ for (i=0; i<adjustedLen; ++i) {
+
+ sample = data[i]+128;
+
+ // remove DC offset and mix to complex baseband
+ x = (sample - 127.5f) * cexpf( _Complex_I * 2 * M_PI * fc * i );
+
+ // apply low-pass filter, removing spectral image (IIR using direct-form II)
+ iir_buf[2] = iir_buf[1];
+ iir_buf[1] = iir_buf[0];
+ iir_buf[0] = x - a[1]*iir_buf[1] - a[2]*iir_buf[2];
+ x = b[0]*iir_buf[0] +
+ b[1]*iir_buf[1] +
+ b[2]*iir_buf[2];
+
+ // compute instantaneous frequency by looking at phase difference
+ // between adjacent samples
+ float freq = cargf(x*conjf(x_prime));
+ x_prime = x; // retain this sample for next iteration
+
+ output[i] =(freq > 0)? 10 : -10;
+ }
+
+ // show data
+ for (j=0; j<adjustedLen; ++j)
+ data[j] = output[j];
+
+ CmdLtrim("30");
+ adjustedLen -= 30;
+
+ // zero crossings.
+ for (j=0; j<adjustedLen; ++j){
+ if ( data[j] == 10) break;
+ }
+ int startOne =j;
+
+ for (;j<adjustedLen; ++j){
+ if ( data[j] == -10 ) break;
+ }
+ int stopOne = j-1;
+
+ int fieldlen = stopOne-startOne;
+
+ fieldlen = (fieldlen == 39 || fieldlen == 41)? 40 : fieldlen;
+ fieldlen = (fieldlen == 59 || fieldlen == 51)? 50 : fieldlen;
+ if ( fieldlen != 40 && fieldlen != 50){
+ printf("Detected field Length: %d \n", fieldlen);
+ printf("Can only handle 40 or 50. Aborting...\n");
+ return;
+ }
+
+ // FSK sequence start == 000111
+ int startPos = 0;
+ for (i =0; i<adjustedLen; ++i){
+ int dec = 0;
+ for ( j = 0; j < 6*fieldlen; ++j){
+ dec += data[i + j];
+ }
+ if (dec == 0) {
+ startPos = i;
+ break;
+ }
+ }
+
+ printf("000111 position: %d \n", startPos);
+
+ startPos += 6*fieldlen+5;
+
+ int bit =0;
+ printf("BINARY\n");
+ printf("R/40 : ");
+ for (i =startPos ; i < adjustedLen; i += 40){
+ bit = data[i]>0 ? 1:0;
+ printf("%d", bit );
+ }
+ printf("\n");
+
+ printf("R/50 : ");
+ for (i =startPos ; i < adjustedLen; i += 50){
+ bit = data[i]>0 ? 1:0;
+ printf("%d", bit ); }
+ printf("\n");
+
+ free(output);
+}
+
+float complex cexpf (float complex Z)
+{
+ float complex Res;
+ double rho = exp (__real__ Z);
+ __real__ Res = rho * cosf(__imag__ Z);
+ __imag__ Res = rho * sinf(__imag__ Z);
+ return Res;
+}
#ifndef UI_H__
#define UI_H__
+#include <math.h>
+#include <complex.h>
+#include "util.h"
+
void ShowGui(void);
void HideGraphWindow(void);
void ShowGraphWindow(void);
extern int offline;
extern int flushAfterWrite; //buzzy
+int manchester_decode( int * data, const size_t len, uint8_t * dataout, size_t dataoutlen);
+int GetT55x7Clock( const int * data, const size_t len, int high );
+int DetectFirstTransition(const int * data, const size_t len, int low);
+void PrintPaddedManchester( uint8_t * bitStream, size_t len, size_t blocksize);
+void ManchesterDiffDecodedString( const uint8_t *bitStream, size_t len, uint8_t invert );
+int ManchesterConvertFrom255(const int * data, const size_t len, uint8_t * dataout,int dataoutlen, int high, int low, int clock, int startIndex);
+int ManchesterConvertFrom1(const int * data, const size_t len, uint8_t * dataout, int dataoutlen, int clock, int startIndex);
+void iceFsk2(int * data, const size_t len);
+void iceFsk3(int * data, const size_t len);
#endif
LIBS = -lgcc
+LIBS = -lgcc
+
THUMBOBJ = $(patsubst %.c,$(OBJDIR)/%.o,$(THUMBSRC))
ARMOBJ = $(ARMSRC:%.c=$(OBJDIR)/%.o)
ASMOBJ = $(patsubst %.s,$(OBJDIR)/%.o,$(ASMSRC))
//-----------------------------------------------------------------------------
// Generic CRC calculation code.
//-----------------------------------------------------------------------------
-
#include "crc.h"
+#include <stdint.h>
+#include <stddef.h>
void crc_init(crc_t *crc, int order, uint32_t polynom, uint32_t initial_value, uint32_t final_xor)
{
{
return ( crc->state ^ crc->final_xor ) & crc->mask;
}
+
+int CRC8Maxim(uint8_t *buff, size_t size ) {
+
+ crc_t crc;
+ crc_init(&crc, 8, 0x31, 0x00, 0x00);
+ crc_clear(&crc);
+
+ for ( int i=0; i < size; ++i){
+ crc_update(&crc, buff[i], 8);
+ }
+ return crc_finish(&crc);
+}
--- /dev/null
+//-----------------------------------------------------------------------------
+// This code is licensed to you under the terms of the GNU GPL, version 2 or,
+// at your option, any later version. See the LICENSE.txt file for the text of
+// the license.
+//-----------------------------------------------------------------------------
+// Generic CRC calculation code.
+//-----------------------------------------------------------------------------
+
+#ifndef __CRC_H
+#define __CRC_H
+
+#include <stdint.h>
+#include <stddef.h>
+
+typedef struct crc {
+ uint32_t state;
+ int order;
+ uint32_t polynom;
+ uint32_t initial_value;
+ uint32_t final_xor;
+ uint32_t mask;
+} crc_t;
+
+/* Initialize a crc structure. order is the order of the polynom, e.g. 32 for a CRC-32
+ * polynom is the CRC polynom. initial_value is the initial value of a clean state.
+ * final_xor is XORed onto the state before returning it from crc_result(). */
+extern void crc_init(crc_t *crc, int order, uint32_t polynom, uint32_t initial_value, uint32_t final_xor);
+
+/* Update the crc state. data is the data of length data_width bits (only the the
+ * data_width lower-most bits are used).
+ */
+extern void crc_update(crc_t *crc, uint32_t data, int data_width);
+
+/* Clean the crc state, e.g. reset it to initial_value */
+extern void crc_clear(crc_t *crc);
+
+/* Get the result of the crc calculation */
+extern uint32_t crc_finish(crc_t *crc);
+
+// Calculate CRC-8/Maxim checksum
+int CRC8Maxim(uint8_t *buff, size_t size );
+
+/* Static initialization of a crc structure */
+#define CRC_INITIALIZER(_order, _polynom, _initial_value, _final_xor) { \
+ .state = ((_initial_value) & ((1L<<(_order))-1)), \
+ .order = (_order), \
+ .polynom = (_polynom), \
+ .initial_value = (_initial_value), \
+ .final_xor = (_final_xor), \
+ .mask = ((1L<<(_order))-1) }
+
+#endif /* __CRC_H */
--- /dev/null
+#include <stdint.h>
+#include <stddef.h>
+#include "crc64.h"
+
+#define CRC64_ISO_PRESET 0xFFFFFFFFFFFFFFFF
+#define CRC64_ECMA_PRESET 0x0000000000000000
+
+const uint64_t crc64_table[] = {
+ 0x0000000000000000, 0x42F0E1EBA9EA3693, 0x85E1C3D753D46D26, 0xC711223CFA3E5BB5,
+ 0x493366450E42ECDF, 0x0BC387AEA7A8DA4C, 0xCCD2A5925D9681F9, 0x8E224479F47CB76A,
+ 0x9266CC8A1C85D9BE, 0xD0962D61B56FEF2D, 0x17870F5D4F51B498, 0x5577EEB6E6BB820B,
+ 0xDB55AACF12C73561, 0x99A54B24BB2D03F2, 0x5EB4691841135847, 0x1C4488F3E8F96ED4,
+ 0x663D78FF90E185EF, 0x24CD9914390BB37C, 0xE3DCBB28C335E8C9, 0xA12C5AC36ADFDE5A,
+ 0x2F0E1EBA9EA36930, 0x6DFEFF5137495FA3, 0xAAEFDD6DCD770416, 0xE81F3C86649D3285,
+ 0xF45BB4758C645C51, 0xB6AB559E258E6AC2, 0x71BA77A2DFB03177, 0x334A9649765A07E4,
+ 0xBD68D2308226B08E, 0xFF9833DB2BCC861D, 0x388911E7D1F2DDA8, 0x7A79F00C7818EB3B,
+ 0xCC7AF1FF21C30BDE, 0x8E8A101488293D4D, 0x499B3228721766F8, 0x0B6BD3C3DBFD506B,
+ 0x854997BA2F81E701, 0xC7B97651866BD192, 0x00A8546D7C558A27, 0x4258B586D5BFBCB4,
+ 0x5E1C3D753D46D260, 0x1CECDC9E94ACE4F3, 0xDBFDFEA26E92BF46, 0x990D1F49C77889D5,
+ 0x172F5B3033043EBF, 0x55DFBADB9AEE082C, 0x92CE98E760D05399, 0xD03E790CC93A650A,
+ 0xAA478900B1228E31, 0xE8B768EB18C8B8A2, 0x2FA64AD7E2F6E317, 0x6D56AB3C4B1CD584,
+ 0xE374EF45BF6062EE, 0xA1840EAE168A547D, 0x66952C92ECB40FC8, 0x2465CD79455E395B,
+ 0x3821458AADA7578F, 0x7AD1A461044D611C, 0xBDC0865DFE733AA9, 0xFF3067B657990C3A,
+ 0x711223CFA3E5BB50, 0x33E2C2240A0F8DC3, 0xF4F3E018F031D676, 0xB60301F359DBE0E5,
+ 0xDA050215EA6C212F, 0x98F5E3FE438617BC, 0x5FE4C1C2B9B84C09, 0x1D14202910527A9A,
+ 0x93366450E42ECDF0, 0xD1C685BB4DC4FB63, 0x16D7A787B7FAA0D6, 0x5427466C1E109645,
+ 0x4863CE9FF6E9F891, 0x0A932F745F03CE02, 0xCD820D48A53D95B7, 0x8F72ECA30CD7A324,
+ 0x0150A8DAF8AB144E, 0x43A04931514122DD, 0x84B16B0DAB7F7968, 0xC6418AE602954FFB,
+ 0xBC387AEA7A8DA4C0, 0xFEC89B01D3679253, 0x39D9B93D2959C9E6, 0x7B2958D680B3FF75,
+ 0xF50B1CAF74CF481F, 0xB7FBFD44DD257E8C, 0x70EADF78271B2539, 0x321A3E938EF113AA,
+ 0x2E5EB66066087D7E, 0x6CAE578BCFE24BED, 0xABBF75B735DC1058, 0xE94F945C9C3626CB,
+ 0x676DD025684A91A1, 0x259D31CEC1A0A732, 0xE28C13F23B9EFC87, 0xA07CF2199274CA14,
+ 0x167FF3EACBAF2AF1, 0x548F120162451C62, 0x939E303D987B47D7, 0xD16ED1D631917144,
+ 0x5F4C95AFC5EDC62E, 0x1DBC74446C07F0BD, 0xDAAD56789639AB08, 0x985DB7933FD39D9B,
+ 0x84193F60D72AF34F, 0xC6E9DE8B7EC0C5DC, 0x01F8FCB784FE9E69, 0x43081D5C2D14A8FA,
+ 0xCD2A5925D9681F90, 0x8FDAB8CE70822903, 0x48CB9AF28ABC72B6, 0x0A3B7B1923564425,
+ 0x70428B155B4EAF1E, 0x32B26AFEF2A4998D, 0xF5A348C2089AC238, 0xB753A929A170F4AB,
+ 0x3971ED50550C43C1, 0x7B810CBBFCE67552, 0xBC902E8706D82EE7, 0xFE60CF6CAF321874,
+ 0xE224479F47CB76A0, 0xA0D4A674EE214033, 0x67C58448141F1B86, 0x253565A3BDF52D15,
+ 0xAB1721DA49899A7F, 0xE9E7C031E063ACEC, 0x2EF6E20D1A5DF759, 0x6C0603E6B3B7C1CA,
+ 0xF6FAE5C07D3274CD, 0xB40A042BD4D8425E, 0x731B26172EE619EB, 0x31EBC7FC870C2F78,
+ 0xBFC9838573709812, 0xFD39626EDA9AAE81, 0x3A28405220A4F534, 0x78D8A1B9894EC3A7,
+ 0x649C294A61B7AD73, 0x266CC8A1C85D9BE0, 0xE17DEA9D3263C055, 0xA38D0B769B89F6C6,
+ 0x2DAF4F0F6FF541AC, 0x6F5FAEE4C61F773F, 0xA84E8CD83C212C8A, 0xEABE6D3395CB1A19,
+ 0x90C79D3FEDD3F122, 0xD2377CD44439C7B1, 0x15265EE8BE079C04, 0x57D6BF0317EDAA97,
+ 0xD9F4FB7AE3911DFD, 0x9B041A914A7B2B6E, 0x5C1538ADB04570DB, 0x1EE5D94619AF4648,
+ 0x02A151B5F156289C, 0x4051B05E58BC1E0F, 0x87409262A28245BA, 0xC5B073890B687329,
+ 0x4B9237F0FF14C443, 0x0962D61B56FEF2D0, 0xCE73F427ACC0A965, 0x8C8315CC052A9FF6,
+ 0x3A80143F5CF17F13, 0x7870F5D4F51B4980, 0xBF61D7E80F251235, 0xFD913603A6CF24A6,
+ 0x73B3727A52B393CC, 0x31439391FB59A55F, 0xF652B1AD0167FEEA, 0xB4A25046A88DC879,
+ 0xA8E6D8B54074A6AD, 0xEA16395EE99E903E, 0x2D071B6213A0CB8B, 0x6FF7FA89BA4AFD18,
+ 0xE1D5BEF04E364A72, 0xA3255F1BE7DC7CE1, 0x64347D271DE22754, 0x26C49CCCB40811C7,
+ 0x5CBD6CC0CC10FAFC, 0x1E4D8D2B65FACC6F, 0xD95CAF179FC497DA, 0x9BAC4EFC362EA149,
+ 0x158E0A85C2521623, 0x577EEB6E6BB820B0, 0x906FC95291867B05, 0xD29F28B9386C4D96,
+ 0xCEDBA04AD0952342, 0x8C2B41A1797F15D1, 0x4B3A639D83414E64, 0x09CA82762AAB78F7,
+ 0x87E8C60FDED7CF9D, 0xC51827E4773DF90E, 0x020905D88D03A2BB, 0x40F9E43324E99428,
+ 0x2CFFE7D5975E55E2, 0x6E0F063E3EB46371, 0xA91E2402C48A38C4, 0xEBEEC5E96D600E57,
+ 0x65CC8190991CB93D, 0x273C607B30F68FAE, 0xE02D4247CAC8D41B, 0xA2DDA3AC6322E288,
+ 0xBE992B5F8BDB8C5C, 0xFC69CAB42231BACF, 0x3B78E888D80FE17A, 0x7988096371E5D7E9,
+ 0xF7AA4D1A85996083, 0xB55AACF12C735610, 0x724B8ECDD64D0DA5, 0x30BB6F267FA73B36,
+ 0x4AC29F2A07BFD00D, 0x08327EC1AE55E69E, 0xCF235CFD546BBD2B, 0x8DD3BD16FD818BB8,
+ 0x03F1F96F09FD3CD2, 0x41011884A0170A41, 0x86103AB85A2951F4, 0xC4E0DB53F3C36767,
+ 0xD8A453A01B3A09B3, 0x9A54B24BB2D03F20, 0x5D45907748EE6495, 0x1FB5719CE1045206,
+ 0x919735E51578E56C, 0xD367D40EBC92D3FF, 0x1476F63246AC884A, 0x568617D9EF46BED9,
+ 0xE085162AB69D5E3C, 0xA275F7C11F7768AF, 0x6564D5FDE549331A, 0x279434164CA30589,
+ 0xA9B6706FB8DFB2E3, 0xEB46918411358470, 0x2C57B3B8EB0BDFC5, 0x6EA7525342E1E956,
+ 0x72E3DAA0AA188782, 0x30133B4B03F2B111, 0xF7021977F9CCEAA4, 0xB5F2F89C5026DC37,
+ 0x3BD0BCE5A45A6B5D, 0x79205D0E0DB05DCE, 0xBE317F32F78E067B, 0xFCC19ED95E6430E8,
+ 0x86B86ED5267CDBD3, 0xC4488F3E8F96ED40, 0x0359AD0275A8B6F5, 0x41A94CE9DC428066,
+ 0xCF8B0890283E370C, 0x8D7BE97B81D4019F, 0x4A6ACB477BEA5A2A, 0x089A2AACD2006CB9,
+ 0x14DEA25F3AF9026D, 0x562E43B4931334FE, 0x913F6188692D6F4B, 0xD3CF8063C0C759D8,
+ 0x5DEDC41A34BBEEB2, 0x1F1D25F19D51D821, 0xD80C07CD676F8394, 0x9AFCE626CE85B507
+};
+
+void crc64 (const uint8_t *data, const size_t len, uint64_t *crc) {
+
+ for (size_t i = 0; i < len; i++)
+ {
+ //uint8_t tableIndex = (((uint8_t)(*crc >> 56)) ^ data[i]) & 0xff;
+ uint8_t tableIndex = (((uint8_t)(*crc >> 56)) ^ data[i]) & 0xff;
+ *crc = crc64_table[tableIndex] ^ (*crc << 8);
+ }
+}
+
+//suint8_t x = (c & 0xFF00000000000000 ) >> 56;
\ No newline at end of file
--- /dev/null
+//-----------------------------------------------------------------------------
+// This code is licensed to you under the terms of the GNU GPL, version 2 or,
+// at your option, any later version. See the LICENSE.txt file for the text of
+// the license.
+//-----------------------------------------------------------------------------
+// CRC64 ECMA
+//-----------------------------------------------------------------------------
+
+#ifndef __CRC64_H
+#define __CRC64_H
+
+void crc64 (const uint8_t *data, const size_t len, uint64_t *crc) ;
+
+#endif
--- /dev/null
+#ifndef __DESFIRE_H
+#define __DESFIRE_H
+
+#include <string.h>
+#include <stdarg.h>
+
+#include "aes.h"
+
+#define MAX_CRYPTO_BLOCK_SIZE 16
+/* Mifare DESFire EV1 Application crypto operations */
+#define APPLICATION_CRYPTO_DES 0x00
+#define APPLICATION_CRYPTO_3K3DES 0x40
+#define APPLICATION_CRYPTO_AES 0x80
+
+#define MAC_LENGTH 4
+#define CMAC_LENGTH 8
+
+typedef enum {
+ MCD_SEND,
+ MCD_RECEIVE
+} MifareCryptoDirection;
+
+typedef enum {
+ MCO_ENCYPHER,
+ MCO_DECYPHER
+} MifareCryptoOperation;
+
+#define MDCM_MASK 0x000F
+
+#define CMAC_NONE 0
+
+// Data send to the PICC is used to update the CMAC
+#define CMAC_COMMAND 0x010
+// Data received from the PICC is used to update the CMAC
+#define CMAC_VERIFY 0x020
+
+// MAC the command (when MDCM_MACED)
+#define MAC_COMMAND 0x100
+// The command returns a MAC to verify (when MDCM_MACED)
+#define MAC_VERIFY 0x200
+
+#define ENC_COMMAND 0x1000
+#define NO_CRC 0x2000
+
+#define MAC_MASK 0x0F0
+#define CMAC_MACK 0xF00
+
+/* Communication mode */
+#define MDCM_PLAIN 0x00
+#define MDCM_MACED 0x01
+#define MDCM_ENCIPHERED 0x03
+
+/* Error code managed by the library */
+#define CRYPTO_ERROR 0x01
+
+
+enum DESFIRE_AUTH_SCHEME {
+ AS_LEGACY,
+ AS_NEW
+};
+
+enum DESFIRE_CRYPTOALGO {
+ T_DES = 0x00,
+ T_3DES = 0x01,
+ T_3K3DES = 0x02,
+ T_AES = 0x03
+};
+
+
+#define DESFIRE_KEY(key) ((struct desfire_key *) key)
+struct desfire_key {
+ enum DESFIRE_CRYPTOALGO type;
+ uint8_t data[24];
+ // DES_key_schedule ks1;
+ // DES_key_schedule ks2;
+ // DES_key_schedule ks3;
+ AesCtx aes_ks;
+ uint8_t cmac_sk1[24];
+ uint8_t cmac_sk2[24];
+ uint8_t aes_version;
+};
+typedef struct desfire_key *desfirekey_t;
+
+#define DESFIRE(tag) ((struct desfire_tag *) tag)
+struct desfire_tag {
+ iso14a_card_select_t info;
+ int active;
+ uint8_t last_picc_error;
+ uint8_t last_internal_error;
+ uint8_t last_pcd_error;
+ desfirekey_t session_key;
+ enum DESFIRE_AUTH_SCHEME authentication_scheme;
+ uint8_t authenticated_key_no;
+
+ uint8_t ivect[MAX_CRYPTO_BLOCK_SIZE];
+ uint8_t cmac[16];
+ uint8_t *crypto_buffer;
+ size_t crypto_buffer_size;
+ uint32_t selected_application;
+};
+typedef struct desfire_tag *desfiretag_t;
+
+
+/* File types */
+enum DESFIRE_FILE_TYPES {
+ MDFT_STANDARD_DATA_FILE = 0x00,
+ MDFT_BACKUP_DATA_FILE = 0x01,
+ MDFT_VALUE_FILE_WITH_BACKUP = 0x02,
+ MDFT_LINEAR_RECORD_FILE_WITH_BACKUP = 0x03,
+ MDFT_CYCLIC_RECORD_FILE_WITH_BACKUP = 0x04
+};
+
+
+
+enum DESFIRE_STATUS {
+ OPERATION_OK = 0x00,
+ NO_CHANGES = 0x0c,
+ OUT_OF_EEPROM_ERROR = 0x0e,
+ ILLEGAL_COMMAND_CODE = 0x1c,
+ INTEGRITY_ERROR = 0x1e,
+ NO_SUCH_KEY = 0x40,
+ LENGTH_ERROR = 0x7e,
+ PERMISSION_DENIED = 0x9d,
+ PARAMETER_ERROR = 0x9e,
+ APPLICATION_NOT_FOUND = 0xa0,
+ APPL_INTEGRITY_ERROR = 0xa1,
+ AUTHENTICATION_ERROR = 0xae,
+ ADDITIONAL_FRAME = 0xaf,
+ BOUNDARY_ERROR = 0xbe,
+ PICC_INTEGRITY_ERROR = 0xc1,
+ COMMAND_ABORTED = 0xca,
+ PICC_DISABLED_ERROR = 0xcd,
+ COUNT_ERROR = 0xce,
+ DUPLICATE_ERROR = 0xde,
+ EEPROM_ERROR = 0xee,
+ FILE_NOT_FOUND = 0xf0,
+ FILE_INTEGRITY_ERROR = 0xf1
+};
+
+enum DESFIRE_CMD {
+ CREATE_APPLICATION = 0xca,
+ DELETE_APPLICATION = 0xda,
+ GET_APPLICATION_IDS = 0x6a,
+ SELECT_APPLICATION = 0x5a,
+ FORMAT_PICC = 0xfc,
+ GET_VERSION = 0x60,
+ READ_DATA = 0xbd,
+ WRITE_DATA = 0x3d,
+ GET_VALUE = 0x6c,
+ CREDIT = 0x0c,
+ DEBIT = 0xdc,
+ LIMITED_CREDIT = 0x1c,
+ WRITE_RECORD = 0x3b,
+ READ_RECORDS = 0xbb,
+ CLEAR_RECORD_FILE = 0xeb,
+ COMMIT_TRANSACTION = 0xc7,
+ ABORT_TRANSACTION = 0xa7,
+ GET_FREE_MEMORY = 0x6e,
+ GET_FILE_IDS = 0x6f,
+ GET_FILE_SETTINGS = 0xf5,
+ CHANGE_FILE_SETTINGS = 0x5f,
+ CREATE_STD_DATA_FILE = 0xcd,
+ CREATE_BACKUP_DATA_FILE = 0xcb,
+ CREATE_VALUE_FILE = 0xcc,
+ CREATE_LINEAR_RECORD_FILE = 0xc1,
+ CREATE_CYCLIC_RECORD_FILE = 0xc0,
+ DELETE_FILE = 0xdf,
+ AUTHENTICATE = 0x0a, // AUTHENTICATE_NATIVE
+ AUTHENTICATE_ISO = 0x1a, // AUTHENTICATE_STANDARD
+ AUTHENTICATE_AES = 0xaa,
+ CHANGE_KEY_SETTINGS = 0x54,
+ GET_KEY_SETTINGS = 0x45,
+ CHANGE_KEY = 0xc4,
+ GET_KEY_VERSION = 0x64,
+ AUTHENTICATION_FRAME = 0xAF
+};
+
+#endif
+
// ISO14443 CRC calculation code.
//-----------------------------------------------------------------------------
-#include "iso14443crc.h"
+#include "../common/iso14443crc.h"
static unsigned short UpdateCrc14443(unsigned char ch, unsigned short *lpwCrc)
{
#ifndef __ISO14443CRC_H
#define __ISO14443CRC_H
-#include "common.h"
+#include "../include/common.h"
//-----------------------------------------------------------------------------
// Routines to compute the CRCs (two different flavours, just for confusion)
//-----------------------------------------------------------------------------
-#include "proxmark3.h"
+#include "../include/proxmark3.h"
#include <stdint.h>
#include <stdlib.h>
//#include "iso15693tools.h"
// LEFIC's obfuscation function
//-----------------------------------------------------------------------------
-#include "legic_prng.h"
+#include "../include/legic_prng.h"
struct lfsr {
uint8_t a;
--- /dev/null
+cp armsrc/obj/*.elf /z
+cp armsrc/obj/*.s19 /z
+cp bootrom/obj/*.elf /z
+cp bootrom/obj/*.s19 /z
+++ /dev/null
-//-----------------------------------------------------------------------------
-// This code is licensed to you under the terms of the GNU GPL, version 2 or,
-// at your option, any later version. See the LICENSE.txt file for the text of
-// the license.
-//-----------------------------------------------------------------------------
-// Generic CRC calculation code.
-//-----------------------------------------------------------------------------
-
-#ifndef __CRC_H
-#define __CRC_H
-
-#include <stdint.h>
-
-typedef struct crc {
- uint32_t state;
- int order;
- uint32_t polynom;
- uint32_t initial_value;
- uint32_t final_xor;
- uint32_t mask;
-} crc_t;
-
-/* Initialize a crc structure. order is the order of the polynom, e.g. 32 for a CRC-32
- * polynom is the CRC polynom. initial_value is the initial value of a clean state.
- * final_xor is XORed onto the state before returning it from crc_result(). */
-extern void crc_init(crc_t *crc, int order, uint32_t polynom, uint32_t initial_value, uint32_t final_xor);
-
-/* Update the crc state. data is the data of length data_width bits (only the the
- * data_width lower-most bits are used).
- */
-extern void crc_update(crc_t *crc, uint32_t data, int data_width);
-
-/* Clean the crc state, e.g. reset it to initial_value */
-extern void crc_clear(crc_t *crc);
-
-/* Get the result of the crc calculation */
-extern uint32_t crc_finish(crc_t *crc);
-
-/* Static initialization of a crc structure */
-#define CRC_INITIALIZER(_order, _polynom, _initial_value, _final_xor) { \
- .state = ((_initial_value) & ((1L<<(_order))-1)), \
- .order = (_order), \
- .polynom = (_polynom), \
- .initial_value = (_initial_value), \
- .final_xor = (_final_xor), \
- .mask = ((1L<<(_order))-1) }
-
-#endif /* __CRC_H */
--- /dev/null
+//-----------------------------------------------------------------------------
+// This code is licensed to you under the terms of the GNU GPL, version 2 or,
+// at your option, any later version. See the LICENSE.txt file for the text of
+// the license.
+//-----------------------------------------------------------------------------
+// Generic CRC calculation code.
+//-----------------------------------------------------------------------------
+
+#ifndef __CRC_H
+#define __CRC_H
+
+#include <stdint.h>
+
+typedef struct crc {
+ uint32_t state;
+ int order;
+ uint32_t polynom;
+ uint32_t initial_value;
+ uint32_t final_xor;
+ uint32_t mask;
+} crc_t;
+
+/* Initialize a crc structure. order is the order of the polynom, e.g. 32 for a CRC-32
+ * polynom is the CRC polynom. initial_value is the initial value of a clean state.
+ * final_xor is XORed onto the state before returning it from crc_result(). */
+extern void crc_init(crc_t *crc, int order, uint32_t polynom, uint32_t initial_value, uint32_t final_xor);
+
+/* Update the crc state. data is the data of length data_width bits (only the the
+ * data_width lower-most bits are used).
+ */
+extern void crc_update(crc_t *crc, uint32_t data, int data_width);
+
+/* Clean the crc state, e.g. reset it to initial_value */
+extern void crc_clear(crc_t *crc);
+
+/* Get the result of the crc calculation */
+extern uint32_t crc_finish(crc_t *crc);
+
+/* Static initialization of a crc structure */
+#define CRC_INITIALIZER(_order, _polynom, _initial_value, _final_xor) { \
+ .state = ((_initial_value) & ((1L<<(_order))-1)), \
+ .order = (_order), \
+ .polynom = (_polynom), \
+ .initial_value = (_initial_value), \
+ .final_xor = (_final_xor), \
+ .mask = ((1L<<(_order))-1) }
+
+#endif /* __CRC_H */
#ifndef _MIFARE_H_
#define _MIFARE_H_
-#include "common.h"
+#include "../include/common.h"
//-----------------------------------------------------------------------------
// ISO 14443A
#define CMD_READER_LEGIC_RF 0x0388
#define CMD_WRITER_LEGIC_RF 0x0389
#define CMD_EPA_PACE_COLLECT_NONCE 0x038A
+//#define CMD_EPA_ 0x038B
#define CMD_SNOOP_ICLASS 0x0392
#define CMD_SIMULATE_TAG_ICLASS 0x0393
#define CMD_READER_ICLASS 0x0394
-#define CMD_READER_ICLASS_REPLAY 0x0395
+#define CMD_READER_ICLASS_REPLAY 0x0395
#define CMD_ICLASS_ISO14443A_WRITE 0x0397
#define CMD_ICLASS_EML_MEMSET 0x0398
#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
//Iclass reader flags
-#define FLAG_ICLASS_READER_ONLY_ONCE 0x01
+#define FLAG_ICLASS_READER_ONLY_ONCE 0x01
#define FLAG_ICLASS_READER_GET_CC 0x02
my $clean = 2;
my @compiletime = gmtime();
-my $fullgitinfo = $gitbranch . '/' . $gitversion;
+my $fullgitinfo = 'iceman' . $gitbranch . '/' . $gitversion;
$fullgitinfo =~ s/(\s)//g;