+The iceman fork.
+
NOTICE:
-(2014-03-26)
-This is now the official Proxmark repository!
-INTRODUCTION:
+The official Proxmark repository is found here: https://github.com/Proxmark/proxmark3
-The proxmark3 is a powerful general purpose RFID tool, the size of a deck
-of cards, designed to snoop, listen and emulate everything from
-Low Frequency (125kHz) to High Frequency (13.56MHz) tags.
-This repository contains enough software, logic (for the FPGA), and design
-documentation for the hardware that you could, at least in theory,
-do something useful with a proxmark3.
+NEWS:
-RESOURCES:
+Whats in this fork? I have scraped the web for different enhancements to the PM3 source code and not all of them ever found their way to the master branch.
+Among the stuff is
- * This repository!
- https://github.com/Proxmark/proxmark3
-
- * The Wiki
- https://github.com/Proxmark/proxmark3/wiki
-
- * The GitHub page
- http://proxmark.github.io/proxmark3/
-
- * The Forum
- http://www.proxmark.org/forum
-
- * The IRC chanel
- irc.freenode.org #proxmark3
- -or-
- http://webchat.freenode.net/?channels=#proxmark3
-
-DEVELOPMENT:
+ * Jonor's hf 14a raw timing patch
+ * Piwi's updates. (usually gets into the master)
+ * Holiman's iclass, (usually gets into the master)
+ * Marshmellow's LF fixes
+ * Midnitesnake's Ultralight, Ultralight-c enhancements
+ * Izsh's lf peak modification / iir-filtering
+ * Aspers's tips and tricks from inside the PM3-gui-tool, settings.xml and other stuff.
+ * My own desfire, Ultralight extras, LF T55xx enhancements, bugs fixes (filelength, hf mf commands ), TNP3xxx lua scripts, Awid26, skidata scripts (will come)
+ * other obscure patches like for the sammy-mode, (offline you know), tagidentifications, defaultkeys.
+
+Give me a hint, and I'll see if I can't merge in the stuff you have.
-The tools required to build or run the project will vary depending on
-your operating system. Please refer to the Wiki for details.
+I don't actually know how to make small pull-request to github :( and that is the number one reason for me not pushing a lot of things back to the PM3 master.
+
+PM3 GUI:
- * https://github.com/Proxmark/proxmark3/wiki
+I do tend to rename and move stuff around, the official PM3-GUI from Gaucho will not work so well. *sorry*
+
+
+DEVELOPMENT:
-OBTAINING HARDWARE:
+This fork is adjusted to compile on windows/mingw environment with Qt5.3.1 & GCC 4.8
+For people with linux you will need to patch some source code and some small change to one makefile. If you are lazy, you google the forum and find asper's or holimans makefile or you find your solution below.
+
+Common errors linux/macOS finds
+Error:
+ * loclass/fileutils.c:15:2: warning: implicit declaration of function \91_stat\92 [-Wimplicit-function-declaration]
+Solution:
+ * Remove the "unscore" sign. In linux you use without underscore, in windows you need a underscore.
+
+Error:
+ * \client\makefile the parameter -lgdi32
+Solution:
+ * Remove parameter.
+
+Error:
+ * Using older Qt4.6 gives compilation errors.
+Solution
+ * Upgrade to Qt5.3.1
+ OR
+ * Change these two line in \client\makefile
+ CXXFLAGS = -I$(QTDIR)/include -I$(QTDIR)/include/QtCore -I$(QTDIR)/include/QtGui -I$(QTDIR)/include/QtWidgets -I/mingw/include
+ QTLDLIBS = -L$(QTDIR)/lib -lQt5Core -lQt5Gui -lQt5Widgets
+
+ TO
+
+ CXXFLAGS = -I$(QTDIR)/include -I$(QTDIR)/include/QtCore -I$(QTDIR)/include/QtGui
+ QTLDLIBS = -L$(QTDIR)/lib -lQtCore4 -lQtGui4
+
+
+An old Qt4 version makefile is found here: http://www.icesql.se/proxmark3/code/linuxmakefile.txt but this one doesn't have all new files in it. So I don't recommend it.
The Proxmark 3 is available for purchase (assembled and tested) from the
following locations:
- * http://proxmark3.com/
- * http://www.xfpga.com/
-
-Most of the ultra-low-volume contract assemblers could put
-something like this together with a reasonable yield. A run of around
-a dozen units is probably cost-effective. The BOM includes (possibly-
-outdated) component pricing, and everything is available from Digikey
-and the usual distributors.
-
-If you've never assembled a modern circuit board by hand, then this is
-not a good place to start. Some of the components (e.g. the crystals)
-must not be assembled with a soldering iron, and require hot air.
-
-The schematics are included; the component values given are not
-necessarily correct for all situations, but it should be possible to do
-nearly anything you would want with appropriate population options.
-
-The printed circuit board artwork is also available, as Gerbers and an
-Excellon drill file.
-
-
-LICENSING:
-
-This program is free software; you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation; either version 2 of the License, or
-(at your option) any later version.
-
-This program is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with this program; if not, write to the Free Software
-Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
-
-
-Jonathan Westhues
-user jwesthues, at host cq.cx
-May 2007, Cambridge MA
+January 2015, Sweden
+iceman at host iuse.se
\ No newline at end of file
traceLen += iLen;
// parity bytes
- if (parity != NULL && iLen != 0) {
- memcpy(trace + traceLen, parity, num_paritybytes);
+ if (iLen != 0) {
+ if (parity != NULL) {
+ memcpy(trace + traceLen, parity, num_paritybytes);
+ } else {
+ memset(trace + traceLen, 0x00, num_paritybytes);
+ }
}
traceLen += num_paritybytes;
- if(traceLen +4 < max_traceLen)
- { //If it hadn't been cleared, for whatever reason..
- memset(trace+traceLen,0x44, 4);
- }
-
return TRUE;
}
+
+
int LogTraceHitag(const uint8_t * btBytes, int iBits, int iSamples, uint32_t dwParity, int readerToTag)
{
/**
return TRUE;
}
+
+
// Emulator memory
uint8_t emlSet(uint8_t *data, uint32_t offset, uint32_t length){
uint8_t* mem = BigBuf_get_EM_addr();
// LCD code
//-----------------------------------------------------------------------------
-#include "proxmark3.h"
+#include "../include/proxmark3.h"
#include "apps.h"
#include "LCD.h"
#include "fonts.h"
SRC_ISO15693 = iso15693.c iso15693tools.c
SRC_ISO14443a = epa.c iso14443a.c mifareutil.c mifarecmd.c mifaresniff.c
SRC_ISO14443b = iso14443.c
-SRC_CRAPTO1 = crapto1.c crypto1.c des.c aes.c
+SRC_CRAPTO1 = crapto1.c crypto1.c des.c aes.c desfire_key.c desfire_crypto.c mifaredesfire.c
SRC_CRC = iso14443crc.c crc.c crc16.c crc32.c
THUMBSRC = start.c \
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 "proxmark3.h"
+#include "../common/usb_cdc.h"
+#include "../common/cmd.h"
+#include "../include/proxmark3.h"
+#include "../include/hitag2.h"
#include "apps.h"
#include "util.h"
#include "printf.h"
#include "string.h"
-
#include <stdarg.h>
-
#include "legicrf.h"
-#include <hitag2.h>
#include "lfsampling.h"
#include "BigBuf.h"
+
#ifdef WITH_LCD
#include "LCD.h"
#endif
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
#ifdef WITH_ISO14443a
case CMD_SNOOP_ISO_14443a:
- SnoopIso14443a(c->arg[0]);
+ SniffIso14443a(c->arg[0]);
break;
case CMD_READER_ISO_14443a:
ReaderIso14443a(c);
EPA_PACE_Collect_Nonce(c);
break;
+ // case CMD_EPA_:
+ // EpaFoo(c);
+ // break;
+
case CMD_READER_MIFARE:
- ReaderMifare(c->arg[0]);
+ ReaderMifare(c->arg[0]);
break;
case CMD_MIFARE_READBL:
MifareReadBlock(c->arg[0], c->arg[1], c->arg[2], c->d.asBytes);
break;
case CMD_MIFAREU_WRITEBL:
MifareUWriteBlock_Special(c->arg[0], c->d.asBytes);
+ MifareUWriteBlock_Special(c->arg[0], c->arg[1], c->d.asBytes);
break;
case CMD_MIFARE_NESTED:
MifareNested(c->arg[0], c->arg[1], c->arg[2], c->d.asBytes);
SniffMifare(c->arg[0]);
break;
+ //mifare desfire
+ case CMD_MIFARE_DESFIRE_READBL: break;
+ case CMD_MIFARE_DESFIRE_WRITEBL: break;
+ case CMD_MIFARE_DESFIRE_AUTH1:
+ MifareDES_Auth1(c->arg[0], c->arg[1], c->arg[2], c->d.asBytes);
+ break;
+ case CMD_MIFARE_DESFIRE_AUTH2:
+ //MifareDES_Auth2(c->arg[0],c->d.asBytes);
+ break;
+ case CMD_MIFARE_DES_READER:
+ //readermifaredes(c->arg[0], c->arg[1], c->d.asBytes);
+ break;
+ case CMD_MIFARE_DESFIRE_INFO:
+ MifareDesfireGetInformation();
+ break;
+ case CMD_MIFARE_DESFIRE:
+ MifareSendCommand(c->arg[0], c->arg[1], c->d.asBytes);
+ break;
+
+ case CMD_MIFARE_COLLECT_NONCES:
+ MifareCollectNonces(c->arg[0], c->arg[1]);
+ break;
#endif
#ifdef WITH_ICLASS
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 "../common/lfdemod.h"
#include "BigBuf.h"
+#include "../include/hitag2.h"
+#include "../include/mifare.h"
+//#include "des.h"
+//#include "aes.h"
+#include "desfire.h"
+
extern const uint8_t OddByteParity[256];
extern int rsamples; // = 0;
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);
void SendRawCommand14443B(uint32_t, uint32_t, uint8_t, uint8_t[]);
/// iso14443a.h
-void RAMFUNC SnoopIso14443a(uint8_t param);
+void RAMFUNC SniffIso14443a(uint8_t param);
void SimulateIso14443aTag(int tagType, int uid_1st, int uid_2nd, byte_t* data);
void ReaderIso14443a(UsbCommand * c);
// Also used in iclass.c
void MifareReadSector(uint8_t arg0, uint8_t arg1, uint8_t arg2, uint8_t *datain);
void MifareWriteBlock(uint8_t arg0, uint8_t arg1, uint8_t arg2, uint8_t *datain);
void MifareUWriteBlock(uint8_t arg0,uint8_t *datain);
-void MifareUWriteBlock_Special(uint8_t arg0,uint8_t *datain);
+void MifareUWriteBlock_Special(uint8_t arg0, uint8_t arg1, uint8_t *datain);
void MifareNested(uint32_t arg0, uint32_t arg1, uint32_t arg2, uint8_t *datain);
void MifareChkKeys(uint8_t arg0, uint8_t arg1, uint8_t arg2, uint8_t *datain);
void Mifare1ksim(uint8_t arg0, uint8_t arg1, uint8_t arg2, uint8_t *datain);
void MifareCIdent(); // is "magic chinese" card?
void MifareUSetPwd(uint8_t arg0, uint8_t *datain);
+void MifareCollectNonces(uint32_t arg0, uint32_t arg1);
+
//desfire
void Mifare_DES_Auth1(uint8_t arg0,uint8_t *datain);
void Mifare_DES_Auth2(uint32_t arg0, uint8_t *datain);
+// desfire_crypto.h
+void *mifare_cryto_preprocess_data (desfiretag_t tag, void *data, size_t *nbytes, off_t offset, int communication_settings);
+void *mifare_cryto_postprocess_data (desfiretag_t tag, void *data, ssize_t *nbytes, int communication_settings);
+void mifare_cypher_single_block (desfirekey_t key, uint8_t *data, uint8_t *ivect, MifareCryptoDirection direction, MifareCryptoOperation operation, size_t block_size);
+void mifare_cypher_blocks_chained (desfiretag_t tag, desfirekey_t key, uint8_t *ivect, uint8_t *data, size_t data_size, MifareCryptoDirection direction, MifareCryptoOperation operation);
+size_t key_block_size (const desfirekey_t key);
+size_t padded_data_length (const size_t nbytes, const size_t block_size);
+size_t maced_data_length (const desfirekey_t key, const size_t nbytes);
+size_t enciphered_data_length (const desfiretag_t tag, const size_t nbytes, int communication_settings);
+void cmac_generate_subkeys (desfirekey_t key);
+void cmac (const desfirekey_t key, uint8_t *ivect, const uint8_t *data, size_t len, uint8_t *cmac);
/// iso15693.h
/* 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
des_dec(out, out, (uint8_t*)key + 0);
}
-void tdes_2key_enc(void* out, const void* in, size_t length, const void* key, unsigned char iv[8]){
+ void tdes_2key_enc(void* out, const void* in, size_t length, const void* key, unsigned char iv[8]){
if( length % 8 ) return;
-
+
uint8_t i;
uint8_t* tin = (uint8_t*) in;
uint8_t* tout = (uint8_t*) out;
while( length > 0 )
{
- for ( i = 0; i < 8; i++ )
- tout[i] = (unsigned char)(tin[i] ^ iv[i]);
-
+ for( i = 0; i < 8; i++ )
+ tout[i] = (unsigned char)( tin[i] ^ iv[i] );
+
des_enc(tout, tin, (uint8_t*)key + 0);
des_dec(tout, tout, (uint8_t*)key + 8);
des_enc(tout, tout, (uint8_t*)key + 0);
- memcpy(iv, tout, 8);
-
+ memcpy( iv, tout, 8 );
+
tin += 8;
tout += 8;
length -= 8;
}
-}
-
-void tdes_2key_dec(void* out, const void* in, size_t length, const void* key, unsigned char iv[8]){
+ }
+
+ void tdes_2key_dec(void* out, const void* in, size_t length, const void* key, unsigned char iv[8]){
if( length % 8 ) return;
uint8_t i;
unsigned char temp[8];
+
uint8_t* tin = (uint8_t*) in;
uint8_t* tout = (uint8_t*) out;
while( length > 0 )
{
- memcpy(temp, tin, 8);
-
+ memcpy( temp, tin, 8 );
+
des_dec(tout, tin, (uint8_t*)key + 0);
des_enc(tout, tout, (uint8_t*)key + 8);
des_dec(tout, tout, (uint8_t*)key + 0);
- for (i = 0; i < 8; i++)
- tout[i] = (unsigned char)(tout[i] ^ iv[i]);
+ for( i = 0; i < 8; i++ )
+ tout[i] = (unsigned char)( tout[i] ^ iv[i] );
- memcpy(iv, temp, 8);
+ memcpy( iv, temp, 8 );
tin += 8;
tout += 8;
length -= 8;
}
-}
-
+ }
/******************************************************************************/
* \param key pointer to the key (192 bit = 24 byte)
*/
void tdes_dec(void* out, const void* in, const void* key);
+
+ void tdes_2key_enc(void* out, const void* in, size_t length, const void* key, unsigned char iv[8]);
+ void tdes_2key_dec(void* out, const void* in, size_t length, const void* key, unsigned char iv[8]);
void tdes_2key_enc(void* out, const void* in, size_t length, const void* key, unsigned char iv[8]);
void tdes_2key_dec(void* out, const void* in, size_t length, const void* key, unsigned char iv[8]);
--- /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)
//-----------------------------------------------------------------------------
void RAMFUNC SnoopIClass(void)
{
-
-
// We won't start recording the frames that we acquire until we trigger;
// a good trigger condition to get started is probably when we see a
// response from the tag.
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!!
uint8_t card_data[6 * 8]={0};
memset(card_data, 0xFF, sizeof(card_data));
- uint8_t last_csn[8]={0};
+ uint8_t last_csn[8]={0};
//Read conf block CRC(0x01) => 0xfa 0x22
uint8_t readConf[] = { ICLASS_CMD_READ_OR_IDENTIFY,0x01, 0xfa, 0x22};
uint8_t readAA[] = { ICLASS_CMD_READ_OR_IDENTIFY,0x05, 0xde, 0x64};
- int read_status= 0;
+ int read_status= 0;
uint8_t result_status = 0;
- bool abort_after_read = arg0 & FLAG_ICLASS_READER_ONLY_ONCE;
+ bool abort_after_read = arg0 & FLAG_ICLASS_READER_ONLY_ONCE;
bool try_once = arg0 & FLAG_ICLASS_READER_ONE_TRY;
set_tracing(TRUE);
- setupIclassReader();
+ setupIclassReader();
uint16_t tryCnt=0;
- while(!BUTTON_PRESS())
- {
+ while(!BUTTON_PRESS())
+ {
if (try_once && tryCnt > 5) break;
tryCnt++;
if(!tracing) {
//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 caller requires that we get CC, continue until we got it
if( (arg0 & read_status & FLAG_ICLASS_READER_CC) || !(arg0 & FLAG_ICLASS_READER_CC))
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);
}
}
LED_B_OFF();
- }
+ }
cmd_send(CMD_ACK,0,0,0,card_data, 0);
LED_A_OFF();
}
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);
#include "util.h"
#include "string.h"
#include "cmd.h"
-
#include "iso14443crc.h"
#include "iso14443a.h"
#include "crapto1.h"
ComputeCrc14443(CRC_14443_A,data,len,data+len,data+len+1);
}
+void AppendCrc14443b(uint8_t* data, int len)
+{
+ ComputeCrc14443(CRC_14443_B,data,len,data+len,data+len+1);
+}
+
+
//=============================================================================
// ISO 14443 Type A - Miller decoder
//=============================================================================
static tUart Uart;
// Lookup-Table to decide if 4 raw bits are a modulation.
-// We accept two or three consecutive "0" in any position with the rest "1"
+// We accept the following:
+// 0001 - a 3 tick wide pause
+// 0011 - a 2 tick wide pause, or a three tick wide pause shifted left
+// 0111 - a 2 tick wide pause shifted left
+// 1001 - a 2 tick wide pause shifted right
const bool Mod_Miller_LUT[] = {
- TRUE, TRUE, FALSE, TRUE, FALSE, FALSE, FALSE, FALSE,
- TRUE, TRUE, FALSE, FALSE, TRUE, FALSE, FALSE, FALSE
+ FALSE, TRUE, FALSE, TRUE, FALSE, FALSE, FALSE, TRUE,
+ FALSE, TRUE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE
};
-#define IsMillerModulationNibble1(b) (Mod_Miller_LUT[(b & 0x00F0) >> 4])
-#define IsMillerModulationNibble2(b) (Mod_Miller_LUT[(b & 0x000F)])
+#define IsMillerModulationNibble1(b) (Mod_Miller_LUT[(b & 0x000000F0) >> 4])
+#define IsMillerModulationNibble2(b) (Mod_Miller_LUT[(b & 0x0000000F)])
void UartReset()
{
Uart.parityLen = 0; // number of decoded parity bytes
Uart.shiftReg = 0; // shiftreg to hold decoded data bits
Uart.parityBits = 0; // holds 8 parity bits
- Uart.twoBits = 0x0000; // buffer for 2 Bits
- Uart.highCnt = 0;
Uart.startTime = 0;
Uart.endTime = 0;
+
+ Uart.byteCntMax = 0;
+ Uart.posCnt = 0;
+ Uart.syncBit = 9999;
}
void UartInit(uint8_t *data, uint8_t *parity)
{
Uart.output = data;
Uart.parity = parity;
+ Uart.fourBits = 0x00000000; // clear the buffer for 4 Bits
UartReset();
}
static RAMFUNC bool MillerDecoding(uint8_t bit, uint32_t non_real_time)
{
- Uart.twoBits = (Uart.twoBits << 8) | bit;
+ Uart.fourBits = (Uart.fourBits << 8) | bit;
if (Uart.state == STATE_UNSYNCD) { // not yet synced
- if (Uart.highCnt < 2) { // wait for a stable unmodulated signal
- if (Uart.twoBits == 0xffff) {
- Uart.highCnt++;
- } else {
- Uart.highCnt = 0;
- }
- } else {
- Uart.syncBit = 0xFFFF; // not set
- // we look for a ...1111111100x11111xxxxxx pattern (the start bit)
- if ((Uart.twoBits & 0xDF00) == 0x1F00) Uart.syncBit = 8; // mask is 11x11111 xxxxxxxx,
- // check for 00x11111 xxxxxxxx
- else if ((Uart.twoBits & 0xEF80) == 0x8F80) Uart.syncBit = 7; // both masks shifted right one bit, left padded with '1'
- else if ((Uart.twoBits & 0xF7C0) == 0xC7C0) Uart.syncBit = 6; // ...
- else if ((Uart.twoBits & 0xFBE0) == 0xE3E0) Uart.syncBit = 5;
- else if ((Uart.twoBits & 0xFDF0) == 0xF1F0) Uart.syncBit = 4;
- else if ((Uart.twoBits & 0xFEF8) == 0xF8F8) Uart.syncBit = 3;
- else if ((Uart.twoBits & 0xFF7C) == 0xFC7C) Uart.syncBit = 2;
- else if ((Uart.twoBits & 0xFFBE) == 0xFE3E) Uart.syncBit = 1;
- if (Uart.syncBit != 0xFFFF) { // found a sync bit
+ Uart.syncBit = 9999; // not set
+
+ // 00x11111 2|3 ticks pause followed by 6|5 ticks unmodulated Sequence Z (a "0" or "start of communication")
+ // 11111111 8 ticks unmodulation Sequence Y (a "0" or "end of communication" or "no information")
+ // 111100x1 4 ticks unmodulated followed by 2|3 ticks pause Sequence X (a "1")
+
+ // The start bit is one ore more Sequence Y followed by a Sequence Z (... 11111111 00x11111). We need to distinguish from
+ // Sequence X followed by Sequence Y followed by Sequence Z (111100x1 11111111 00x11111)
+ // we therefore look for a ...xx1111 11111111 00x11111xxxxxx... pattern
+ // (12 '1's followed by 2 '0's, eventually followed by another '0', followed by 5 '1's)
+ //
+#define ISO14443A_STARTBIT_MASK 0x07FFEF80 // mask is 00001111 11111111 1110 1111 10000000
+#define ISO14443A_STARTBIT_PATTERN 0x07FF8F80 // pattern is 00001111 11111111 1000 1111 10000000
+
+ if ((Uart.fourBits & (ISO14443A_STARTBIT_MASK >> 0)) == ISO14443A_STARTBIT_PATTERN >> 0) Uart.syncBit = 7;
+ else if ((Uart.fourBits & (ISO14443A_STARTBIT_MASK >> 1)) == ISO14443A_STARTBIT_PATTERN >> 1) Uart.syncBit = 6;
+ else if ((Uart.fourBits & (ISO14443A_STARTBIT_MASK >> 2)) == ISO14443A_STARTBIT_PATTERN >> 2) Uart.syncBit = 5;
+ else if ((Uart.fourBits & (ISO14443A_STARTBIT_MASK >> 3)) == ISO14443A_STARTBIT_PATTERN >> 3) Uart.syncBit = 4;
+ else if ((Uart.fourBits & (ISO14443A_STARTBIT_MASK >> 4)) == ISO14443A_STARTBIT_PATTERN >> 4) Uart.syncBit = 3;
+ else if ((Uart.fourBits & (ISO14443A_STARTBIT_MASK >> 5)) == ISO14443A_STARTBIT_PATTERN >> 5) Uart.syncBit = 2;
+ else if ((Uart.fourBits & (ISO14443A_STARTBIT_MASK >> 6)) == ISO14443A_STARTBIT_PATTERN >> 6) Uart.syncBit = 1;
+ else if ((Uart.fourBits & (ISO14443A_STARTBIT_MASK >> 7)) == ISO14443A_STARTBIT_PATTERN >> 7) Uart.syncBit = 0;
+
+ if (Uart.syncBit != 9999) { // found a sync bit
Uart.startTime = non_real_time?non_real_time:(GetCountSspClk() & 0xfffffff8);
Uart.startTime -= Uart.syncBit;
Uart.endTime = Uart.startTime;
Uart.state = STATE_START_OF_COMMUNICATION;
}
- }
} else {
- if (IsMillerModulationNibble1(Uart.twoBits >> Uart.syncBit)) {
- if (IsMillerModulationNibble2(Uart.twoBits >> Uart.syncBit)) { // Modulation in both halves - error
+ if (IsMillerModulationNibble1(Uart.fourBits >> Uart.syncBit)) {
+ if (IsMillerModulationNibble2(Uart.fourBits >> Uart.syncBit)) { // Modulation in both halves - error
UartReset();
} else { // Modulation in first half = Sequence Z = logic "0"
if (Uart.state == STATE_MILLER_X) { // error - must not follow after X
}
}
} else {
- if (IsMillerModulationNibble2(Uart.twoBits >> Uart.syncBit)) { // Modulation second half = Sequence X = logic "1"
+ if (IsMillerModulationNibble2(Uart.fourBits >> Uart.syncBit)) { // Modulation second half = Sequence X = logic "1"
Uart.bitCount++;
Uart.shiftReg = (Uart.shiftReg >> 1) | 0x100; // add a 1 to the shiftreg
Uart.state = STATE_MILLER_X;
return TRUE; // we are finished with decoding the raw data sequence
} else {
UartReset(); // Nothing received - start over
- Uart.highCnt = 1;
}
}
if (Uart.state == STATE_START_OF_COMMUNICATION) { // error - must not follow directly after SOC
UartReset();
- Uart.highCnt = 1;
} else { // a logic "0"
Uart.bitCount++;
Uart.shiftReg = (Uart.shiftReg >> 1); // add a 0 to the shiftreg
Demod.highCnt = 0;
Demod.startTime = 0;
Demod.endTime = 0;
+
+ //
+ Demod.bitCount = 0;
+ Demod.syncBit = 0xFFFF;
+ Demod.samples = 0;
}
void DemodInit(uint8_t *data, uint8_t *parity)
}
}
}
-
}
-
return FALSE; // not finished yet, need more data
}
// triggering so that we start recording at the point that the tag is moved
// near the reader.
//-----------------------------------------------------------------------------
-void RAMFUNC SnoopIso14443a(uint8_t param) {
+void RAMFUNC SniffIso14443a(uint8_t param) {
// param:
// bit 0 - trigger from first card answer
// bit 1 - trigger from first reader 7-bit request
// And ready to receive another response.
DemodReset();
+ // And reset the Miller decoder including itS (now outdated) input buffer
+ UartInit(receivedCmd, receivedCmdPar);
+
LED_C_OFF();
}
TagIsActive = (Demod.state != DEMOD_UNSYNCD);
// Main loop of simulated tag: receive commands from reader, decide what
// response to send, and send it.
//-----------------------------------------------------------------------------
-void SimulateIso14443aTag(int tagType, int uid_1st, int uid_2nd, byte_t* data)
+void SimulateIso14443aTag(int tagType, int flags, int uid_2nd, byte_t* data)
{
+
+ //Here, we collect UID,NT,AR,NR,UID2,NT2,AR2,NR2
+ // This can be used in a reader-only attack.
+ // (it can also be retrieved via 'hf 14a list', but hey...
+ uint32_t ar_nr_responses[] = {0,0,0,0,0,0,0,0,0,0};
+ uint8_t ar_nr_collected = 0;
+
uint8_t sak;
// The first response contains the ATQA (note: bytes are transmitted in reverse order).
response1[0] = 0x01;
response1[1] = 0x0f;
sak = 0x01;
- } break;
+ } break;
+ case 6: { // MIFARE Mini
+ // Says: I am a Mifare Mini, 320b
+ response1[0] = 0x44;
+ response1[1] = 0x00;
+ sak = 0x09;
+ } break;
default: {
Dbprintf("Error: unkown tagtype (%d)",tagType);
return;
// Check if the uid uses the (optional) part
uint8_t response2a[5] = {0x00};
- if (uid_2nd) {
+ if (flags & FLAG_7B_UID_IN_DATA) {
response2[0] = 0x88;
- num_to_bytes(uid_1st,3,response2+1);
- num_to_bytes(uid_2nd,4,response2a);
+ response2[1] = data[0];
+ response2[2] = data[1];
+ response2[3] = data[2];
+
+ response2a[0] = data[3];
+ response2a[1] = data[4];
+ response2a[2] = data[5];
+ response2a[3] = data[7];
response2a[4] = response2a[0] ^ response2a[1] ^ response2a[2] ^ response2a[3];
// Configure the ATQA and SAK accordingly
response1[0] |= 0x40;
sak |= 0x04;
} else {
- num_to_bytes(uid_1st,4,response2);
+ memcpy(response2, data, 4);
+ //num_to_bytes(uid_1st,4,response2);
// Configure the ATQA and SAK accordingly
response1[0] &= 0xBF;
sak &= 0xFB;
if (tracing) {
LogTrace(receivedCmd, Uart.len, Uart.startTime*16 - DELAY_AIR2ARM_AS_TAG, Uart.endTime*16 - DELAY_AIR2ARM_AS_TAG, Uart.parity, TRUE);
}
+ uint32_t nonce = bytes_to_num(response5,4);
uint32_t nr = bytes_to_num(receivedCmd,4);
uint32_t ar = bytes_to_num(receivedCmd+4,4);
- Dbprintf("Auth attempt {nr}{ar}: %08x %08x",nr,ar);
+ //Dbprintf("Auth attempt {nonce}{nr}{ar}: %08x %08x %08x", nonce, nr, ar);
+
+ if(flags & FLAG_NR_AR_ATTACK )
+ {
+ if(ar_nr_collected < 2){
+ // Avoid duplicates... probably not necessary, nr should vary.
+ //if(ar_nr_responses[3] != nr){
+ ar_nr_responses[ar_nr_collected*5] = 0;
+ ar_nr_responses[ar_nr_collected*5+1] = 0;
+ ar_nr_responses[ar_nr_collected*5+2] = nonce;
+ ar_nr_responses[ar_nr_collected*5+3] = nr;
+ ar_nr_responses[ar_nr_collected*5+4] = ar;
+ ar_nr_collected++;
+ //}
+ }
+
+ if(ar_nr_collected > 1 ) {
+
+ if (MF_DBGLEVEL >= 2) {
+ Dbprintf("Collected two pairs of AR/NR which can be used to extract keys from reader:");
+ Dbprintf("../tools/mfkey/mfkey32 %07x%08x %08x %08x %08x %08x %08x",
+ ar_nr_responses[0], // UID1
+ ar_nr_responses[1], // UID2
+ ar_nr_responses[2], // NT
+ ar_nr_responses[3], // AR1
+ ar_nr_responses[4], // NR1
+ ar_nr_responses[8], // AR2
+ ar_nr_responses[9] // NR2
+ );
+ }
+ uint8_t len = ar_nr_collected*5*4;
+ cmd_send(CMD_ACK,CMD_SIMULATE_MIFARE_CARD,len,0,&ar_nr_responses,len);
+ ar_nr_collected = 0;
+ memset(ar_nr_responses, 0x00, len);
+ Dbprintf("ICE");
+ }
+ }
} else {
// Check for ISO 14443A-4 compliant commands, look at left nibble
switch (receivedCmd[0]) {
}
}
+ FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
+
Dbprintf("%x %x %x", happened, happened2, cmdsRecvd);
LED_A_OFF();
BigBuf_free_keep_EM();
}
// Only transmit parity bit if we transmitted a complete byte
- if (j == 8) {
+ if (j == 8 && parity != NULL) {
// Get the parity bit
if (parity[i>>3] & (0x80 >> (i&0x0007))) {
// Sequence X
//-----------------------------------------------------------------------------
static int GetIso14443aAnswerFromTag(uint8_t *receivedResponse, uint8_t *receivedResponsePar, uint16_t offset)
{
- uint32_t c;
+ uint32_t c = 0x00;
// Set FPGA mode to "reader listen mode", no modulation (listen
// only, since we are receiving, not transmitting).
// clear RXRDY:
uint8_t b = (uint8_t)AT91C_BASE_SSC->SSC_RHR;
- c = 0;
for(;;) {
WDT_HIT();
}
}
+
void ReaderTransmitBitsPar(uint8_t* frame, uint16_t bits, uint8_t *par, uint32_t *timing)
{
CodeIso14443aBitsAsReaderPar(frame, bits, par);
}
}
+
void ReaderTransmitPar(uint8_t* frame, uint16_t len, uint8_t *par, uint32_t *timing)
{
ReaderTransmitBitsPar(frame, len*8, par, timing);
}
+
void ReaderTransmitBits(uint8_t* frame, uint16_t len, uint32_t *timing)
{
// Generate parity and redirect
ReaderTransmitBitsPar(frame, len, par, timing);
}
+
void ReaderTransmit(uint8_t* frame, uint16_t len, uint32_t *timing)
{
// Generate parity and redirect
memset(uid_ptr,0,10);
}
+ // check for proprietary anticollision:
+ if ((resp[0] & 0x1F) == 0) {
+ return 3;
+ }
+
// OK we will select at least at cascade 1, lets see if first byte of UID was 0x88 in
// which case we need to make a cascade 2 request and select - this is a long UID
// While the UID is not complete, the 3nd bit (from the right) is set in the SAK.
DemodReset();
UartReset();
NextTransferTime = 2*DELAY_ARM2AIR_AS_READER;
- iso14a_set_timeout(1050); // 10ms default
+ iso14a_set_timeout(10*106); // 10ms default
}
int iso14_apdu(uint8_t *cmd, uint16_t cmd_len, void *data) {
if(param & ISO14A_RAW) {
if(param & ISO14A_APPEND_CRC) {
- AppendCrc14443a(cmd,len);
+ if(param & ISO14A_TOPAZMODE) {
+ AppendCrc14443b(cmd,len);
+ } else {
+ AppendCrc14443a(cmd,len);
+ }
len += 2;
if (lenbits) lenbits += 16;
}
- if(lenbits>0) {
+ if(lenbits>0) { // want to send a specific number of bits (e.g. short commands)
+ if(param & ISO14A_TOPAZMODE) {
+ int bits_to_send = lenbits;
+ uint16_t i = 0;
+ ReaderTransmitBitsPar(&cmd[i++], MIN(bits_to_send, 7), NULL, NULL); // first byte is always short (7bits) and no parity
+ bits_to_send -= 7;
+ while (bits_to_send > 0) {
+ ReaderTransmitBitsPar(&cmd[i++], MIN(bits_to_send, 8), NULL, NULL); // following bytes are 8 bit and no parity
+ bits_to_send -= 8;
+ }
+ } else {
GetParity(cmd, lenbits/8, par);
- ReaderTransmitBitsPar(cmd, lenbits, par, NULL);
+ ReaderTransmitBitsPar(cmd, lenbits, par, NULL); // bytes are 8 bit with odd parity
+ }
+ } else { // want to send complete bytes only
+ if(param & ISO14A_TOPAZMODE) {
+ uint16_t i = 0;
+ ReaderTransmitBitsPar(&cmd[i++], 7, NULL, NULL); // first byte: 7 bits, no paritiy
+ while (i < len) {
+ ReaderTransmitBitsPar(&cmd[i++], 8, NULL, NULL); // following bytes: 8 bits, no paritiy
+ }
} else {
- ReaderTransmit(cmd,len, NULL);
+ ReaderTransmit(cmd,len, NULL); // 8 bits, odd parity
+ }
}
arg0 = ReaderReceive(buf, par);
cmd_send(CMD_ACK,arg0,0,0,buf,sizeof(buf));
// Therefore try in alternating directions.
int32_t dist_nt(uint32_t nt1, uint32_t nt2) {
- uint16_t i;
- uint32_t nttmp1, nttmp2;
-
if (nt1 == nt2) return 0;
- nttmp1 = nt1;
- nttmp2 = nt2;
+ uint16_t i;
+ uint32_t nttmp1 = nt1;
+ uint32_t nttmp2 = nt2;
for (i = 1; i < 32768; i++) {
nttmp1 = prng_successor(nttmp1, 1);
// Cloning MiFare Classic Rail and Building Passes, Anywhere, Anytime"
// (article by Nicolas T. Courtois, 2009)
//-----------------------------------------------------------------------------
-void ReaderMifare(bool first_try)
-{
- // Mifare AUTH
- uint8_t mf_auth[] = { 0x60,0x00,0xf5,0x7b };
- uint8_t mf_nr_ar[] = { 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 };
- static uint8_t mf_nr_ar3;
-
- uint8_t receivedAnswer[MAX_MIFARE_FRAME_SIZE];
- uint8_t receivedAnswerPar[MAX_MIFARE_PARITY_SIZE];
-
+void ReaderMifare(bool first_try) {
// free eventually allocated BigBuf memory. We want all for tracing.
BigBuf_free();
clear_trace();
set_tracing(TRUE);
+ // Mifare AUTH
+ uint8_t mf_auth[] = { 0x60,0x00,0xf5,0x7b };
+ uint8_t mf_nr_ar[8] = { 0x00 }; //{ 0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01 };
+ static uint8_t mf_nr_ar3 = 0;
+
+ uint8_t receivedAnswer[MAX_MIFARE_FRAME_SIZE] = { 0x00 };
+ uint8_t receivedAnswerPar[MAX_MIFARE_PARITY_SIZE] = { 0x00 };
+
byte_t nt_diff = 0;
uint8_t par[1] = {0}; // maximum 8 Bytes to be sent here, 1 byte parity is therefore enough
static byte_t par_low = 0;
bool led_on = TRUE;
- uint8_t uid[10] ={0};
- uint32_t cuid;
+ uint8_t uid[10] = {0x00};
+ //uint32_t cuid = 0x00;
uint32_t nt = 0;
uint32_t previous_nt = 0;
byte_t par_list[8] = {0x00};
byte_t ks_list[8] = {0x00};
- static uint32_t sync_time;
- static uint32_t sync_cycles;
+ static uint32_t sync_time = 0;
+ static uint32_t sync_cycles = 0;
int catch_up_cycles = 0;
int last_catch_up = 0;
uint16_t consecutive_resyncs = 0;
int isOK = 0;
+ int numWrongDistance = 0;
+
if (first_try) {
mf_nr_ar3 = 0;
iso14443a_setup(FPGA_HF_ISO14443A_READER_MOD);
LED_A_ON();
LED_B_OFF();
LED_C_OFF();
-
+ LED_C_ON();
for(uint16_t i = 0; TRUE; i++) {
WDT_HIT();
// Test if the action was cancelled
- if(BUTTON_PRESS()) {
+ if(BUTTON_PRESS()) break;
+
+ if (numWrongDistance > 1000) {
+ isOK = 0;
break;
}
- LED_C_ON();
-
- if(!iso14443a_select_card(uid, NULL, &cuid)) {
+ //if(!iso14443a_select_card(uid, NULL, &cuid)) {
+ if(!iso14443a_select_card(uid, NULL, NULL)) {
if (MF_DBGLEVEL >= 1) Dbprintf("Mifare: Can't select card");
continue;
}
nt_attacked = nt;
}
else {
- if (nt_distance == -99999) { // invalid nonce received, try again
+
+ // invalid nonce received, try again
+ if (nt_distance == -99999) {
+ numWrongDistance++;
+ if (MF_DBGLEVEL >= 3) Dbprintf("The two nonces has invalid distance, tag could have good PRNG\n");
continue;
}
+
sync_cycles = (sync_cycles - nt_distance);
if (MF_DBGLEVEL >= 3) Dbprintf("calibrating in cycle %d. nt_distance=%d, Sync_cycles: %d\n", i, nt_distance, sync_cycles);
continue;
if ((nt != nt_attacked) && nt_attacked) { // we somehow lost sync. Try to catch up again...
catch_up_cycles = -dist_nt(nt_attacked, nt);
- if (catch_up_cycles == 99999) { // invalid nonce received. Don't resync on that one.
+ if (catch_up_cycles >= 99999) { // invalid nonce received. Don't resync on that one.
catch_up_cycles = 0;
continue;
}
}
}
-
mf_nr_ar[3] &= 0x1F;
- byte_t buf[28];
+ byte_t buf[28] = {0x00};
+
memcpy(buf + 0, uid, 4);
num_to_bytes(nt, 4, buf + 4);
memcpy(buf + 8, par_list, 8);
cmd_send(CMD_ACK,isOK,0,0,buf,28);
- // Thats it...
+ set_tracing(FALSE);
FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
LEDsoff();
-
- set_tracing(FALSE);
}
-/**
+
+ /*
*MIFARE 1K simulate.
*
*@param flags :
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;
+ }
}
// --- crypto
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
- ar_nr_responses[1], //NT
- ar_nr_responses[2], //AR1
- ar_nr_responses[3], //NR1
- ar_nr_responses[6], //AR2
- ar_nr_responses[7] //NR2
+ ar_nr_responses[1], // NT
+ ar_nr_responses[2], // AR1
+ ar_nr_responses[3], // NR1
+ ar_nr_responses[6], // AR2
+ ar_nr_responses[7] // NR2
);
} else {
Dbprintf("Failed to obtain two AR/NR pairs!");
- if(ar_nr_collected >0) {
+ if(ar_nr_collected > 0 ) {
Dbprintf("Only got these: UID=%08x, nonce=%08x, AR1=%08x, NR1=%08x",
ar_nr_responses[0], // UID
- ar_nr_responses[1], //NT
- ar_nr_responses[2], //AR1
- ar_nr_responses[3] //NR1
+ ar_nr_responses[1], // NT
+ ar_nr_responses[2], // AR1
+ ar_nr_responses[3] // NR1
);
}
}
}
-
//-----------------------------------------------------------------------------
// MIFARE sniffer.
//
// bit 0 - trigger from first card answer
// bit 1 - trigger from first reader 7-bit request
+ // free eventually allocated BigBuf memory
+ BigBuf_free();
+
// C(red) A(yellow) B(green)
LEDsoff();
// init trace buffer
uint8_t receivedResponse[MAX_MIFARE_FRAME_SIZE];
uint8_t receivedResponsePar[MAX_MIFARE_PARITY_SIZE];
- // As we receive stuff, we copy it from receivedCmd or receivedResponse
- // into trace, along with its length and other annotations.
- //uint8_t *trace = (uint8_t *)BigBuf;
-
- // free eventually allocated BigBuf memory
- BigBuf_free();
// allocate the DMA buffer, used to stream samples from the FPGA
uint8_t *dmaBuf = BigBuf_malloc(DMA_BUFFER_SIZE);
uint8_t *data = dmaBuf;
if (MfSniffLogic(receivedCmd, Uart.len, Uart.parity, Uart.bitCount, TRUE)) break;
/* And ready to receive another command. */
- UartReset();
+ UartInit(receivedCmd, receivedCmdPar);
/* And also reset the demod code */
DemodReset();
// And ready to receive another response.
DemodReset();
+
+ // And reset the Miller decoder including its (now outdated) input buffer
+ UartInit(receivedCmd, receivedCmdPar);
}
TagIsActive = (Demod.state != DEMOD_UNSYNCD);
}
#ifndef __ISO14443A_H
#define __ISO14443A_H
-#include "common.h"
+#include "../include/common.h"
+#include "../include/mifare.h"
#include "mifaresniff.h"
typedef struct {
// DROP_FIRST_HALF,
} state;
uint16_t shiftReg;
- uint16_t bitCount;
+ int16_t bitCount;
uint16_t len;
uint16_t byteCntMax;
uint16_t posCnt;
uint16_t syncBit;
uint8_t parityBits;
uint8_t parityLen;
- uint16_t highCnt;
- uint16_t twoBits;
+ uint32_t fourBits;
uint32_t startTime, endTime;
uint8_t *output;
uint8_t *parity;
// 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;
AcquireTiType();
FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
- DbpString("Now use tiread to check");
+ DbpString("Now use 'lf ti read' to check");
}
void SimulateTagLowFrequency(int period, int gap, int ledcontrol)
{
uint8_t *dest = BigBuf_get_addr();
//const size_t sizeOfBigBuff = BigBuf_max_traceLen();
- size_t size;
+ size_t size = 0;
uint32_t hi2=0, hi=0, lo=0;
int idx=0;
// Configure to go in 125Khz listen mode
if (errCnt<0) continue;
- errCnt = Em410xDecode(dest, &size, &idx, &hi, &lo);
- if (errCnt){
- if (size>64){
- Dbprintf("EM XL TAG ID: %06x%08x%08x - (%05d_%03d_%08d)",
- hi,
- (uint32_t)(lo>>32),
- (uint32_t)lo,
- (uint32_t)(lo&0xFFFF),
- (uint32_t)((lo>>16LL) & 0xFF),
- (uint32_t)(lo & 0xFFFFFF));
- } else {
- Dbprintf("EM TAG ID: %02x%08x - (%05d_%03d_%08d)",
- (uint32_t)(lo>>32),
- (uint32_t)lo,
- (uint32_t)(lo&0xFFFF),
- (uint32_t)((lo>>16LL) & 0xFF),
- (uint32_t)(lo & 0xFFFFFF));
- }
+ errCnt = Em410xDecode(dest, &size, &idx, &hi, &lo);
+ if (errCnt){
+ if (size>64){
+ Dbprintf("EM XL TAG ID: %06x%08x%08x - (%05d_%03d_%08d)",
+ hi,
+ (uint32_t)(lo>>32),
+ (uint32_t)lo,
+ (uint32_t)(lo&0xFFFF),
+ (uint32_t)((lo>>16LL) & 0xFF),
+ (uint32_t)(lo & 0xFFFFFF));
+ } else {
+ Dbprintf("EM TAG ID: %02x%08x - (%05d_%03d_%08d)",
+ (uint32_t)(lo>>32),
+ (uint32_t)lo,
+ (uint32_t)(lo&0xFFFF),
+ (uint32_t)((lo>>16LL) & 0xFF),
+ (uint32_t)(lo & 0xFFFFFF));
+ }
if (findone){
if (ledcontrol) LED_A_OFF();
uint8_t version=0;
uint8_t facilitycode=0;
uint16_t number=0;
+ uint8_t crc = 0;
+ uint16_t calccrc = 0;
// Configure to go in 125Khz listen mode
LFSetupFPGAForADC(95, true);
WDT_HIT();
idx = IOdemodFSK(dest, BigBuf_max_traceLen());
if (idx<0) continue;
- //valid tag found
-
- //Index map
- //0 10 20 30 40 50 60
- //| | | | | | |
- //01234567 8 90123456 7 89012345 6 78901234 5 67890123 4 56789012 3 45678901 23
- //-----------------------------------------------------------------------------
- //00000000 0 11110000 1 facility 1 version* 1 code*one 1 code*two 1 ???????? 11
- //
- //XSF(version)facility:codeone+codetwo
- //Handle the data
- if(findone){ //only print binary if we are doing one
- Dbprintf("%d%d%d%d%d%d%d%d %d",dest[idx], dest[idx+1], dest[idx+2],dest[idx+3],dest[idx+4],dest[idx+5],dest[idx+6],dest[idx+7],dest[idx+8]);
- Dbprintf("%d%d%d%d%d%d%d%d %d",dest[idx+9], dest[idx+10],dest[idx+11],dest[idx+12],dest[idx+13],dest[idx+14],dest[idx+15],dest[idx+16],dest[idx+17]);
- Dbprintf("%d%d%d%d%d%d%d%d %d",dest[idx+18],dest[idx+19],dest[idx+20],dest[idx+21],dest[idx+22],dest[idx+23],dest[idx+24],dest[idx+25],dest[idx+26]);
- Dbprintf("%d%d%d%d%d%d%d%d %d",dest[idx+27],dest[idx+28],dest[idx+29],dest[idx+30],dest[idx+31],dest[idx+32],dest[idx+33],dest[idx+34],dest[idx+35]);
- Dbprintf("%d%d%d%d%d%d%d%d %d",dest[idx+36],dest[idx+37],dest[idx+38],dest[idx+39],dest[idx+40],dest[idx+41],dest[idx+42],dest[idx+43],dest[idx+44]);
- Dbprintf("%d%d%d%d%d%d%d%d %d",dest[idx+45],dest[idx+46],dest[idx+47],dest[idx+48],dest[idx+49],dest[idx+50],dest[idx+51],dest[idx+52],dest[idx+53]);
- Dbprintf("%d%d%d%d%d%d%d%d %d%d",dest[idx+54],dest[idx+55],dest[idx+56],dest[idx+57],dest[idx+58],dest[idx+59],dest[idx+60],dest[idx+61],dest[idx+62],dest[idx+63]);
- }
- code = bytebits_to_byte(dest+idx,32);
- code2 = bytebits_to_byte(dest+idx+32,32);
- version = bytebits_to_byte(dest+idx+27,8); //14,4
+ //valid tag found
+
+ //Index map
+ //0 10 20 30 40 50 60
+ //| | | | | | |
+ //01234567 8 90123456 7 89012345 6 78901234 5 67890123 4 56789012 3 45678901 23
+ //-----------------------------------------------------------------------------
+ //00000000 0 11110000 1 facility 1 version* 1 code*one 1 code*two 1 checksum 11
+ //
+ //Checksum:
+ //00000000 0 11110000 1 11100000 1 00000001 1 00000011 1 10110110 1 01110101 11
+ //preamble F0 E0 01 03 B6 75
+ // How to calc checksum,
+ // http://www.proxmark.org/forum/viewtopic.php?id=364&p=6
+ // F0 + E0 + 01 + 03 + B6 = 28A
+ // 28A & FF = 8A
+ // FF - 8A = 75
+ // Checksum: 0x75
+ //XSF(version)facility:codeone+codetwo
+ //Handle the data
+ if(findone){ //only print binary if we are doing one
+ Dbprintf("%d%d%d%d%d%d%d%d %d",dest[idx], dest[idx+1], dest[idx+2],dest[idx+3],dest[idx+4],dest[idx+5],dest[idx+6],dest[idx+7],dest[idx+8]);
+ Dbprintf("%d%d%d%d%d%d%d%d %d",dest[idx+9], dest[idx+10],dest[idx+11],dest[idx+12],dest[idx+13],dest[idx+14],dest[idx+15],dest[idx+16],dest[idx+17]);
+ Dbprintf("%d%d%d%d%d%d%d%d %d",dest[idx+18],dest[idx+19],dest[idx+20],dest[idx+21],dest[idx+22],dest[idx+23],dest[idx+24],dest[idx+25],dest[idx+26]);
+ Dbprintf("%d%d%d%d%d%d%d%d %d",dest[idx+27],dest[idx+28],dest[idx+29],dest[idx+30],dest[idx+31],dest[idx+32],dest[idx+33],dest[idx+34],dest[idx+35]);
+ Dbprintf("%d%d%d%d%d%d%d%d %d",dest[idx+36],dest[idx+37],dest[idx+38],dest[idx+39],dest[idx+40],dest[idx+41],dest[idx+42],dest[idx+43],dest[idx+44]);
+ Dbprintf("%d%d%d%d%d%d%d%d %d",dest[idx+45],dest[idx+46],dest[idx+47],dest[idx+48],dest[idx+49],dest[idx+50],dest[idx+51],dest[idx+52],dest[idx+53]);
+ Dbprintf("%d%d%d%d%d%d%d%d %d%d",dest[idx+54],dest[idx+55],dest[idx+56],dest[idx+57],dest[idx+58],dest[idx+59],dest[idx+60],dest[idx+61],dest[idx+62],dest[idx+63]);
+ }
+ code = bytebits_to_byte(dest+idx,32);
+ code2 = bytebits_to_byte(dest+idx+32,32);
+ version = bytebits_to_byte(dest+idx+27,8); //14,4
facilitycode = bytebits_to_byte(dest+idx+18,8);
- number = (bytebits_to_byte(dest+idx+36,8)<<8)|(bytebits_to_byte(dest+idx+45,8)); //36,9
-
- Dbprintf("XSF(%02d)%02x:%05d (%08x%08x)",version,facilitycode,number,code,code2);
- // if we're only looking for one tag
- if (findone){
- if (ledcontrol) LED_A_OFF();
- //LED_A_OFF();
- *high=code;
- *low=code2;
- return;
- }
- code=code2=0;
- version=facilitycode=0;
- number=0;
- idx=0;
+ number = (bytebits_to_byte(dest+idx+36,8)<<8)|(bytebits_to_byte(dest+idx+45,8)); //36,9
+
+ crc = bytebits_to_byte(dest+idx+54,8);
+ for (uint8_t i=1; i<6; ++i)
+ calccrc += bytebits_to_byte(dest+idx+9*i,8);
+ calccrc &= 0xff;
+ calccrc = 0xff - calccrc;
+
+ char *crcStr = (crc == calccrc) ? "ok":"!crc";
+
+ Dbprintf("IO Prox XSF(%02d)%02x:%05d (%08x%08x) [%02x %s]",version,facilitycode,number,code,code2, crc, crcStr);
+ // if we're only looking for one tag
+ if (findone){
+ if (ledcontrol) LED_A_OFF();
+ //LED_A_OFF();
+ *high=code;
+ *low=code2;
+ return;
+ }
+ code=code2=0;
+ version=facilitycode=0;
+ number=0;
+ idx=0;
WDT_HIT();
}
* and enlarge the gap ones.
*/
#define START_GAP 50*8 // 10 - 50fc 250
-#define WRITE_GAP 20*8 // - 30fc 160
-#define WRITE_0 24*8 // 16 - 63fc 54fc 144
-#define WRITE_1 54*8 // 48 - 63fc 54fc 432 for T55x7; 448 for E5550 //400
+#define WRITE_GAP 20*8 // 8 - 30fc
+#define WRITE_0 24*8 // 16 - 31fc 24fc 192
+#define WRITE_1 54*8 // 48 - 63fc 54fc 432 for T55x7; 448 for E5550
+
+// VALUES TAKEN FROM EM4x function: SendForward
+// START_GAP = 440; (55*8) cycles at 125Khz (8us = 1cycle)
+// WRITE_GAP = 128; (16*8)
+// WRITE_1 = 256 32*8; (32*8)
+
+// These timings work for 4469/4269/4305 (with the 55*8 above)
+// WRITE_0 = 23*8 , 9*8 SpinDelayUs(23*8);
+
+// Sam7s has several timers, we will use the source TIMER_CLOCK1 (aka AT91C_TC_CLKS_TIMER_DIV1_CLOCK)
+// TIMER_CLOCK1 = MCK/2, MCK is running at 48 MHz, Timer is running at 48/2 = 24 MHz
+// Hitag units (T0) have duration of 8 microseconds (us), which is 1/125000 per second (carrier)
+// T0 = TIMER_CLOCK1 / 125000 = 192
+// 1 Cycle = 8 microseconds(us)
#define T55xx_SAMPLES_SIZE 12000 // 32 x 32 x 10 (32 bit times numofblock (7), times clock skip..)
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);
#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 bits[256] = {0x00};
+ uint8_t blocks[8][16];
+ uint8_t *dest = BigBuf_get_addr();
+
int GraphTraceLen = BigBuf_max_traceLen();
+ if ( GraphTraceLen > 18000 )
+ GraphTraceLen = 18000;
+
+
int i, j, lastval, bitidx, half_switch;
int clock = 64;
int tolerance = clock / 8;
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;
block_done = 1;
}
else if(half_switch == 1) {
- BitStream[bitidx++] = 0;
+ bits[bitidx++] = 0;
half_switch = 0;
}
else
half_switch++;
} else if (abs(lc-clock) < tolerance) {
// 64TO
- BitStream[bitidx++] = 1;
+ bits[bitidx++] = 1;
} else {
// Error
warnings++;
if(block_done == 1) {
if(bitidx == 128) {
for(j=0; j<16; j++) {
- Blocks[num_blocks][j] = 128*BitStream[j*8+7]+
- 64*BitStream[j*8+6]+
- 32*BitStream[j*8+5]+
- 16*BitStream[j*8+4]+
- 8*BitStream[j*8+3]+
- 4*BitStream[j*8+2]+
- 2*BitStream[j*8+1]+
- BitStream[j*8];
+ blocks[num_blocks][j] = 128*bits[j*8+7]+
+ 64*bits[j*8+6]+
+ 32*bits[j*8+5]+
+ 16*bits[j*8+4]+
+ 8*bits[j*8+3]+
+ 4*bits[j*8+2]+
+ 2*bits[j*8+1]+
+ bits[j*8];
+
}
num_blocks++;
}
half_switch = 0;
}
if(i < GraphTraceLen)
- {
- if (GraphBuffer[i-1] > GraphBuffer[i]) dir=0;
- else dir = 1;
- }
+ dir =(dest[i-1] > dest[i]) ? 0 : 1;
}
if(bitidx==255)
bitidx=0;
warnings = 0;
if(num_blocks == 4) break;
}
- memcpy(outBlocks, Blocks, 16*num_blocks);
+ memcpy(outBlocks, blocks, 16*num_blocks);
return num_blocks;
}
void EM4xReadWord(uint8_t Address, uint32_t Pwd, uint8_t PwdMode) {
- uint8_t fwd_bit_count;
uint8_t *dest = BigBuf_get_addr();
- int m=0, i=0;
+ uint16_t bufferlength = BigBuf_max_traceLen();
+ uint32_t i = 0;
+
+ // Clear destination buffer before sending the command 0x80 = average.
+ memset(dest, 0x80, bufferlength);
+
+ uint8_t fwd_bit_count;
//If password mode do login
if (PwdMode == 1) EM4xLogin(Pwd);
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();
}
LEDsoff();\r
}\r
cmd_send(CMD_ACK,1,0,0,0,0);\r
+ } \r
+ cmd_send(CMD_ACK,1,0,0,0,0);\r
}\r
\r
// Arg0 = BlockNo,\r
return;\r
}\r
\r
- cmd_send(CMD_ACK,1,0,0,dataout,16);\r
+ cmd_send(CMD_ACK,1,0,0,dataout,16);\r
FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);\r
LEDsoff();\r
}\r
isOK = 0;\r
if (MF_DBGLEVEL >= 1) Dbprintf("Can't select card");\r
}\r
-\r
+ \r
\r
if(isOK && mifare_classic_auth(pcs, cuid, FirstBlockOfSector(sectorNo), keyType, ui64Key, AUTH_FIRST)) {\r
isOK = 0;\r
LEDsoff();\r
}\r
\r
+// arg0 = blockNo (start)\r
+// arg1 = Pages (number of blocks)\r
+// arg2 = useKey\r
+// datain = KEY bytes\r
void MifareUReadCard(uint8_t arg0, uint16_t arg1, uint8_t arg2, uint8_t *datain)\r
{\r
// free eventually allocated BigBuf memory\r
break;\r
}\r
\r
- len = mifare_ultra_readblock(blockNo + i, dataout + 4 * i);\r
+ // UL-C authentication\r
+ if ( useKey ) {\r
+ uint8_t key[16] = {0x00}; \r
+ memcpy(key, datain, sizeof(key) );\r
+\r
+ if ( !mifare_ultra_auth(key) ) {\r
+ OnError(1);\r
+ return; \r
+ }\r
+ }\r
+\r
+ // UL-EV1 / NTAG authentication\r
+ if (usePwd) { \r
+ uint8_t pwd[4] = {0x00};\r
+ memcpy(pwd, datain, sizeof(pwd));\r
+ uint8_t pack[4] = {0,0,0,0};\r
\r
+ if (!mifare_ul_ev1_auth(pwd, pack)){\r
+ OnError(1);\r
+ return; \r
+ }\r
+ }\r
+ \r
+ for (int i = 0; i < blocks; i++){\r
+ if ((i*4) + 4 > CARD_MEMORY_SIZE) {\r
+ Dbprintf("Data exceeds buffer!!");\r
+ break;\r
+ }\r
+ \r
+ len = mifare_ultra_readblock(blockNo + i, dataout + 4 * i);\r
+ \r
if (len) {\r
if (MF_DBGLEVEL >= MF_DBG_ERROR) Dbprintf("Read block %d error",i);\r
// if no blocks read - error out\r
if (i==0){\r
OnError(2);\r
- return;\r
+ return;\r
} else {\r
//stop at last successful read block and return what we got\r
break;\r
LEDsoff();\r
}\r
\r
-void MifareUWriteBlock_Special(uint8_t arg0, uint8_t *datain)\r
+// Arg0 : Block to write to.\r
+// Arg1 : 0 = use no authentication.\r
+// 1 = use 0x1A authentication.\r
+// 2 = use 0x1B authentication.\r
+// datain : 4 first bytes is data to be written.\r
+// : 4/16 next bytes is authentication key.\r
+void MifareUWriteBlock_Special(uint8_t arg0, uint8_t arg1, uint8_t *datain)\r
{\r
uint8_t blockNo = arg0;\r
+ bool useKey = (arg1 == 1); //UL_C\r
+ bool usePwd = (arg1 == 2); //UL_EV1/NTAG\r
byte_t blockdata[4] = {0x00};\r
\r
memcpy(blockdata, datain,4);\r
return;\r
};\r
\r
+ // UL-C authentication\r
+ if ( useKey ) {\r
+ uint8_t key[16] = {0x00}; \r
+ memcpy(key, datain+4, sizeof(key) );\r
+\r
+ if ( !mifare_ultra_auth(key) ) {\r
+ OnError(1);\r
+ return; \r
+ }\r
+ }\r
+ \r
+ // UL-EV1 / NTAG authentication\r
+ if (usePwd) { \r
+ uint8_t pwd[4] = {0x00};\r
+ memcpy(pwd, datain+4, 4);\r
+ uint8_t pack[4] = {0,0,0,0};\r
+ if (!mifare_ul_ev1_auth(pwd, pack)) {\r
+ OnError(1);\r
+ return; \r
+ }\r
+ }\r
+ \r
if(mifare_ultra_special_writeblock(blockNo, blockdata)) {\r
if (MF_DBGLEVEL >= 1) Dbprintf("Write block error");\r
OnError(0);\r
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
cmd_send(CMD_ACK,isOK,0,0,0,0);\r
}\r
\r
- //\r
+void MifareCollectNonces(uint32_t arg0, uint32_t arg1){\r
+\r
+ BigBuf_free();\r
+\r
+ uint32_t iterations = arg0;\r
+ uint8_t uid[10] = {0x00};\r
+\r
+ uint8_t *response = BigBuf_malloc(MAX_MIFARE_FRAME_SIZE);\r
+ uint8_t *responsePar = BigBuf_malloc(MAX_MIFARE_PARITY_SIZE);\r
+\r
+ uint8_t mf_auth[] = { 0x60,0x00,0xf5,0x7b };\r
+ \r
+ // get memory from BigBuf.\r
+ uint8_t *nonces = BigBuf_malloc(iterations * 4);\r
+\r
+ LED_A_ON();\r
+ LED_B_OFF();\r
+ LED_C_OFF();\r
+\r
+ clear_trace();\r
+ set_tracing(TRUE);\r
+ iso14443a_setup(FPGA_HF_ISO14443A_READER_LISTEN);\r
+ \r
+ for (int i = 0; i < iterations; i++) {\r
+ \r
+ WDT_HIT();\r
+\r
+ // Test if the action was cancelled\r
+ if(BUTTON_PRESS()) break;\r
+ \r
+ // if(mifare_classic_halt(pcs, cuid)) {\r
+ // if (MF_DBGLEVEL >= 1) Dbprintf("Halt error");\r
+ //}\r
+\r
+ if(!iso14443a_select_card(uid, NULL, NULL)) {\r
+ if (MF_DBGLEVEL >= 1) Dbprintf("Can't select card");\r
+ continue;\r
+ };\r
+\r
+ // Transmit MIFARE_CLASSIC_AUTH.\r
+ ReaderTransmit(mf_auth, sizeof(mf_auth), NULL);\r
+\r
+ // Receive the (4 Byte) "random" nonce\r
+ if (!ReaderReceive(response, responsePar)) {\r
+ if (MF_DBGLEVEL >= 1) Dbprintf("Couldn't receive tag nonce");\r
+ continue;\r
+ } \r
+ \r
+ nonces[i*4] = bytes_to_num(response, 4);\r
+ }\r
+ \r
+ int packLen = iterations * 4;\r
+ int packSize = 0;\r
+ int packNum = 0;\r
+ while (packLen > 0) {\r
+ packSize = MIN(USB_CMD_DATA_SIZE, packLen);\r
+ LED_B_ON();\r
+ cmd_send(CMD_ACK, 77, 0, packSize, nonces - packLen, packSize);\r
+ LED_B_OFF();\r
+\r
+ packLen -= packSize;\r
+ packNum++;\r
+ }\r
+ FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);\r
+ LEDsoff();\r
+}\r
+\r
+//\r
// DESFIRE\r
//\r
\r
\r
byte_t dataout[11] = {0x00};\r
uint8_t uid[10] = {0x00};\r
- uint32_t cuid;\r
+ uint32_t cuid = 0x00;\r
\r
clear_trace();\r
iso14443a_setup(FPGA_HF_ISO14443A_READER_LISTEN);\r
\r
uint32_t cuid = arg0;\r
uint8_t key[16] = {0x00};\r
- byte_t isOK = 0;\r
byte_t dataout[12] = {0x00};\r
+ byte_t isOK = 0;\r
\r
memcpy(key, datain, 16);\r
\r
isOK = mifare_desfire_des_auth2(cuid, key, dataout);\r
\r
if( isOK) {\r
- if (MF_DBGLEVEL >= MF_DBG_EXTENDED) \r
- Dbprintf("Authentication part2: Failed"); \r
- //OnError(4);\r
+ if (MF_DBGLEVEL >= MF_DBG_EXTENDED) Dbprintf("Authentication part2: Failed"); \r
+ OnError(4);\r
return;\r
}\r
\r
- if (MF_DBGLEVEL >= MF_DBG_EXTENDED) \r
- DbpString("AUTH 2 FINISHED");\r
+ if (MF_DBGLEVEL >= MF_DBG_EXTENDED) DbpString("AUTH 2 FINISHED");\r
\r
cmd_send(CMD_ACK, isOK, 0, 0, dataout, sizeof(dataout));\r
FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);\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"
+#include "BigBuf.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;
+
+ 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 ){
+ 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?
+ */
+ clear_trace();
+ 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] = {0x00};
+
+ uint8_t resp[MAX_FRAME_SIZE];
+ uint8_t par[MAX_PARITY_SIZE];
+
+ wrappedLen = CreateAPDU( cmd, cmd_len, wCmd);
+
+ if (MF_DBGLEVEL >= 4) {
+ print_result("WCMD <--: ", wCmd, wrappedLen);
+ }
+ ReaderTransmit( wCmd, wrappedLen, NULL);
+
+ len = ReaderReceive(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
return 0;\r
}\r
\r
+ // encrypt out, in, length, key, iv\r
+ tdes_2key_enc(rnd_ab, rnd_ab, sizeof(rnd_ab), key, enc_random_b);\r
+\r
+ len = mifare_sendcmd_short_mfucauth(NULL, 1, 0xAF, rnd_ab, resp, respPar, NULL);\r
+ if (len != 11) {\r
+ if (MF_DBGLEVEL >= MF_DBG_ERROR) Dbprintf("Cmd Error: %02x", resp[0]);\r
+ return 0;\r
+ }\r
+\r
+ uint8_t enc_resp[8] = { 0,0,0,0,0,0,0,0 };\r
+ uint8_t resp_random_a[8] = { 0,0,0,0,0,0,0,0 };\r
+ memcpy(enc_resp, resp+1, 8);\r
+ \r
+ // decrypt out, in, length, key, iv \r
+ tdes_2key_dec(resp_random_a, enc_resp, 8, key, enc_random_b);\r
+ if ( memcmp(resp_random_a, random_a, 8) != 0 ) {\r
+ if (MF_DBGLEVEL >= MF_DBG_ERROR) Dbprintf("failed authentication");\r
+ return 0;\r
+ } \r
+\r
if (MF_DBGLEVEL >= MF_DBG_EXTENDED) {\r
Dbprintf("e_AB: %02x %02x %02x %02x %02x %02x %02x %02x", \r
rnd_ab[0],rnd_ab[1],rnd_ab[2],rnd_ab[3],\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
- byte_t res;\r
+ uint32_t pos = 0;\r
+ uint8_t par[3] = {0x00}; // enough for 18 Bytes to send\r
+ byte_t res = 0;\r
\r
uint8_t d_block[18], d_block_enc[18];\r
uint8_t receivedAnswer[MAX_MIFARE_FRAME_SIZE];\r
int mifare_ultra_writeblock(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 par[3] = {0}; // enough for 18 parity bits\r
uint8_t d_block[18] = {0x00};\r
uint8_t receivedAnswer[MAX_FRAME_SIZE];\r
uint8_t receivedAnswerPar[MAX_PARITY_SIZE];\r
\r
- // command MIFARE_CLASSIC_WRITEBLOCK\r
- len = mifare_sendcmd_short(NULL, true, 0xA0, blockNo, receivedAnswer, receivedAnswerPar, NULL);\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 ((len != 1) || (receivedAnswer[0] != 0x0A)) { // 0x0a - ACK\r
if (MF_DBGLEVEL >= MF_DBG_ERROR)\r
Dbprintf("Cmd Addr Error: %02x", receivedAnswer[0]);\r
- return 1;\r
- }\r
+ return 1;\r
+ }\r
\r
memcpy(d_block, blockData, 16);\r
- AppendCrc14443a(d_block, 16);\r
+ AppendCrc14443a(d_block, 16);\r
\r
ReaderTransmitPar(d_block, sizeof(d_block), par, NULL);\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);\r
- return 2;\r
+ return 2;\r
}\r
- return 0;\r
+ return 0;\r
}\r
\r
int mifare_ultra_special_writeblock(uint8_t blockNo, uint8_t *blockData)\r
{\r
- uint16_t len;\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
\r
- // command MIFARE_CLASSIC_WRITEBLOCK\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
+ len = mifare_sendcmd_short_special(NULL, 1, 0xA2, d_block, receivedAnswer, receivedAnswerPar, NULL);\r
\r
- if (receivedAnswer[0] != 0x0A) { // 0x0a - ACK\r
+ if (receivedAnswer[0] != 0x0A) { // 0x0a - ACK\r
if (MF_DBGLEVEL >= MF_DBG_ERROR)\r
Dbprintf("Cmd Send Error: %02x %d", receivedAnswer[0],len);\r
- return 1;\r
- }\r
- return 0;\r
+ return 1;\r
+ }\r
+ return 0;\r
}\r
\r
int mifare_classic_halt(struct Crypto1State *pcs, uint32_t uid) \r
data[0] = 0xAF;\r
memcpy(data+1,key,16);\r
\r
- uint8_t receivedAnswer[MAX_MIFARE_FRAME_SIZE];\r
- uint8_t receivedAnswerPar[MAX_MIFARE_PARITY_SIZE];\r
+ uint8_t receivedAnswer[MAX_FRAME_SIZE];\r
+ uint8_t receivedAnswerPar[MAX_PARITY_SIZE];\r
\r
len = mifare_sendcmd_special2(NULL, 1, 0x03, data, receivedAnswer, receivedAnswerPar ,NULL);\r
\r
\r
#define cardSTATE_TO_IDLE() cardSTATE = MFEMUL_IDLE; LED_B_OFF(); LED_C_OFF();\r
\r
-//functions\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
-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
+//functions
+int mifare_sendcmd_short(struct Crypto1State *pcs, uint8_t crypted, uint8_t cmd, uint8_t data, uint8_t* answer, uint8_t *answer_parity, uint32_t *timing);
+int mifare_sendcmd_short_special(struct Crypto1State *pcs, uint8_t crypted, uint8_t cmd, uint8_t *data, uint8_t* answer, uint8_t *answer_parity, uint32_t *timing);
\r
int mifare_sendcmd_short_mfucauth(struct Crypto1State *pcs, uint8_t crypted, uint8_t cmd, uint8_t *data, uint8_t *answer, uint8_t *answer_parity, uint32_t *timing);\r
int mifare_sendcmd_short_mfuev1auth(struct Crypto1State *pcs, uint8_t crypted, uint8_t cmd, uint8_t *data, uint8_t *answer, uint8_t *answer_parity, uint32_t *timing);\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
+int mifare_sendcmd_shortex(struct Crypto1State *pcs, uint8_t crypted, uint8_t cmd, uint8_t data, uint8_t* answer, uint8_t *answer_parity, uint32_t *timing);
+
int mifare_classic_auth(struct Crypto1State *pcs, uint32_t uid, uint8_t blockNo, uint8_t keyType, uint64_t ui64Key, uint8_t isNested);\r
-int mifare_classic_authex(struct Crypto1State *pcs, uint32_t uid, uint8_t blockNo, uint8_t keyType, uint64_t ui64Key, uint8_t isNested, uint32_t * ntptr, uint32_t *timing);\r
+int mifare_classic_authex(struct Crypto1State *pcs, uint32_t uid, uint8_t blockNo, uint8_t keyType, uint64_t ui64Key, uint8_t isNested, uint32_t * ntptr, uint32_t *timing);
int mifare_classic_readblock(struct Crypto1State *pcs, uint32_t uid, uint8_t blockNo, uint8_t *blockData);\r
int mifare_ul_ev1_auth(uint8_t *key, uint8_t *pack);\r
int mifare_ultra_auth(uint8_t *key);\r
int mifare_ultra_readblock(uint8_t blockNo, uint8_t *blockData);\r
-int mifare_classic_writeblock(struct Crypto1State *pcs, uint32_t uid, uint8_t blockNo, uint8_t *blockData);\r
-int mifare_ultra_writeblock(uint8_t blockNo, uint8_t *blockData);\r
-int mifare_ultra_special_writeblock(uint8_t blockNo, uint8_t *blockData);\r
-int mifare_classic_halt(struct Crypto1State *pcs, uint32_t uid); \r
-int mifare_ultra_halt();\r
+int mifare_classic_writeblock(struct Crypto1State *pcs, uint32_t uid, uint8_t blockNo, uint8_t *blockData);
+int mifare_ultra_writeblock(uint8_t blockNo, uint8_t *blockData);
+int mifare_ultra_special_writeblock(uint8_t blockNo, uint8_t *blockData);
+int mifare_classic_halt(struct Crypto1State *pcs, uint32_t uid);
+int mifare_ultra_halt();
\r
// desfire\r
int mifare_sendcmd_special(struct Crypto1State *pcs, uint8_t crypted, uint8_t cmd, uint8_t* data, uint8_t* answer, uint8_t *answer_parity, uint32_t *timing);\r
int mifare_sendcmd_special2(struct Crypto1State *pcs, uint8_t crypted, uint8_t cmd, uint8_t* data, uint8_t* answer,uint8_t *answer_parity, uint32_t *timing);\r
int mifare_desfire_des_auth1(uint32_t uid, uint8_t *blockData);\r
int mifare_desfire_des_auth2(uint32_t uid, uint8_t *key, uint8_t *blockData);\r
-\r
-// crypto functions\r
-void mf_crypto1_decrypt(struct Crypto1State *pcs, uint8_t *receivedCmd, int len);\r
+
+// crypto functions
+void mf_crypto1_decrypt(struct Crypto1State *pcs, uint8_t *receivedCmd, int len);
void mf_crypto1_encrypt(struct Crypto1State *pcs, uint8_t *data, uint16_t len, uint8_t *par);\r
uint8_t mf_crypto1_encrypt4bit(struct Crypto1State *pcs, uint8_t data);\r
\r
void emlGetMemBt(uint8_t *data, int bytePtr, int byteCount);\r
uint64_t emlGetKey(int sectorNum, int keyType);\r
int emlGetValBl(uint32_t *blReg, uint8_t *blBlock, int blockNum);\r
-int emlSetValBl(uint32_t blReg, uint8_t blBlock, int blockNum);\r
-int emlCheckValBl(int blockNum);\r
-\r
-#endif\r
+int emlSetValBl(uint32_t blReg, uint8_t blBlock, int blockNum);
+int emlCheckValBl(int blockNum);
+
+#endif
// 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)))
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
cmdhficlass.c \
cmdhfmf.c \
cmdhfmfu.c \
+ cmdhfmfdes.c \
+ cmdhftopaz.c \
cmdhw.c \
cmdlf.c \
cmdlfio.c \
pm3_bitlib.c\
aes.c\
protocols.c\
-
+ cmdcrc.c\
+ # reveng/reveng.c\
+ # reveng/cli.c\
+ # reveng/bmpbit.c\
+ # reveng/model.c\
+ # reveng/poly.c\
COREOBJS = $(CORESRCS:%.c=$(OBJDIR)/%.o)
CMDOBJS = $(CMDSRCS:%.c=$(OBJDIR)/%.o)
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)
--- /dev/null
+//-----------------------------------------------------------------------------
+// Copyright (C) 2015 iceman <iceman at iuse.se>
+//
+// 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.
+//-----------------------------------------------------------------------------
+// CRC Calculations from the software reveng commands
+//-----------------------------------------------------------------------------
+
+#include <stdio.h>
+#include <string.h>
+#include "cmdparser.h"
+#include "cmdcrc.h"
+//#include "reveng/reveng.h"
+//#include "reveng/cli.h"
+static int CmdHelp(const char *Cmd);
+
+int CmdCrcCalc(const char *Cmd)
+{
+ //pm3main(Cmd);
+ return 0;
+}
+
+static command_t CommandTable[] =
+{
+ {"help", CmdHelp, 1, "This help"},
+ {"calc", CmdCrcCalc, 1, "{ Calculate CRC's }"},
+ {NULL, NULL, 0, NULL}
+};
+
+int CmdCrc(const char *Cmd)
+{
+ CmdsParse(CommandTable, Cmd);
+ return 0;
+}
+
+int CmdHelp(const char *Cmd)
+{
+ CmdsHelp(CommandTable);
+ return 0;
+}
--- /dev/null
+//-----------------------------------------------------------------------------
+// Copyright (C) 2015 iceman <iceman at iuse.se>
+//
+// 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.
+//-----------------------------------------------------------------------------
+// CRC Calculations from the software reveng commands
+//-----------------------------------------------------------------------------
+
+#ifndef CMDCRC_H__
+#define CMDCRC_H__
+
+int CmdCrc(const char *Cmd);
+int CmdCrcCalc(const char *Cmd);
+#endif
#include "cmdhficlass.h"
#include "cmdhfmf.h"
#include "cmdhfmfu.h"
+#include "cmdhfmfdes.h"
+#include "cmdhftopaz.h"
#include "protocols.h"
static int CmdHelp(const char *Cmd);
return 0;
}
-
void annotateIso14443a(char *exp, size_t size, uint8_t* cmd, uint8_t cmdsize)
{
switch(cmd[0])
case MIFARE_MAGICWUPC1: snprintf(exp,size,"MAGIC WUPC1"); break;
case MIFARE_MAGICWUPC2: snprintf(exp,size,"MAGIC WUPC2"); break;
case MIFARE_MAGICWIPEC: snprintf(exp,size,"MAGIC WIPEC"); break;
- case MIFARE_ULC_AUTH_1: snprintf(exp,size,"AUTH "); break;
- case MIFARE_ULC_AUTH_2: snprintf(exp,size,"AUTH_ANSW"); break;
- case MIFARE_ULEV1_AUTH:
+ case MIFARE_ULC_AUTH_1 : snprintf(exp,size,"AUTH "); break;
+ case MIFARE_ULC_AUTH_2 : snprintf(exp,size,"AUTH_ANSW"); break;
+ case MIFARE_ULEV1_AUTH :
if ( cmdsize == 7 )
snprintf(exp,size,"PWD-AUTH KEY: 0x%02x%02x%02x%02x", cmd[1], cmd[2], cmd[3], cmd[4] );
else
snprintf(exp,size,"PWD-AUTH");
break;
- case MIFARE_ULEV1_FASTREAD:{
+
+ case MIFARE_ULEV1_FASTREAD : {
if ( cmdsize >=3 && cmd[2] <= 0xE6)
snprintf(exp,size,"READ RANGE (%d-%d)",cmd[1],cmd[2]);
else
snprintf(exp,size,"?");
break;
}
- case MIFARE_ULC_WRITE:{
+ case MIFARE_ULC_WRITE : {
if ( cmd[1] < 0x21 )
snprintf(exp,size,"WRITEBLOCK(%d)",cmd[1]);
else
snprintf(exp,size,"?");
break;
}
- case MIFARE_ULEV1_READ_CNT:{
+ case MIFARE_ULEV1_READ_CNT :{
if ( cmd[1] < 5 )
snprintf(exp,size,"READ CNT(%d)",cmd[1]);
else
snprintf(exp,size,"?");
break;
}
- case MIFARE_ULEV1_INCR_CNT:{
+ case MIFARE_ULEV1_INCR_CNT : {
if ( cmd[1] < 5 )
snprintf(exp,size,"INCR(%d)",cmd[1]);
else
snprintf(exp,size,"?");
break;
}
- case MIFARE_ULEV1_READSIG: snprintf(exp,size,"READ_SIG"); break;
- case MIFARE_ULEV1_CHECKTEAR: snprintf(exp,size,"CHK_TEARING(%d)",cmd[1]); break;
- case MIFARE_ULEV1_VCSL: snprintf(exp,size,"VCSL"); break;
+ case MIFARE_ULEV1_READSIG : snprintf(exp,size,"READ_SIG"); break;
+ case MIFARE_ULEV1_CHECKTEAR : snprintf(exp,size,"CHK_TEARING(%d)",cmd[1]); break;
+ case MIFARE_ULEV1_VCSL : snprintf(exp,size,"VCSL"); break;
default: snprintf(exp,size,"?"); break;
}
return;
}
}
+
+void annotateTopaz(char *exp, size_t size, uint8_t* cmd, uint8_t cmdsize)
+{
+ switch(cmd[0]) {
+ case TOPAZ_REQA :snprintf(exp, size, "REQA");break;
+ case TOPAZ_WUPA :snprintf(exp, size, "WUPA");break;
+ case TOPAZ_RID :snprintf(exp, size, "RID");break;
+ case TOPAZ_RALL :snprintf(exp, size, "RALL");break;
+ case TOPAZ_READ :snprintf(exp, size, "READ");break;
+ case TOPAZ_WRITE_E :snprintf(exp, size, "WRITE-E");break;
+ case TOPAZ_WRITE_NE :snprintf(exp, size, "WRITE-NE");break;
+ case TOPAZ_RSEG :snprintf(exp, size, "RSEG");break;
+ case TOPAZ_READ8 :snprintf(exp, size, "READ8");break;
+ case TOPAZ_WRITE_E8 :snprintf(exp, size, "WRITE-E8");break;
+ case TOPAZ_WRITE_NE8 :snprintf(exp, size, "WRITE-NE8");break;
+ default: snprintf(exp,size,"?"); break;
+ }
+}
+
+
/**
06 00 = INITIATE
0E xx = SELECT ID (xx = Chip-ID)
}
/**
- * @brief iso14443B_CRC_Ok Checks CRC in command or response
+ * @brief iso14443A_CRC_check Checks CRC in command or response
+ * @param isResponse
+ * @param data
+ * @param len
+ * @return 0 : CRC-command, CRC not ok
+ * 1 : CRC-command, CRC ok
+ * 2 : Not crc-command
+ */
+
+uint8_t iso14443A_CRC_check(bool isResponse, uint8_t* data, uint8_t len)
+{
+ uint8_t b1,b2;
+
+ if(len <= 2) return 2;
+
+ if(isResponse & (len < 6)) return 2;
+
+ ComputeCrc14443(CRC_14443_A, data, len-2, &b1, &b2);
+ if (b1 != data[len-2] || b2 != data[len-1]) {
+ return 0;
+ } else {
+ return 1;
+ }
+}
+
+
+/**
+ * @brief iso14443B_CRC_check Checks CRC in command or response
* @param isResponse
* @param data
* @param len
}
}
-uint16_t printTraceLine(uint16_t tracepos, uint16_t traceLen, uint8_t *trace, uint8_t protocol, bool showWaitCycles)
+
+bool is_last_record(uint16_t tracepos, uint8_t *trace, uint16_t traceLen)
{
- bool isResponse;
- uint16_t duration, data_len, parity_len;
+ return(tracepos + sizeof(uint32_t) + sizeof(uint16_t) + sizeof(uint16_t) >= traceLen);
+}
+
+
+bool next_record_is_response(uint16_t tracepos, uint8_t *trace)
+{
+ uint16_t next_records_datalen = *((uint16_t *)(trace + tracepos + sizeof(uint32_t) + sizeof(uint16_t)));
+
+ return(next_records_datalen & 0x8000);
+}
+
+
+bool merge_topaz_reader_frames(uint32_t timestamp, uint32_t *duration, uint16_t *tracepos, uint16_t traceLen, uint8_t *trace, uint8_t *frame, uint8_t *topaz_reader_command, uint16_t *data_len)
+{
+
+#define MAX_TOPAZ_READER_CMD_LEN 16
+
+ uint32_t last_timestamp = timestamp + *duration;
+
+ if ((*data_len != 1) || (frame[0] == TOPAZ_WUPA) || (frame[0] == TOPAZ_REQA)) return false;
+
+ memcpy(topaz_reader_command, frame, *data_len);
+ while (!is_last_record(*tracepos, trace, traceLen) && !next_record_is_response(*tracepos, trace)) {
+ uint32_t next_timestamp = *((uint32_t *)(trace + *tracepos));
+ *tracepos += sizeof(uint32_t);
+ uint16_t next_duration = *((uint16_t *)(trace + *tracepos));
+ *tracepos += sizeof(uint16_t);
+ uint16_t next_data_len = *((uint16_t *)(trace + *tracepos)) & 0x7FFF;
+ *tracepos += sizeof(uint16_t);
+ uint8_t *next_frame = (trace + *tracepos);
+ *tracepos += next_data_len;
+ if ((next_data_len == 1) && (*data_len + next_data_len <= MAX_TOPAZ_READER_CMD_LEN)) {
+ memcpy(topaz_reader_command + *data_len, next_frame, next_data_len);
+ *data_len += next_data_len;
+ last_timestamp = next_timestamp + next_duration;
+ } else {
+ // rewind and exit
+ *tracepos = *tracepos - next_data_len - sizeof(uint16_t) - sizeof(uint16_t) - sizeof(uint32_t);
+ break;
+ }
+ uint16_t next_parity_len = (next_data_len-1)/8 + 1;
+ *tracepos += next_parity_len;
+ }
+
+ *duration = last_timestamp - timestamp;
+
+ return true;
+}
+
+
+uint16_t printTraceLine(uint16_t tracepos, uint16_t traceLen, uint8_t *trace, uint8_t protocol, bool showWaitCycles, bool markCRCBytes)
+{
+ bool isResponse;
+ uint16_t data_len, parity_len;
+ uint32_t duration;
+ uint8_t topaz_reader_command[9];
uint32_t timestamp, first_timestamp, EndOfTransmissionTimestamp;
char explanation[30] = {0};
uint8_t *parityBytes = trace + tracepos;
tracepos += parity_len;
+ if (protocol == TOPAZ && !isResponse) {
+ // topaz reader commands come in 1 or 9 separate frames with 7 or 8 Bits each.
+ // merge them:
+ if (merge_topaz_reader_frames(timestamp, &duration, &tracepos, traceLen, trace, frame, topaz_reader_command, &data_len)) {
+ frame = topaz_reader_command;
+ }
+ }
+
//Check the CRC status
uint8_t crcStatus = 2;
if (data_len > 2) {
- uint8_t b1, b2;
- if(protocol == ICLASS)
- {
- crcStatus = iclass_CRC_check(isResponse, frame, data_len);
-
- }else if (protocol == ISO_14443B)
- {
- crcStatus = iso14443B_CRC_check(isResponse, frame, data_len);
- }
- else if (protocol == ISO_14443A){//Iso 14443a
-
- ComputeCrc14443(CRC_14443_A, frame, data_len-2, &b1, &b2);
-
- if (b1 != frame[data_len-2] || b2 != frame[data_len-1]) {
- if(!(isResponse & (data_len < 6)))
- {
- crcStatus = 0;
- }
- }
+ switch (protocol) {
+ case ICLASS:
+ crcStatus = iclass_CRC_check(isResponse, frame, data_len);
+ break;
+ case ISO_14443B:
+ case TOPAZ:
+ crcStatus = iso14443B_CRC_check(isResponse, frame, data_len);
+ break;
+ case ISO_14443A:
+ crcStatus = iso14443A_CRC_check(isResponse, frame, data_len);
+ break;
+ default:
+ break;
}
}
//0 CRC-command, CRC not ok
//2 Not crc-command
//--- Draw the data column
- //char line[16][110];
char line[16][110];
for (int j = 0; j < data_len && j/16 < 16; j++) {
uint8_t parityBits = parityBytes[j>>3];
if (isResponse && (oddparity != ((parityBits >> (7-(j&0x0007))) & 0x01))) {
snprintf(line[j/16]+(( j % 16) * 4),110, "%02x! ", frame[j]);
-
} else {
snprintf(line[j/16]+(( j % 16) * 4),110, "%02x ", frame[j]);
}
-
- }
- if(crcStatus == 1)
- {//CRC-command
- char *pos1 = line[(data_len-2)/16]+(((data_len-2) % 16) * 4)-1;
- (*pos1) = '[';
- char *pos2 = line[(data_len)/16]+(((data_len) % 16) * 4)-2;
- (*pos2) = ']';
}
- if(data_len == 0)
- {
- if(data_len == 0){
- sprintf(line[0],"<empty trace - possible error>");
+
+ if (markCRCBytes) {
+ //CRC-command
+ if(crcStatus == 0 || crcStatus == 1) {
+ char *pos1 = line[(data_len-2)/16]+(((data_len-2) % 16) * 4);
+ (*pos1) = '[';
+ char *pos2 = line[(data_len)/16]+(((data_len) % 16) * 4);
+ sprintf(pos2, "%c", ']');
}
}
- //--- Draw the CRC column
+ if(data_len == 0){
+ sprintf(line[0],"<empty trace - possible error>");
+ }
+ //--- Draw the CRC column
char *crc = (crcStatus == 0 ? "!crc" : (crcStatus == 1 ? " ok " : " "));
EndOfTransmissionTimestamp = timestamp + duration;
if(!isResponse)
{
- if(protocol == ICLASS)
- annotateIclass(explanation,sizeof(explanation),frame,data_len);
- else if (protocol == ISO_14443A)
- annotateIso14443a(explanation,sizeof(explanation),frame,data_len);
- else if(protocol == ISO_14443B)
- annotateIso14443b(explanation,sizeof(explanation),frame,data_len);
+ switch(protocol) {
+ case ICLASS: annotateIclass(explanation,sizeof(explanation),frame,data_len); break;
+ case ISO_14443A: annotateIso14443a(explanation,sizeof(explanation),frame,data_len); break;
+ case ISO_14443B: annotateIso14443b(explanation,sizeof(explanation),frame,data_len); break;
+ case TOPAZ: annotateTopaz(explanation,sizeof(explanation),frame,data_len); break;
+ default: break;
+ }
}
int num_lines = MIN((data_len - 1)/16 + 1, 16);
for (int j = 0; j < num_lines ; j++) {
if (j == 0) {
- PrintAndLog(" %9d | %9d | %s | %-64s| %s| %s",
+ PrintAndLog(" %10d | %10d | %s |%-64s | %s| %s",
(timestamp - first_timestamp),
(EndOfTransmissionTimestamp - first_timestamp),
(isResponse ? "Tag" : "Rdr"),
(j == num_lines-1) ? crc : " ",
(j == num_lines-1) ? explanation : "");
} else {
- PrintAndLog(" | | | %-64s| %s| %s",
+ PrintAndLog(" | | |%-64s | %s| %s",
line[j],
- (j == num_lines-1)?crc:" ",
+ (j == num_lines-1) ? crc : " ",
(j == num_lines-1) ? explanation : "");
}
}
- if (tracepos + sizeof(uint32_t) + sizeof(uint16_t) + sizeof(uint16_t) > traceLen) return traceLen;
+ if (is_last_record(tracepos, trace, traceLen)) return traceLen;
- bool next_isResponse = *((uint16_t *)(trace + tracepos + 6)) & 0x8000;
-
- if (showWaitCycles && !isResponse && next_isResponse) {
+ if (showWaitCycles && !isResponse && next_record_is_response(tracepos, trace)) {
uint32_t next_timestamp = *((uint32_t *)(trace + tracepos));
- if (next_timestamp != 0x44444444) {
- PrintAndLog(" %9d | %9d | %s | fdt (Frame Delay Time): %d",
+ PrintAndLog(" %10d | %10d | %s |fdt (Frame Delay Time): %d",
(EndOfTransmissionTimestamp - first_timestamp),
(next_timestamp - first_timestamp),
" ",
(next_timestamp - EndOfTransmissionTimestamp));
}
- }
return tracepos;
}
int CmdHFList(const char *Cmd)
{
bool showWaitCycles = false;
+ bool markCRCBytes = false;
char type[40] = {0};
int tlen = param_getstr(Cmd,0,type);
- char param = param_getchar(Cmd, 1);
+ char param1 = param_getchar(Cmd, 1);
+ char param2 = param_getchar(Cmd, 2);
bool errors = false;
uint8_t protocol = 0;
//Validate params
- if(tlen == 0)
- {
+
+ if(tlen == 0) {
errors = true;
}
- if(param == 'h' || (param !=0 && param != 'f'))
- {
+
+ if(param1 == 'h'
+ || (param1 != 0 && param1 != 'f' && param1 != 'c')
+ || (param2 != 0 && param2 != 'f' && param2 != 'c')) {
errors = true;
}
- if(!errors)
- {
- if(strcmp(type, "iclass") == 0)
- {
+
+ if(!errors) {
+ if(strcmp(type, "iclass") == 0) {
protocol = ICLASS;
- }else if(strcmp(type, "14a") == 0)
- {
+ } else if(strcmp(type, "14a") == 0) {
protocol = ISO_14443A;
- }
- else if(strcmp(type, "14b") == 0)
- {
+ } else if(strcmp(type, "14b") == 0) {
protocol = ISO_14443B;
- }else if(strcmp(type,"raw")== 0)
- {
+ } else if(strcmp(type,"topaz")== 0) {
+ protocol = TOPAZ;
+ } else if(strcmp(type,"raw")== 0) {
protocol = -1;//No crc, no annotations
}else{
errors = true;
if (errors) {
PrintAndLog("List protocol data in trace buffer.");
- PrintAndLog("Usage: hf list <protocol> [f]");
+ PrintAndLog("Usage: hf list <protocol> [f][c]");
PrintAndLog(" f - show frame delay times as well");
+ PrintAndLog(" c - mark CRC bytes");
PrintAndLog("Supported <protocol> values:");
PrintAndLog(" raw - just show raw data without annotations");
PrintAndLog(" 14a - interpret data as iso14443a communications");
PrintAndLog(" 14b - interpret data as iso14443b communications");
PrintAndLog(" iclass - interpret data as iclass communications");
+ PrintAndLog(" topaz - interpret data as topaz communications");
PrintAndLog("");
PrintAndLog("example: hf list 14a f");
PrintAndLog("example: hf list iclass");
}
- if (param == 'f') {
+ if (param1 == 'f' || param2 == 'f') {
showWaitCycles = true;
}
+ if (param1 == 'c' || param2 == 'c') {
+ markCRCBytes = true;
+ }
uint8_t *trace;
uint16_t tracepos = 0;
PrintAndLog("iso14443a - All times are in carrier periods (1/13.56Mhz)");
PrintAndLog("iClass - Timings are not as accurate");
PrintAndLog("");
- PrintAndLog(" Start | End | Src | Data (! denotes parity error) | CRC | Annotation |");
- PrintAndLog("-----------|-----------|-----|-----------------------------------------------------------------|-----|--------------------|");
+ PrintAndLog(" Start | End | Src | Data (! denotes parity error) | CRC | Annotation |");
+ PrintAndLog("------------|------------|-----|-----------------------------------------------------------------|-----|--------------------|");
while(tracepos < traceLen)
{
- tracepos = printTraceLine(tracepos, traceLen, trace, protocol, showWaitCycles);
+ tracepos = printTraceLine(tracepos, traceLen, trace, protocol, showWaitCycles, markCRCBytes);
}
free(trace);
{"epa", CmdHFEPA, 1, "{ German Identification Card... }"},
{"legic", CmdHFLegic, 0, "{ LEGIC RFIDs... }"},
{"iclass", CmdHFiClass, 1, "{ ICLASS RFIDs... }"},
- {"mf", CmdHFMF, 1, "{ MIFARE RFIDs... }"},
+ {"mf", CmdHFMF, 1, "{ MIFARE RFIDs... }"},
{"mfu", CmdHFMFUltra, 1, "{ MIFARE Ultralight RFIDs... }"},
- {"tune", CmdHFTune, 0, "Continuously measure HF antenna tuning"},
+ {"mfdes", CmdHFMFDes, 1, "{ MIFARE Desfire RFIDs... }"},
+ {"topaz", CmdHFTopaz, 1, "{ TOPAZ (NFC Type 1) RFIDs... }"},
+ {"tune", CmdHFTune, 0, "Continuously measure HF antenna tuning"},
{"list", CmdHFList, 1, "List protocol data in trace buffer"},
{"search", CmdHFSearch, 1, "Search for known HF tags [preliminary]"},
{NULL, NULL, 0, NULL}
int CmdHF(const char *Cmd);
int CmdHFTune(const char *Cmd);
int CmdHFList(const char *Cmd);
+int CmdHFSearch(const char *Cmd);
#endif
#include "cmdmain.h"
#include "mifare.h"
#include "cmdhfmfu.h"
+#include "nonce2key/crapto1.h"
+
+#define llx PRIx64
static int CmdHelp(const char *Cmd);
static void waitCmd(uint8_t iLen);
iso14a_card_select_t card;
memcpy(&card, (iso14a_card_select_t *)resp.d.asBytes, sizeof(iso14a_card_select_t));
- uint64_t select_status = resp.arg[0]; // 0: couldn't read, 1: OK, with ATS, 2: OK, no ATS
+ uint64_t select_status = resp.arg[0]; // 0: couldn't read, 1: OK, with ATS, 2: OK, no ATS, 3: proprietary Anticollision
if(select_status == 0) {
if (Cmd[0] != 's') PrintAndLog("iso14443a card select failed");
case 0x00:
//***************************************test****************
- // disconnect
- c.arg[0] = 0;
- c.arg[1] = 0;
- c.arg[2] = 0;
- SendCommand(&c);
+ ul_switch_off_field();
uint32_t tagT = GetHF14AMfU_Type();
ul_print_type(tagT, 0);
select_status = resp.arg[0]; // 0: couldn't read, 1: OK, with ATS, 2: OK, no ATS
if(select_status == 0) {
- //PrintAndLog("iso14443a card select failed");
- // disconnect
- c.arg[0] = 0;
- c.arg[1] = 0;
- c.arg[2] = 0;
- SendCommand(&c);
+ ul_switch_off_field();
return 0;
}
c.d.asBytes[0] = 0x60;
SendCommand(&c);
WaitForResponse(CMD_ACK,&resp);
-
+
uint8_t version[10] = {0};
memcpy(version, resp.d.asBytes, resp.arg[0] < sizeof(version) ? resp.arg[0] : sizeof(version));
- uint8_t len = resp.arg[0] & 0xff;
- switch ( len ){
- // todo, identify "Magic UL-C tags". // they usually have a static nonce response to 0x1A command.
+ uint8_t len = resp.arg[0] & 0xff;
+ switch ( len){
+ // todo, identify "Magic UL-C tags". // they usually have a static nonce response to 0x1A command.
// UL-EV1, size, check version[6] == 0x0b (smaller) 0x0b * 4 == 48
- case 0x0A:PrintAndLog("TYPE : NXP MIFARE Ultralight EV1 %d bytes", (version[6] == 0xB) ? 48 : 128);break;
+ case 0x0A:PrintAndLog("TYPE : NXP MIFARE Ultralight EV1 %d bytes", (version[6] == 0xB) ? 48 : 128); break;
case 0x01:PrintAndLog("TYPE : NXP MIFARE Ultralight C");break;
- case 0x00:PrintAndLog("TYPE : NXP MIFARE Ultralight");break;
+ case 0x00:PrintAndLog("TYPE : NXP MIFARE Ultralight");break;
}
*/
break;
}
// Double & triple sized UID, can be mapped to a manufacturer.
- // HACK: does this apply for Ultralight cards?
if ( card.uidlen > 4 ) {
PrintAndLog("MANUFACTURER : %s", getTagInfo(card.uid[0]));
}
-
+
// try to request ATS even if tag claims not to support it
if (select_status == 2) {
uint8_t rats[] = { 0xE0, 0x80 }; // FSDI=8 (FSD=256), CID=0
return 1;
}
+
+static int usage_hf_14a_sim(void)
+{
+ PrintAndLog("\n Emulating ISO/IEC 14443 type A tag with 4 or 7 byte UID\n");
+ PrintAndLog("Usage: hf 14a sim t <type> u <uid> x");
+ PrintAndLog(" Options : ");
+ PrintAndLog(" h : this help");
+ PrintAndLog(" t : 1 = MIFARE Classic");
+ PrintAndLog(" 2 = MIFARE Ultralight");
+ PrintAndLog(" 3 = MIFARE Desfire");
+ PrintAndLog(" 4 = ISO/IEC 14443-4");
+ PrintAndLog(" 5 = MIFARE Tnp3xxx");
+ PrintAndLog(" 6 = MIFARE Mini");
+ PrintAndLog(" u : 4 or 7 byte UID");
+ PrintAndLog(" x : (Optional) performs the 'reader attack', nr/ar attack against a legitimate reader");
+ PrintAndLog("\n sample : hf 14a sim t 1 u 1122344");
+ PrintAndLog(" : hf 14a sim t 1 u 1122344 x\n");
+ return 0;
+}
+
// ## simulate iso14443a tag
// ## greg - added ability to specify tag UID
int CmdHF14ASim(const char *Cmd)
{
- UsbCommand c = {CMD_SIMULATE_TAG_ISO_14443a,{0,0,0}};
-
- // Retrieve the tag type
- uint8_t tagtype = param_get8ex(Cmd,0,0,10);
+ bool errors = FALSE;
+ uint8_t flags = 0;
+ uint8_t tagtype = 1;
+ uint64_t uid = 0;
+ uint8_t cmdp = 0;
- // When no argument was given, just print help message
- if (tagtype == 0) {
- PrintAndLog("");
- PrintAndLog(" Emulating ISO/IEC 14443 type A tag with 4 or 7 byte UID");
- PrintAndLog("");
- PrintAndLog(" syntax: hf 14a sim <type> <uid>");
- PrintAndLog(" types: 1 = MIFARE Classic");
- PrintAndLog(" 2 = MIFARE Ultralight");
- PrintAndLog(" 3 = MIFARE Desfire");
- PrintAndLog(" 4 = ISO/IEC 14443-4");
- PrintAndLog(" 5 = MIFARE Tnp3xxx");
- PrintAndLog("");
- return 1;
+ while(param_getchar(Cmd, cmdp) != 0x00)
+ {
+ switch(param_getchar(Cmd, cmdp))
+ {
+ case 'h':
+ case 'H':
+ return usage_hf_14a_sim();
+ case 't':
+ case 'T':
+ // Retrieve the tag type
+ tagtype = param_get8ex(Cmd, cmdp+1, 0, 10);
+ if (tagtype == 0)
+ errors = true;
+ cmdp += 2;
+ break;
+ case 'u':
+ case 'U':
+ // Retrieve the full 4 or 7 byte long uid
+ uid = param_get64ex(Cmd, cmdp+1, 0, 16);
+ if (uid == 0 )
+ errors = TRUE;
+
+ if (uid > 0xffffffff) {
+ PrintAndLog("Emulating ISO/IEC 14443 type A tag with 7 byte UID (%014"llx")",uid);
+ flags |= FLAG_7B_UID_IN_DATA;
+ } else {
+ PrintAndLog("Emulating ISO/IEC 14443 type A tag with 4 byte UID (%08x)",uid);
+ flags |= FLAG_4B_UID_IN_DATA;
+ }
+ cmdp += 2;
+ break;
+ case 'x':
+ case 'X':
+ flags |= FLAG_NR_AR_ATTACK;
+ cmdp++;
+ break;
+ default:
+ PrintAndLog("Unknown parameter '%c'", param_getchar(Cmd, cmdp));
+ errors = true;
+ break;
+ }
+ if(errors) break;
}
+
+ //Validations
+ if (errors) return usage_hf_14a_sim();
+
+ PrintAndLog("Press pm3-button to abort simulation");
- // Store the tag type
- c.arg[0] = tagtype;
-
- // Retrieve the full 4 or 7 byte long uid
- uint64_t long_uid = param_get64ex(Cmd,1,0,16);
-
- // Are we handling the (optional) second part uid?
- if (long_uid > 0xffffffff) {
- PrintAndLog("Emulating ISO/IEC 14443 type A tag with 7 byte UID (%014"llx")",long_uid);
- // Store the second part
- c.arg[2] = (long_uid & 0xffffffff);
- long_uid >>= 32;
- // Store the first part, ignore the first byte, it is replaced by cascade byte (0x88)
- c.arg[1] = (long_uid & 0xffffff);
- } else {
- PrintAndLog("Emulating ISO/IEC 14443 type A tag with 4 byte UID (%08x)",long_uid);
- // Only store the first part
- c.arg[1] = long_uid & 0xffffffff;
+ UsbCommand c = {CMD_SIMULATE_TAG_ISO_14443a,{ tagtype, flags, 0 }};
+ num_to_bytes(uid, 7, c.d.asBytes);
+ SendCommand(&c);
+
+ while(!ukbhit()){
+ UsbCommand resp;
+ WaitForResponseTimeout(CMD_ACK,&resp,1500);
+ PrintAndLog("Got %04X %02X", resp.arg[0], resp.arg[0]);
+ if ( (resp.arg[0] & 0xffff) == CMD_SIMULATE_MIFARE_CARD ){
+ uint8_t data[40];
+ uint8_t key[6];
+ int len = (resp.arg[1] > sizeof(data)) ? sizeof(data) : resp.arg[1];
+ memcpy(data, resp.d.asBytes, len);
+ tryMfk32(uid, data, key);
+ //tryMfk64(uid, data, key);
+ PrintAndLog("--");
+ memset(data,0x00, 40);
+ }
}
-/*
- // At lease save the mandatory first part of the UID
- c.arg[0] = long_uid & 0xffffffff;
+ return 0;
+}
- if (c.arg[1] == 0) {
- PrintAndLog("Emulating ISO/IEC 14443 type A tag with UID %01d %08x %08x",c.arg[0],c.arg[1],c.arg[2]);
+int tryMfk32(uint64_t myuid, uint8_t *data, uint8_t *outputkey ){
+
+ struct Crypto1State *s,*t;
+ uint64_t key; // recovered key
+ uint32_t uid; // serial number
+ uint32_t nt; // tag challenge
+ uint32_t nr0_enc; // first encrypted reader challenge
+ uint32_t ar0_enc; // first encrypted reader response
+ uint32_t nr1_enc; // second encrypted reader challenge
+ uint32_t ar1_enc; // second encrypted reader response
+ bool isSuccess = FALSE;
+ int counter = 0;
+
+ uid = myuid;//(uint32_t)bytes_to_num(data + 0, 4);
+ nt = *(uint32_t*)(data+8);
+ nr0_enc = *(uint32_t*)(data+12);
+ ar0_enc = *(uint32_t*)(data+16);
+ nr1_enc = *(uint32_t*)(data+32);
+ ar1_enc = *(uint32_t*)(data+36);
+
+ // PrintAndLog("Recovering key for:");
+ // PrintAndLog(" uid: %08x",uid);
+ // PrintAndLog(" nt: %08x",nt);
+ // PrintAndLog(" {nr_0}: %08x",nr0_enc);
+ // PrintAndLog(" {ar_0}: %08x",ar0_enc);
+ // PrintAndLog(" {nr_1}: %08x",nr1_enc);
+ // PrintAndLog(" {ar_1}: %08x",ar1_enc);
+
+ s = lfsr_recovery32(ar0_enc ^ prng_successor(nt, 64), 0);
+
+ for(t = s; t->odd | t->even; ++t) {
+ lfsr_rollback_word(t, 0, 0);
+ lfsr_rollback_word(t, nr0_enc, 1);
+ lfsr_rollback_word(t, uid ^ nt, 0);
+ crypto1_get_lfsr(t, &key);
+ crypto1_word(t, uid ^ nt, 0);
+ crypto1_word(t, nr1_enc, 1);
+ if (ar1_enc == (crypto1_word(t, 0, 0) ^ prng_successor(nt, 64))) {
+ PrintAndLog("Found Key: [%012"llx"]",key);
+ isSuccess = TRUE;
+ ++counter;
+ if (counter==10)
+ break;
+ }
}
+ free(s);
+ return isSuccess;
+}
+
+int tryMfk64(uint64_t myuid, uint8_t *data, uint8_t *outputkey ){
+
+ struct Crypto1State *revstate;
+ uint64_t key; // recovered key
+ uint32_t uid; // serial number
+ uint32_t nt; // tag challenge
+ uint32_t nr_enc; // encrypted reader challenge
+ uint32_t ar_enc; // encrypted reader response
+ uint32_t at_enc; // encrypted tag response
+ uint32_t ks2; // keystream used to encrypt reader response
+ uint32_t ks3; // keystream used to encrypt tag response
+
+ struct Crypto1State mpcs = {0, 0};
+ struct Crypto1State *pcs;
+ pcs = &mpcs;
- switch (c.arg[0]) {
- case 1: {
- PrintAndLog("Emulating ISO/IEC 14443-3 type A tag with 4 byte UID");
- UsbCommand c = {CMD_SIMULATE_TAG_ISO_14443a,param_get32ex(Cmd,0,0,10),param_get32ex(Cmd,1,0,16),param_get32ex(Cmd,2,0,16)};
- } break;
- case 2: {
- PrintAndLog("Emulating ISO/IEC 14443-4 type A tag with 7 byte UID");
- } break;
- default: {
- PrintAndLog("Error: unkown tag type (%d)",c.arg[0]);
- PrintAndLog("syntax: hf 14a sim <uid>",c.arg[0]);
- PrintAndLog(" type1: 4 ",c.arg[0]);
-
- return 1;
- } break;
- }
-*/
-/*
- unsigned int hi = 0, lo = 0;
- int n = 0, i = 0;
- while (sscanf(&Cmd[i++], "%1x", &n ) == 1) {
- hi= (hi << 4) | (lo >> 28);
- lo= (lo << 4) | (n & 0xf);
- }
-*/
-// UsbCommand c = {CMD_SIMULATE_TAG_ISO_14443a,param_get32ex(Cmd,0,0,10),param_get32ex(Cmd,1,0,16),param_get32ex(Cmd,2,0,16)};
-// PrintAndLog("Emulating ISO/IEC 14443 type A tag with UID %01d %08x %08x",c.arg[0],c.arg[1],c.arg[2]);
- SendCommand(&c);
- return 0;
+
+
+ uid = myuid;//(uint32_t)bytes_to_num(data + 0, 4);
+ nt = *(uint32_t*)(data+8);
+ nr_enc = *(uint32_t*)(data+12);
+ ar_enc = *(uint32_t*)(data+16);
+
+ crypto1_word(pcs, nr_enc , 1);
+ at_enc = prng_successor(nt, 96) ^ crypto1_word(pcs, 0, 0);
+
+ // printf("Recovering key for:\n");
+ // printf(" uid: %08x\n",uid);
+ // printf(" nt: %08x\n",nt);
+ // printf(" {nr}: %08x\n",nr_enc);
+ // printf(" {ar}: %08x\n",ar_enc);
+ // printf(" {at}: %08x\n",at_enc);
+
+ // Extract the keystream from the messages
+ ks2 = ar_enc ^ prng_successor(nt, 64);
+ ks3 = at_enc ^ prng_successor(nt, 96);
+
+ revstate = lfsr_recovery64(ks2, ks3);
+ lfsr_rollback_word(revstate, 0, 0);
+ lfsr_rollback_word(revstate, 0, 0);
+ lfsr_rollback_word(revstate, nr_enc, 1);
+ lfsr_rollback_word(revstate, uid ^ nt, 0);
+ crypto1_get_lfsr(revstate, &key);
+ PrintAndLog("Found Key: [%012"llx"]",key);
+ crypto1_destroy(revstate);
+ crypto1_destroy(pcs);
+ return 0;
}
-int CmdHF14ASnoop(const char *Cmd) {
+int CmdHF14ASniff(const char *Cmd) {
int param = 0;
uint8_t ctmp = param_getchar(Cmd, 0) ;
if (ctmp == 'h' || ctmp == 'H') {
PrintAndLog("It get data from the field and saves it into command buffer.");
- PrintAndLog("Buffer accessible from command hf list 14a.");
- PrintAndLog("Usage: hf 14a snoop [c][r]");
+ PrintAndLog("Buffer accessible from command 'hf list 14a'");
+ PrintAndLog("Usage: hf 14a sniff [c][r]");
PrintAndLog("c - triggered by first data from card");
PrintAndLog("r - triggered by first 7-bit request from reader (REQ,WUP,...)");
- PrintAndLog("sample: hf 14a snoop c r");
+ PrintAndLog("sample: hf 14a sniff c r");
return 0;
}
return 0;
}
+
int CmdHF14ACmdRaw(const char *cmd) {
UsbCommand c = {CMD_READER_ISO_14443a, {0, 0, 0}};
- uint8_t reply=1;
- uint8_t crc=0;
- uint8_t power=0;
- uint8_t active=0;
- uint8_t active_select=0;
+ bool reply=1;
+ bool crc = FALSE;
+ bool power = FALSE;
+ bool active = FALSE;
+ bool active_select = FALSE;
uint16_t numbits=0;
+ bool bTimeout = FALSE;
uint32_t timeout=0;
- uint8_t bTimeout=0;
+ bool topazmode = FALSE;
char buf[5]="";
int i=0;
uint8_t data[USB_CMD_DATA_SIZE];
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");
PrintAndLog(" -s active signal field ON with select");
PrintAndLog(" -b number of bits to send. Useful for send partial byte");
PrintAndLog(" -t timeout in ms");
+ PrintAndLog(" -T use Topaz protocol to send command");
return 0;
}
+
// strip
while (*cmd==' ' || *cmd=='\t') cmd++;
if (cmd[i]=='-') {
switch (cmd[i+1]) {
case 'r':
- reply=0;
+ reply = FALSE;
break;
case 'c':
- crc=1;
+ crc = TRUE;
break;
case 'p':
- power=1;
+ power = TRUE;
break;
case 'a':
- active=1;
+ active = TRUE;
break;
case 's':
- active_select=1;
+ active_select = TRUE;
break;
case 'b':
sscanf(cmd+i+2,"%d",&temp);
i-=2;
break;
case 't':
- bTimeout=1;
+ bTimeout = TRUE;
sscanf(cmd+i+2,"%d",&temp);
timeout = temp;
i+=3;
while(cmd[i]!=' ' && cmd[i]!='\0') { i++; }
i-=2;
break;
+ case 'T':
+ topazmode = TRUE;
+ break;
default:
PrintAndLog("Invalid option");
return 0;
sscanf(buf,"%x",&temp);
data[datalen]=(uint8_t)(temp & 0xff);
*buf=0;
- if (++datalen>sizeof(data)){
+ if (++datalen >= sizeof(data)){
if (crc)
PrintAndLog("Buffer is full, we can't add CRC to your data");
break;
PrintAndLog("Invalid char on input");
return 0;
}
+
if(crc && datalen>0 && datalen<sizeof(data)-2)
{
uint8_t first, second;
- ComputeCrc14443(CRC_14443_A, data, datalen, &first, &second);
+ if (topazmode) {
+ ComputeCrc14443(CRC_14443_B, data, datalen, &first, &second);
+ } else {
+ ComputeCrc14443(CRC_14443_A, data, datalen, &first, &second);
+ }
data[datalen++] = first;
data[datalen++] = second;
}
}
if(bTimeout){
- #define MAX_TIMEOUT 40542464 // (2^32-1) * (8*16) / 13560000Hz * 1000ms/s =
+ #define MAX_TIMEOUT 40542464 // = (2^32-1) * (8*16) / 13560000Hz * 1000ms/s
c.arg[0] |= ISO14A_SET_TIMEOUT;
if(timeout > MAX_TIMEOUT) {
timeout = MAX_TIMEOUT;
}
c.arg[2] = 13560000 / 1000 / (8*16) * timeout; // timeout in ETUs (time to transfer 1 bit, approx. 9.4 us)
}
+
if(power)
c.arg[0] |= ISO14A_NO_DISCONNECT;
+
if(datalen>0)
c.arg[0] |= ISO14A_RAW;
+ if(topazmode)
+ c.arg[0] |= ISO14A_TOPAZMODE;
+
// Max buffer is USB_CMD_DATA_SIZE
c.arg[1] = (datalen & 0xFFFF) | (numbits << 16);
memcpy(c.d.asBytes,data,datalen);
return 0;
}
+
static void waitCmd(uint8_t iSelect)
{
uint8_t *recv;
{"reader", CmdHF14AReader, 0, "Act like an ISO14443 Type A reader"},
{"cuids", CmdHF14ACUIDs, 0, "<n> Collect n>0 ISO14443 Type A UIDs in one go"},
{"sim", CmdHF14ASim, 0, "<UID> -- Simulate ISO 14443a tag"},
- {"snoop", CmdHF14ASnoop, 0, "Eavesdrop ISO 14443 Type A"},
+ {"sniff", CmdHF14ASniff, 0, "sniff ISO 14443 Type A traffic"},
{"raw", CmdHF14ACmdRaw, 0, "Send raw hex data to tag"},
{NULL, NULL, 0, NULL}
};
WaitForResponseTimeout(CMD_ACK,NULL,100);
// parse
- CmdsParse(CommandTable, Cmd);
- return 0;
+ CmdsParse(CommandTable, Cmd);
+ return 0;
}
int CmdHelp(const char *Cmd)
int CmdHF14AMifare(const char *Cmd);
int CmdHF14AReader(const char *Cmd);
int CmdHF14ASim(const char *Cmd);
-int CmdHF14ASnoop(const char *Cmd);
+int CmdHF14ASniff(const char *Cmd);
char* getTagInfo(uint8_t uid);
+int tryMfk32(uint64_t myuid, uint8_t *data, uint8_t *outputkey );
+int tryMfk64(uint64_t myuid, uint8_t *data, uint8_t *outputkey );
#endif
{ 0xE02E000000000000LL, 16, "Broadcom Corporation USA" },
{ 0xE02F000000000000LL, 16, "MStar Semiconductor, Inc Taiwan, ROC" },
{ 0xE030000000000000LL, 16, "BeeDar Technology Inc. USA" },
- { 0xE031000000000000LL, 16, " RFIDsec Denmark" },
- { 0xE032000000000000LL, 16, " Schweizer Electronic AG Germany" },
- { 0xE033000000000000LL, 16, " AMIC Technology Corp Taiwan" },
+ { 0xE031000000000000LL, 16, "RFIDsec Denmark" },
+ { 0xE032000000000000LL, 16, "Schweizer Electronic AG Germany" },
+ { 0xE033000000000000LL, 16, "AMIC Technology Corp Taiwan" },
{ 0xE034000000000000LL, 16, "Mikron JSC Russia" },
{ 0xE035000000000000LL, 16, "Fraunhofer Institute for Photonic Microsystems Germany" },
{ 0xE036000000000000LL, 16, "IDS Microchip AG Switzerland" },
*/
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;
}
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"
UsbCommand resp;
while(!ukbhit()){
if (WaitForResponseTimeout(CMD_ACK,&resp, 4500)) {
- uint8_t readStatus = resp.arg[0] & 0xff;
+ uint8_t readStatus = resp.arg[0] & 0xff;
uint8_t *data = resp.d.asBytes;
if (verbose)
- PrintAndLog("Readstatus:%02x", readStatus);
+ PrintAndLog("Readstatus:%02x", readStatus);
if( readStatus == 0){
//Aborted
if (verbose) PrintAndLog("Quitting...");
PrintAndLog("Usage: hf mf chk <block number>|<*card memory> <key type (A/B/?)> [t|d] [<key (12 hex symbols)>] [<dic (*.dic)>]");\r
PrintAndLog(" * - all sectors");\r
PrintAndLog("card memory - 0 - MINI(320 bytes), 1 - 1K, 2 - 2K, 4 - 4K, <other> - 1K");\r
- PrintAndLog("d - write keys to binary file\n");\r
- PrintAndLog("t - write keys to emulator memory");\r
+ PrintAndLog("d - write keys to binary file");\r
+ PrintAndLog("t - write keys to emulator memory\n");\r
PrintAndLog(" sample: hf mf chk 0 A 1234567890ab keys.dic");\r
PrintAndLog(" hf mf chk *1 ? t");\r
PrintAndLog(" hf mf chk *1 ? d");\r
if (fgets(buf, sizeof(buf), f) == NULL) {\r
fclose(f);\r
PrintAndLog("File reading error.");\r
+ fclose(f);\r
return 2;\r
}\r
\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 "loclass/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"
+#include "cmdhf14a.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", getTagInfo(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", getTagInfo(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;
+}
+
+/*
+ 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 )
+ 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 (Unknown)", 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 * 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 "cmdhf14a.h"
#include "mifare.h"
#include "util.h"
-#include "protocols.h"
+#include "../common/protocols.h"
#include "data.h"
#define MAX_UL_BLOCKS 0x0f
return len;
}
+static int ul_auth_select( iso14a_card_select_t *card, TagTypeUL_t tagtype, bool hasAuthKey, uint8_t *authenticationkey, uint8_t *pack, uint8_t packSize){
+ if ( hasAuthKey && (tagtype & UL_C)) {
+ //will select card automatically and close connection on error
+ if (!ulc_authentication(authenticationkey, false)) {
+ PrintAndLog("Error: Authentication Failed UL-C");
+ return 0;
+ }
+
+ memcpy(card, resp.d.asBytes, sizeof(iso14a_card_select_t));
+ return 1;
+}
+
+// This read command will at least return 16bytes.
+static int ul_read( uint8_t page, uint8_t *response, uint16_t responseLength ){
+
+ uint8_t cmd[] = {ISO14443A_CMD_READBLOCK, page};
+ int len = ul_send_cmd_raw(cmd, sizeof(cmd), response, responseLength);
+ return len;
+}
+
+static int ul_comp_write( uint8_t page, uint8_t *data, uint8_t datalen ){
+
+ uint8_t cmd[18];
+ memset(cmd, 0x00, sizeof(cmd));
+ datalen = ( datalen > 16) ? 16 : datalen;
+
+ cmd[0] = ISO14443A_CMD_WRITEBLOCK;
+ cmd[1] = page;
+ memcpy(cmd+2, data, datalen);
+
+ uint8_t response[1] = {0xff};
+ ul_send_cmd_raw(cmd, 2+datalen, response, sizeof(response));
+ // ACK
+ if ( response[0] == 0x0a ) return 0;
+ // NACK
+ return -1;
+}
+
+static int ulc_requestAuthentication( uint8_t *nonce, uint16_t nonceLength ){
+
+ uint8_t cmd[] = {MIFARE_ULC_AUTH_1, 0x00};
+ int len = ul_send_cmd_raw(cmd, sizeof(cmd), nonce, nonceLength);
+ return len;
+}
+
+static int ulc_authentication( uint8_t *key, bool switch_off_field ){
+
+ UsbCommand c = {CMD_MIFAREUC_AUTH, {switch_off_field}};
+ memcpy(c.d.asBytes, key, 16);
+ SendCommand(&c);
+ UsbCommand resp;
+ if ( !WaitForResponseTimeout(CMD_ACK, &resp, 1500) ) return 0;
+ if ( resp.arg[0] == 1 ) return 1;
+
+ return 0;
+}
+
+static int ulev1_requestAuthentication( uint8_t *pwd, uint8_t *pack, uint16_t packLength ){
+
+ uint8_t cmd[] = {MIFARE_ULEV1_AUTH, pwd[0], pwd[1], pwd[2], pwd[3]};
+ int len = ul_send_cmd_raw(cmd, sizeof(cmd), pack, packLength);
+ return len;
+}
+
static int ul_auth_select( iso14a_card_select_t *card, TagTypeUL_t tagtype, bool hasAuthKey, uint8_t *authenticationkey, uint8_t *pack, uint8_t packSize){
if ( hasAuthKey && (tagtype & UL_C)) {
//will select card automatically and close connection on error
dataLen /= 2; // handled as bytes from now on
} else {
PrintAndLog("\nERROR: Key is incorrect length\n");
- errors = true;
+ errors = true;
+ }
+ cmdp += 2;
+ hasAuthKey = true;
+ break;
+ case 'l':
+ case 'L':
+ swapEndian = true;
+ cmdp++;
+ break;
+ default:
+ PrintAndLog("Unknown parameter '%c'", param_getchar(Cmd, cmdp));
+ errors = true;
+ break;
+ }
+ if(errors) break;
+ }
+
+ //Validations
+ if(errors) return usage_hf_mfu_info();
+
+ TagTypeUL_t tagtype = GetHF14AMfU_Type();
+ if (tagtype == UL_ERROR) return -1;
+
+ PrintAndLog("\n--- Tag Information ---------");
+ PrintAndLog("-------------------------------------------------------------");
+ ul_print_type(tagtype, 6);
+
+ // Swap endianness
+ if (swapEndian && hasAuthKey) authkeyptr = SwapEndian64(authenticationkey, dataLen, (dataLen == 16) ? 8 : 4 );
+
+ if (!ul_auth_select( &card, tagtype, hasAuthKey, authkeyptr, pack, sizeof(pack))) return -1;
+
+ // read pages 0,1,2,3 (should read 4pages)
+ status = ul_read(0, data, sizeof(data));
+ if ( status == -1 ) {
+ ul_switch_off_field();
+ PrintAndLog("Error: tag didn't answer to READ");
+ return status;
+ } else if (status == 16) {
+ ul_print_default(data);
+ ndef_print_CC(data+12);
+ } else {
+ locked = true;
+ }
+
+ // UL_C Specific
+ if ((tagtype & UL_C)) {
+
+ // read pages 0x28, 0x29, 0x2A, 0x2B
+ uint8_t ulc_conf[16] = {0x00};
+ status = ul_read(0x28, ulc_conf, sizeof(ulc_conf));
+ if ( status == -1 ){
+ PrintAndLog("Error: tag didn't answer to READ UL-C");
+ ul_switch_off_field();
+ return status;
+ }
+ if (status == 16) ulc_print_configuration(ulc_conf);
+ else locked = true;
+
+ if ((tagtype & MAGIC)) {
+ //just read key
+ uint8_t ulc_deskey[16] = {0x00};
+ status = ul_read(0x2C, ulc_deskey, sizeof(ulc_deskey));
+ if ( status == -1 ) {
+ ul_switch_off_field();
+ PrintAndLog("Error: tag didn't answer to READ magic");
+ return status;
+ }
+ if (status == 16) ulc_print_3deskey(ulc_deskey);
+
+ } else {
+ ul_switch_off_field();
+ // if we called info with key, just return
+ if ( hasAuthKey ) return 1;
+
+ // also try to diversify default keys.. look into CmdHF14AMfuGenDiverseKeys
+ PrintAndLog("Trying some default 3des keys");
+ for (uint8_t i = 0; i < KEYS_3DES_COUNT; ++i ) {
+ key = default_3des_keys[i];
+ if (ulc_authentication(key, true)) {
+ PrintAndLog("Found default 3des key: ");
+ uint8_t keySwap[16];
+ memcpy(keySwap, SwapEndian64(key,16,8), 16);
+ ulc_print_3deskey(keySwap);
+ return 1;
+ }
+ }
+ return 1;
+ }
+ }
+
+ // do counters and signature first (don't neet auth)
+
+ // ul counters are different than ntag counters
+ if ((tagtype & (UL_EV1_48 | UL_EV1_128))) {
+ if (ulev1_print_counters() != 3) {
+ // failed - re-select
+ if (!ul_auth_select( &card, tagtype, hasAuthKey, authkeyptr, pack, sizeof(pack))) return -1;
+ }
+ }
+
+ if ((tagtype & (UL_EV1_48 | UL_EV1_128 | NTAG_213 | NTAG_215 | NTAG_216 | NTAG_I2C_1K | NTAG_I2C_2K ))) {
+ uint8_t ulev1_signature[32] = {0x00};
+ status = ulev1_readSignature( ulev1_signature, sizeof(ulev1_signature));
+ if ( status == -1 ) {
+ PrintAndLog("Error: tag didn't answer to READ SIGNATURE");
+ ul_switch_off_field();
+ return status;
+ }
+ if (status == 32) ulev1_print_signature( ulev1_signature, sizeof(ulev1_signature));
+ else {
+ // re-select
+ if (!ul_auth_select( &card, tagtype, hasAuthKey, authkeyptr, pack, sizeof(pack))) return -1;
+ }
+ }
+
+ if ((tagtype & (UL_EV1_48 | UL_EV1_128 | NTAG_210 | NTAG_212 | NTAG_213 | NTAG_215 | NTAG_216 | NTAG_I2C_1K | NTAG_I2C_2K))) {
+ uint8_t version[10] = {0x00};
+ status = ulev1_getVersion(version, sizeof(version));
+ if ( status == -1 ) {
+ PrintAndLog("Error: tag didn't answer to GETVERSION");
+ ul_switch_off_field();
+ return status;
+ } else if (status == 10) {
+ ulev1_print_version(version);
+ } else {
+ locked = true;
+ if (!ul_auth_select( &card, tagtype, hasAuthKey, authkeyptr, pack, sizeof(pack))) return -1;
+ }
+
+ uint8_t startconfigblock = 0;
+ uint8_t ulev1_conf[16] = {0x00};
+ // config blocks always are last 4 pages
+ for (uint8_t idx = 0; idx < MAX_UL_TYPES; idx++)
+ if (tagtype & UL_TYPES_ARRAY[idx])
+ startconfigblock = UL_MEMORY_ARRAY[idx]-3;
+
+ if (startconfigblock){ // if we know where the config block is...
+ status = ul_read(startconfigblock, ulev1_conf, sizeof(ulev1_conf));
+ if ( status == -1 ) {
+ PrintAndLog("Error: tag didn't answer to READ EV1");
+ ul_switch_off_field();
+ return status;
+ } else if (status == 16) {
+ // save AUTHENTICATION LIMITS for later:
+ authlim = (ulev1_conf[4] & 0x07);
+ ulev1_print_configuration(ulev1_conf, startconfigblock);
+ }
+ }
+
+ // AUTHLIMIT, (number of failed authentications)
+ // 0 = limitless.
+ // 1-7 = limit. No automatic tries then.
+ // hasAuthKey, if we was called with key, skip test.
+ if ( !authlim && !hasAuthKey ) {
+ PrintAndLog("\n--- Known EV1/NTAG passwords.");
+ len = 0;
+ for (uint8_t i = 0; i < KEYS_PWD_COUNT; ++i ) {
+ key = default_pwd_pack[i];
+ len = ulev1_requestAuthentication(key, pack, sizeof(pack));
+ if (len >= 1) {
+ PrintAndLog("Found a default password: %s || Pack: %02X %02X",sprint_hex(key, 4), pack[0], pack[1]);
+ break;
+ } else {
+ if (!ul_auth_select( &card, tagtype, hasAuthKey, authkeyptr, pack, sizeof(pack))) return -1;
+ }
+ }
+ if (len < 1) PrintAndLog("password not known");
+ }
+ }
+
+ ul_switch_off_field();
+ if (locked) PrintAndLog("\nTag appears to be locked, try using the key to get more info");
+ PrintAndLog("");
+ return 1;
+}
+
+//
+// Mifare Ultralight Write Single Block
+//
+int CmdHF14AMfUWrBl(const char *Cmd){
+ uint8_t blockNo = -1;
+ bool chinese_card = FALSE;
+ uint8_t bldata[16] = {0x00};
+ UsbCommand resp;
+
+ PrintAndLog("\n--- Tag Configuration");
+
+ bool strg_mod_en = (data[0] & 2);
+ uint8_t authlim = (data[4] & 0x07);
+ bool cfglck = (data[4] & 0x40);
+ bool prot = (data[4] & 0x80);
+ uint8_t vctid = data[5];
+
+ PrintAndLog(" cfg0 [16/0x10]: %s", sprint_hex(data, 4));
+ if ( data[3] < 0xff )
+ PrintAndLog(" - page %d and above need authentication",data[3]);
+ else
+ PrintAndLog(" - pages don't need authentication");
+ PrintAndLog(" - strong modulation mode %s", (strg_mod_en) ? "enabled":"disabled");
+ PrintAndLog(" cfg1 [17/0x11]: %s", sprint_hex(data+4, 4) );
+ if ( authlim == 0)
+ PrintAndLog(" - Unlimited password attempts");
+ else
+ PrintAndLog(" - Max number of password attempts is %d", authlim);
+ PrintAndLog(" - user configuration %s", cfglck ? "permanently locked":"writeable");
+ PrintAndLog(" - %s access is protected with password", prot ? "read and write":"write");
+ PrintAndLog(" %02X - Virtual Card Type Identifier is %s default", vctid, (vctid==0x05)? "":"not");
+ PrintAndLog(" PWD [18/0x12]: %s", sprint_hex(data+8, 4));
+ PrintAndLog(" PACK [19/0x13]: %s", sprint_hex(data+12, 4));
+ return 0;
+}
+
+static int ulev1_print_counters(){
+ PrintAndLog("--- Tag Counters");
+ uint8_t tear[1] = {0};
+ uint8_t counter[3] = {0,0,0};
+ uint16_t len = 0;
+ for ( uint8_t i = 0; i<3; ++i) {
+ ulev1_readTearing(i,tear,sizeof(tear));
+ len = ulev1_readCounter(i,counter, sizeof(counter) );
+ if (len == 3) {
+ PrintAndLog(" [%0d] : %s", i, sprint_hex(counter,3));
+ PrintAndLog(" - %02X tearing %s", tear[0], ( tear[0]==0xBD)?"Ok":"failure");
+ }
+ }
+ return len;
+}
+
+static int ulev1_print_signature( uint8_t *data, uint8_t len){
+ PrintAndLog("\n--- Tag Signature");
+ //PrintAndLog("IC signature public key name : NXP NTAG21x 2013"); // don't know if there is other NXP public keys.. :(
+ PrintAndLog("IC signature public key value : 04494e1a386d3d3cfe3dc10e5de68a499b1c202db5b132393e89ed19fe5be8bc61");
+ PrintAndLog(" Elliptic curve parameters : secp128r1");
+ PrintAndLog(" Tag ECC Signature : %s", sprint_hex(data, len));
+ //to do: verify if signature is valid
+ //PrintAndLog("IC signature status: %s valid", (iseccvalid() )?"":"not");
+ return 0;
+}
+
+static int ulev1_print_version(uint8_t *data){
+ PrintAndLog("\n--- Tag Version");
+ PrintAndLog(" Raw bytes : %s", sprint_hex(data, 8) );
+ PrintAndLog(" Vendor ID : %02X, %s", data[1], getTagInfo(data[1]));
+ PrintAndLog(" Product type : %s" , getProductTypeStr(data[2]));
+ PrintAndLog(" Product subtype : %02X, %s" , data[3], (data[3]==1) ?"17 pF":"50pF");
+ PrintAndLog(" Major version : %02X" , data[4]);
+ PrintAndLog(" Minor version : %02X" , data[5]);
+ PrintAndLog(" Size : %s", getUlev1CardSizeStr(data[6]));
+ PrintAndLog(" Protocol type : %02X" , data[7]);
+ return 0;
+}
+
+/*
+static int ulc_magic_test(){
+ // Magic Ultralight test
+ // Magic UL-C, by observation,
+ // 1) it seems to have a static nonce response to 0x1A command.
+ // 2) the deskey bytes is not-zero:d out on as datasheet states.
+ // 3) UID - changeable, not only, but pages 0-1-2-3.
+ // 4) use the ul_magic_test ! magic tags answers specially!
+ int returnValue = UL_ERROR;
+ iso14a_card_select_t card;
+ uint8_t nonce1[11] = {0x00};
+ uint8_t nonce2[11] = {0x00};
+ int status = ul_select(&card);
+ if ( !status ){
+ return UL_ERROR;
+ }
+ status = ulc_requestAuthentication(nonce1, sizeof(nonce1));
+ if ( status > 0 ) {
+ status = ulc_requestAuthentication(nonce2, sizeof(nonce2));
+ returnValue = ( !memcmp(nonce1, nonce2, 11) ) ? UL_C_MAGIC : UL_C;
+ } else {
+ returnValue = UL;
+ }
+ ul_switch_off_field();
+ return returnValue;
+}
+*/
+static int ul_magic_test(){
+
+ // Magic Ultralight tests
+ // 1) take present UID, and try to write it back. OBSOLETE
+ // 2) make a wrong length write to page0, and see if tag answers with ACK/NACK:
+ iso14a_card_select_t card;
+ if ( !ul_select(&card) )
+ return UL_ERROR;
+ int status = ul_comp_write(0, NULL, 0);
+ ul_switch_off_field();
+ if ( status == 0 )
+ return MAGIC;
+ return 0;
+}
+
+ if (blockNo > MAX_UL_BLOCKS){
+ PrintAndLog("Error: Maximum number of blocks is 15 for Ultralight Cards!");
+ return 1;
+ }
+
+ if ( card.uid[0] != 0x05) {
+
+ len = ulev1_getVersion(version, sizeof(version));
+ ul_switch_off_field();
+
+ switch (len) {
+ case 0x0A: {
+
+ if ( version[2] == 0x03 && version[6] == 0x0B )
+ tagtype = UL_EV1_48;
+ else if ( version[2] == 0x03 && version[6] != 0x0B )
+ tagtype = UL_EV1_128;
+ else if ( version[2] == 0x04 && version[3] == 0x01 && version[6] == 0x0B )
+ tagtype = NTAG_210;
+ else if ( version[2] == 0x04 && version[3] == 0x01 && version[6] == 0x0E )
+ tagtype = NTAG_212;
+ else if ( version[2] == 0x04 && version[3] == 0x02 && version[6] == 0x0F )
+ tagtype = NTAG_213;
+ else if ( version[2] == 0x04 && version[3] == 0x02 && version[6] == 0x11 )
+ tagtype = NTAG_215;
+ else if ( version[2] == 0x04 && version[3] == 0x02 && version[6] == 0x13 )
+ tagtype = NTAG_216;
+ else if ( version[2] == 0x04 && version[3] == 0x05 && version[6] == 0x13 )
+ tagtype = NTAG_I2C_1K;
+ else if ( version[2] == 0x04 && version[3] == 0x05 && version[6] == 0x15 )
+ tagtype = NTAG_I2C_2K;
+ else if ( version[2] == 0x04 )
+ tagtype = NTAG;
+
+ break;
+ }
+ case 0x01: tagtype = UL_C; break;
+ case 0x00: tagtype = UL; break;
+ case -1 : tagtype = (UL | UL_C | NTAG_203); break; // could be UL | UL_C magic tags
+ default : tagtype = UNKNOWN; break;
+ }
+ // UL vs UL-C vs ntag203 test
+ if (tagtype & (UL | UL_C | NTAG_203)) {
+ if ( !ul_select(&card) ) return UL_ERROR;
+
+ // do UL_C check first...
+ uint8_t nonce[11] = {0x00};
+ status = ulc_requestAuthentication(nonce, sizeof(nonce));
+ ul_switch_off_field();
+ if (status > 1) {
+ tagtype = UL_C;
+ } else {
+ // need to re-select after authentication error
+ if ( !ul_select(&card) ) return UL_ERROR;
+
+ uint8_t data[16] = {0x00};
+ // read page 0x26-0x29 (last valid ntag203 page)
+ status = ul_read(0x26, data, sizeof(data));
+ if ( status <= 1 ) {
+ tagtype = UL;
+ } else {
+ // read page 0x30 (should error if it is a ntag203)
+ status = ul_read(0x30, data, sizeof(data));
+ if ( status <= 1 ){
+ tagtype = NTAG_203;
+ } else {
+ tagtype = UNKNOWN;
+ }
+ }
+ ul_switch_off_field();
+ }
+ }
+ } else {
+ // Infinition MY-D tests Exam high nibble
+ uint8_t nib = (card.uid[1] & 0xf0) >> 4;
+ switch ( nib ){
+ case 1: tagtype = MY_D; break;
+ case 2: tagtype = (MY_D | MY_D_NFC); break; //notice: we can not currently distinguish between these two
+ case 3: tagtype = (MY_D_MOVE | MY_D_MOVE_NFC); break; //notice: we can not currently distinguish between these two
+ }
+ }
+
+
+ tagtype |= ul_magic_test();
+ if (tagtype == (UNKNOWN | MAGIC)) tagtype = (UL_MAGIC);
+ return tagtype;
+}
+
+int CmdHF14AMfUInfo(const char *Cmd){
+
+ uint8_t authlim = 0xff;
+ uint8_t data[16] = {0x00};
+ iso14a_card_select_t card;
+ int status;
+ bool errors = false;
+ bool hasAuthKey = false;
+ bool locked = false;
+ bool swapEndian = false;
+ uint8_t cmdp = 0;
+ uint8_t dataLen = 0;
+ uint8_t authenticationkey[16] = {0x00};
+ uint8_t *authkeyptr = authenticationkey;
+ uint8_t *key;
+ uint8_t pack[4] = {0,0,0,0};
+ int len = 0;
+ char tempStr[50];
+
+ while(param_getchar(Cmd, cmdp) != 0x00)
+ {
+ switch(param_getchar(Cmd, cmdp))
+ {
+ case 'h':
+ case 'H':
+ return usage_hf_mfu_info();
+ case 'k':
+ case 'K':
+ dataLen = param_getstr(Cmd, cmdp+1, tempStr);
+ if (dataLen == 32 || dataLen == 8) { //ul-c or ev1/ntag key length
+ errors = param_gethex(tempStr, 0, authenticationkey, dataLen);
+ dataLen /= 2; // handled as bytes from now on
+ } else {
+ PrintAndLog("\nERROR: Key is incorrect length\n");
+ errors = true;
}
cmdp += 2;
hasAuthKey = true;
//Validations
if(errors) return usage_hf_mfu_info();
-
+
TagTypeUL_t tagtype = GetHF14AMfU_Type();
if (tagtype == UL_ERROR) return -1;
PrintAndLog("\n--- Tag Information ---------");
PrintAndLog("-------------------------------------------------------------");
ul_print_type(tagtype, 6);
-
+
// Swap endianness
if (swapEndian && hasAuthKey) authkeyptr = SwapEndian64(authenticationkey, dataLen, (dataLen == 16) ? 8 : 4 );
-
+
if (!ul_auth_select( &card, tagtype, hasAuthKey, authkeyptr, pack, sizeof(pack))) return -1;
// read pages 0,1,2,3 (should read 4pages)
status = ul_read(0, data, sizeof(data));
- if ( status == -1 ) {
+ if ( status == -1 ){
ul_switch_off_field();
PrintAndLog("Error: tag didn't answer to READ");
return status;
} else if (status == 16) {
ul_print_default(data);
ndef_print_CC(data+12);
- } else {
+ } else {
locked = true;
}
// UL_C Specific
- if ((tagtype & UL_C)) {
-
+ if ((tagtype & UL_C)){
+
// read pages 0x28, 0x29, 0x2A, 0x2B
uint8_t ulc_conf[16] = {0x00};
status = ul_read(0x28, ulc_conf, sizeof(ulc_conf));
if (status == 16) ulc_print_configuration(ulc_conf);
else locked = true;
- if ((tagtype & MAGIC)) {
+ if ((tagtype & MAGIC)){
//just read key
uint8_t ulc_deskey[16] = {0x00};
status = ul_read(0x2C, ulc_deskey, sizeof(ulc_deskey));
- if ( status == -1 ) {
+ if ( status == -1 ){
ul_switch_off_field();
PrintAndLog("Error: tag didn't answer to READ magic");
return status;
ul_switch_off_field();
// if we called info with key, just return
if ( hasAuthKey ) return 1;
-
+
// also try to diversify default keys.. look into CmdHF14AMfuGenDiverseKeys
PrintAndLog("Trying some default 3des keys");
- for (uint8_t i = 0; i < KEYS_3DES_COUNT; ++i ) {
+ for (uint8_t i = 0; i < KEYS_3DES_COUNT; ++i ){
key = default_3des_keys[i];
- if (ulc_authentication(key, true)) {
+ if (ulc_authentication(key, true)){
PrintAndLog("Found default 3des key: ");
uint8_t keySwap[16];
memcpy(keySwap, SwapEndian64(key,16,8), 16);
if ((tagtype & (UL_EV1_48 | UL_EV1_128 | NTAG_213 | NTAG_215 | NTAG_216 | NTAG_I2C_1K | NTAG_I2C_2K ))) {
uint8_t ulev1_signature[32] = {0x00};
status = ulev1_readSignature( ulev1_signature, sizeof(ulev1_signature));
- if ( status == -1 ) {
+ if ( status == -1 ){
PrintAndLog("Error: tag didn't answer to READ SIGNATURE");
ul_switch_off_field();
return status;
- }
+ }
if (status == 32) ulev1_print_signature( ulev1_signature, sizeof(ulev1_signature));
else {
// re-select
if (!ul_auth_select( &card, tagtype, hasAuthKey, authkeyptr, pack, sizeof(pack))) return -1;
}
}
-
+
if ((tagtype & (UL_EV1_48 | UL_EV1_128 | NTAG_210 | NTAG_212 | NTAG_213 | NTAG_215 | NTAG_216 | NTAG_I2C_1K | NTAG_I2C_2K))) {
uint8_t version[10] = {0x00};
status = ulev1_getVersion(version, sizeof(version));
- if ( status == -1 ) {
+ if ( status == -1 ){
PrintAndLog("Error: tag didn't answer to GETVERSION");
ul_switch_off_field();
return status;
startconfigblock = UL_MEMORY_ARRAY[idx]-3;
if (startconfigblock){ // if we know where the config block is...
- status = ul_read(startconfigblock, ulev1_conf, sizeof(ulev1_conf));
- if ( status == -1 ) {
- PrintAndLog("Error: tag didn't answer to READ EV1");
- ul_switch_off_field();
- return status;
- } else if (status == 16) {
- // save AUTHENTICATION LIMITS for later:
- authlim = (ulev1_conf[4] & 0x07);
- ulev1_print_configuration(ulev1_conf, startconfigblock);
+ status = ul_read(startconfigblock, ulev1_conf, sizeof(ulev1_conf));
+ if ( status == -1 ) {
+ PrintAndLog("Error: tag didn't answer to READ EV1");
+ ul_switch_off_field();
+ return status;
+ } else if (status == 16) {
+ // save AUTHENTICATION LIMITS for later:
+ authlim = (ulev1_conf[4] & 0x07);
+ ulev1_print_configuration(ulev1_conf);
}
}
-
+
// AUTHLIMIT, (number of failed authentications)
// 0 = limitless.
// 1-7 = limit. No automatic tries then.
if ( !authlim && !hasAuthKey ) {
PrintAndLog("\n--- Known EV1/NTAG passwords.");
len = 0;
- for (uint8_t i = 0; i < KEYS_PWD_COUNT; ++i ) {
+ for (uint8_t i = 0; i < KEYS_PWD_COUNT; ++i ){
key = default_pwd_pack[i];
- len = ulev1_requestAuthentication(key, pack, sizeof(pack));
+ len = ulev1_requestAuthentication(key, pack, sizeof(pack));
if (len >= 1) {
PrintAndLog("Found a default password: %s || Pack: %02X %02X",sprint_hex(key, 4), pack[0], pack[1]);
break;
} else {
if (!ul_auth_select( &card, tagtype, hasAuthKey, authkeyptr, pack, sizeof(pack))) return -1;
- }
+ }
}
if (len < 1) PrintAndLog("password not known");
}
}
//
-// Mifare Ultralight Write Single Block
+// Write Single Block
//
int CmdHF14AMfUWrBl(const char *Cmd){
- uint8_t blockNo = -1;
- bool chinese_card = FALSE;
- uint8_t bldata[16] = {0x00};
- UsbCommand resp;
- char cmdp = param_getchar(Cmd, 0);
- if (strlen(Cmd) < 3 || cmdp == 'h' || cmdp == 'H') {
- PrintAndLog("Usage: hf mfu wrbl <block number> <block data (8 hex symbols)> [w]");
- PrintAndLog(" [block number]");
- PrintAndLog(" [block data] - (8 hex symbols)");
- PrintAndLog(" [w] - Chinese magic ultralight tag");
- PrintAndLog("");
- PrintAndLog(" sample: hf mfu wrbl 0 01020304");
- PrintAndLog("");
- return 0;
- }
-
- blockNo = param_get8(Cmd, 0);
+ int blockNo = -1;
+ bool errors = false;
+ bool hasAuthKey = false;
+ bool hasPwdKey = false;
+ bool swapEndian = false;
- if (blockNo > MAX_UL_BLOCKS){
- PrintAndLog("Error: Maximum number of blocks is 15 for Ultralight Cards!");
- return 1;
- }
+ uint8_t cmdp = 0;
+ uint8_t keylen = 0;
+ uint8_t blockdata[20] = {0x00};
+ uint8_t data[16] = {0x00};
+ uint8_t authenticationkey[16] = {0x00};
+ uint8_t *authkeyptr = authenticationkey;
- if (param_gethex(Cmd, 1, bldata, 8)) {
- PrintAndLog("Block data must include 8 HEX symbols");
- return 1;
+ // starting with getting tagtype
+ TagTypeUL_t tagtype = GetHF14AMfU_Type();
+ if (tagtype == UL_ERROR) return -1;
+
+ while(param_getchar(Cmd, cmdp) != 0x00)
+ {
+ switch(param_getchar(Cmd, cmdp))
+ {
+ case 'h':
+ case 'H':
+ return usage_hf_mfu_wrbl();
+ case 'k':
+ case 'K':
+ // EV1/NTAG size key
+ keylen = param_gethex(Cmd, cmdp+1, data, 8);
+ if ( !keylen ) {
+ memcpy(authenticationkey, data, 4);
+ cmdp += 2;
+ hasPwdKey = true;
+ break;
+ }
+ // UL-C size key
+ keylen = param_gethex(Cmd, cmdp+1, data, 32);
+ if (!keylen){
+ memcpy(authenticationkey, data, 16);
+ cmdp += 2;
+ hasAuthKey = true;
+ break;
+ }
+ PrintAndLog("\nERROR: Key is incorrect length\n");
+ errors = true;
+ break;
+ case 'b':
+ case 'B':
+ blockNo = param_get8(Cmd, cmdp+1);
+
+ uint8_t maxblockno = 0;
+ for (uint8_t idx = 0; idx < MAX_UL_TYPES; idx++){
+ if (tagtype & UL_TYPES_ARRAY[idx])
+ maxblockno = UL_MEMORY_ARRAY[idx]+1;
+ }
+
+ if (blockNo < 0) {
+ PrintAndLog("Wrong block number");
+ errors = true;
+ }
+ if (blockNo > maxblockno){
+ PrintAndLog("block number to large. Max block is %u/0x%02X \n", maxblockno,maxblockno);
+ errors = true;
+ }
+ cmdp += 2;
+ break;
+ case 'l':
+ case 'L':
+ swapEndian = true;
+ cmdp++;
+ break;
+ case 'd':
+ case 'D':
+ if ( param_gethex(Cmd, cmdp+1, blockdata, 8) ) {
+ PrintAndLog("Block data must include 8 HEX symbols");
+ errors = true;
+ break;
+ }
+ cmdp += 2;
+ break;
+ default:
+ PrintAndLog("Unknown parameter '%c'", param_getchar(Cmd, cmdp));
+ errors = true;
+ break;
+ }
+ //Validations
+ if(errors) return usage_hf_mfu_wrbl();
}
+
+ if ( blockNo == -1 ) return usage_hf_mfu_wrbl();
+
+ // Swap endianness
+ if (swapEndian && hasAuthKey) authkeyptr = SwapEndian64(authenticationkey, 16, 8);
+ if (swapEndian && hasPwdKey) authkeyptr = SwapEndian64(authenticationkey, 4, 4);
+
+
+ if ( blockNo <= 3)
+ PrintAndLog("Special Block: %0d (0x%02X) [ %s]", blockNo, blockNo, sprint_hex(blockdata, 4));
+ else
+ PrintAndLog("Block: %0d (0x%02X) [ %s]", blockNo, blockNo, sprint_hex(blockdata, 4));
+
- if (strchr(Cmd,'w') != 0 || strchr(Cmd,'W') != 0 ) {
- chinese_card = TRUE;
+
+ //Send write Block
+ UsbCommand c = {CMD_MIFAREU_WRITEBL, {blockNo}};
+ memcpy(c.d.asBytes,blockdata,4);
+
+ if ( hasAuthKey ){
+ c.arg[1] = 1;
+ memcpy(c.d.asBytes+4,authkeyptr,16);
+ }
+ else if ( hasPwdKey ) {
+ c.arg[1] = 2;
+ memcpy(c.d.asBytes+4,authkeyptr,4);
}
- if ( blockNo <= 3) {
- if (!chinese_card){
- PrintAndLog("Access Denied");
- } else {
- PrintAndLog("--specialblock no:%02x", blockNo);
- PrintAndLog("--data: %s", sprint_hex(bldata, 4));
- UsbCommand d = {CMD_MIFAREU_WRITEBL, {blockNo}};
- memcpy(d.d.asBytes,bldata, 4);
- SendCommand(&d);
- if (WaitForResponseTimeout(CMD_ACK,&resp,1500)) {
- uint8_t isOK = resp.arg[0] & 0xff;
- PrintAndLog("isOk:%02x", isOK);
- } else {
- PrintAndLog("Command execute timeout");
- }
- }
+ SendCommand(&c);
+ UsbCommand resp;
+ if (WaitForResponseTimeout(CMD_ACK,&resp,1500)) {
+ uint8_t isOK = resp.arg[0] & 0xff;
+ PrintAndLog("isOk:%02x", isOK);
} else {
- PrintAndLog("--block no:%02x", blockNo);
- PrintAndLog("--data: %s", sprint_hex(bldata, 4));
- UsbCommand e = {CMD_MIFAREU_WRITEBL, {blockNo}};
- memcpy(e.d.asBytes,bldata, 4);
- SendCommand(&e);
- if (WaitForResponseTimeout(CMD_ACK,&resp,1500)) {
- uint8_t isOK = resp.arg[0] & 0xff;
- PrintAndLog("isOk:%02x", isOK);
- } else {
- PrintAndLog("Command execute timeout");
- }
+ PrintAndLog("Command execute timeout");
}
+
return 0;
}
-
//
-// Mifare Ultralight Read Single Block
+// Read Single Block
//
int CmdHF14AMfURdBl(const char *Cmd){
- UsbCommand resp;
- uint8_t blockNo = -1;
- char cmdp = param_getchar(Cmd, 0);
+ int blockNo = -1;
+ bool errors = false;
+ bool hasAuthKey = false;
+ bool hasPwdKey = false;
+ bool swapEndian = false;
+ uint8_t cmdp = 0;
+ uint8_t keylen = 0;
+ uint8_t data[16] = {0x00};
+ uint8_t authenticationkey[16] = {0x00};
+ uint8_t *authkeyptr = authenticationkey;
+
+ // starting with getting tagtype
+ TagTypeUL_t tagtype = GetHF14AMfU_Type();
+ if (tagtype == UL_ERROR) return -1;
- if (strlen(Cmd) < 1 || cmdp == 'h' || cmdp == 'H') {
- PrintAndLog("Usage: hf mfu rdbl <block number>");
- PrintAndLog(" sample: hfu mfu rdbl 0");
- return 0;
- }
-
- blockNo = param_get8(Cmd, 0);
-
- if (blockNo > MAX_UL_BLOCKS){
- PrintAndLog("Error: Maximum number of blocks is 15 for Ultralight");
- return 1;
+ while(param_getchar(Cmd, cmdp) != 0x00)
+ {
+ switch(param_getchar(Cmd, cmdp))
+ {
+ case 'h':
+ case 'H':
+ return usage_hf_mfu_rdbl();
+ case 'k':
+ case 'K':
+ // EV1/NTAG size key
+ keylen = param_gethex(Cmd, cmdp+1, data, 8);
+ if ( !keylen ) {
+ memcpy(authenticationkey, data, 4);
+ cmdp += 2;
+ hasPwdKey = true;
+ break;
+ }
+ // UL-C size key
+ keylen = param_gethex(Cmd, cmdp+1, data, 32);
+ if (!keylen){
+ memcpy(authenticationkey, data, 16);
+ cmdp += 2;
+ hasAuthKey = true;
+ break;
+ }
+ PrintAndLog("\nERROR: Key is incorrect length\n");
+ errors = true;
+ break;
+ case 'b':
+ case 'B':
+ blockNo = param_get8(Cmd, cmdp+1);
+
+ uint8_t maxblockno = 0;
+ for (uint8_t idx = 0; idx < MAX_UL_TYPES; idx++){
+ if (tagtype & UL_TYPES_ARRAY[idx])
+ maxblockno = UL_MEMORY_ARRAY[idx]+1;
+ }
+
+ if (blockNo < 0) {
+ PrintAndLog("Wrong block number");
+ errors = true;
+ }
+ if (blockNo > maxblockno){
+ PrintAndLog("block number to large. Max block is %u/0x%02X \n", maxblockno,maxblockno);
+ errors = true;
+ }
+ cmdp += 2;
+ break;
+ case 'l':
+ case 'L':
+ swapEndian = true;
+ cmdp++;
+ break;
+ default:
+ PrintAndLog("Unknown parameter '%c'", param_getchar(Cmd, cmdp));
+ errors = true;
+ break;
+ }
+ //Validations
+ if(errors) return usage_hf_mfu_rdbl();
}
-
+ if ( blockNo == -1 ) return usage_hf_mfu_rdbl();
+
+ // Swap endianness
+ if (swapEndian && hasAuthKey) authkeyptr = SwapEndian64(authenticationkey, 16, 8);
+ if (swapEndian && hasPwdKey) authkeyptr = SwapEndian64(authenticationkey, 4, 4);
+
+ //Read Block
UsbCommand c = {CMD_MIFAREU_READBL, {blockNo}};
+ if ( hasAuthKey ){
+ c.arg[1] = 1;
+ memcpy(c.d.asBytes,authkeyptr,16);
+ }
+ else if ( hasPwdKey ) {
+ c.arg[1] = 2;
+ memcpy(c.d.asBytes,authkeyptr,4);
+ }
+
SendCommand(&c);
-
if (WaitForResponseTimeout(CMD_ACK,&resp,1500)) {
uint8_t isOK = resp.arg[0] & 0xff;
if (isOK) {
uint8_t *data = resp.d.asBytes;
- PrintAndLog("Block: %0d (0x%02X) [ %s]", (int)blockNo, blockNo, sprint_hex(data, 4));
+ PrintAndLog("Block: %0d (0x%02X) [ %s]", blockNo, blockNo, sprint_hex(data, 4));
}
else {
PrintAndLog("Failed reading block: (%02x)", isOK);
return 0;
}
+int usage_hf_mfu_rdbl(void) {
+ PrintAndLog("Read a block and print. It autodetects card type.\n");
+ PrintAndLog("Usage: hf mfu rdbl b <block number> k <key> l\n");
+ PrintAndLog(" Options:");
+ PrintAndLog(" b <no> : block to read");
+ PrintAndLog(" k <key> : (optional) key for authentication [UL-C 16bytes, EV1/NTAG 4bytes]");
+ PrintAndLog(" l : (optional) swap entered key's endianness");
+ PrintAndLog("");
+ PrintAndLog(" sample : hf mfu rdbl b 0");
+ PrintAndLog(" : hf mfu rdbl b 0 k 00112233445566778899AABBCCDDEEFF");
+ PrintAndLog(" : hf mfu rdbl b 0 k AABBCCDDD\n");
+ return 0;
+}
+
+int usage_hf_mfu_wrbl(void) {
+ PrintAndLog("Write a block. It autodetects card type.\n");
+ PrintAndLog("Usage: hf mfu wrbl b <block number> d <data> k <key> l\n");
+ PrintAndLog(" Options:");
+ PrintAndLog(" b <no> : block to write");
+ PrintAndLog(" d <data> : block data - (8 hex symbols)");
+ PrintAndLog(" k <key> : (optional) key for authentication [UL-C 16bytes, EV1/NTAG 4bytes]");
+ PrintAndLog(" l : (optional) swap entered key's endianness");
+ PrintAndLog("");
+ PrintAndLog(" sample : hf mfu wrbl b 0 d 01234567");
+ PrintAndLog(" : hf mfu wrbl b 0 d 01234567 k AABBCCDDD\n");
+ return 0;
+}
+
//
// Mifare Ultralight / Ultralight-C / Ultralight-EV1
// Read and Dump Card Contents, using auto detection of tag size.
+//
+// TODO: take a password to read UL-C / UL-EV1 tags.
int CmdHF14AMfUDump(const char *Cmd){
FILE *fout;
}
switch(i){
case 3: tmplockbit = bit[4]; break;
- case 4: tmplockbit = bit[3]; break;
- case 5: tmplockbit = bit[2]; break;
- case 6: tmplockbit = bit[1]; break;
- case 7: tmplockbit = bit[0]; break;
- case 8: tmplockbit = bit[15]; break;
+ case 4: tmplockbit = bit[3]; break;
+ case 5: tmplockbit = bit[2]; break;
+ case 6: tmplockbit = bit[1]; break;
+ case 7: tmplockbit = bit[0]; break;
+ case 8: tmplockbit = bit[15]; break;
case 9: tmplockbit = bit[14]; break;
case 10: tmplockbit = bit[13]; break;
case 11: tmplockbit = bit[12]; break;
}
**/
-//
-// Ultralight C Read Single Block
-//
-int CmdHF14AMfUCRdBl(const char *Cmd)
-{
- UsbCommand resp;
- bool hasPwd = FALSE;
- uint8_t blockNo = -1;
- uint8_t key[16];
- char cmdp = param_getchar(Cmd, 0);
-
- if (strlen(Cmd) < 1 || cmdp == 'h' || cmdp == 'H') {
- PrintAndLog("Usage: hf mfu crdbl <block number> <key>");
- PrintAndLog("");
- PrintAndLog("sample: hf mfu crdbl 0");
- PrintAndLog(" hf mfu crdbl 0 00112233445566778899AABBCCDDEEFF");
- return 0;
- }
-
- blockNo = param_get8(Cmd, 0);
- if (blockNo < 0) {
- PrintAndLog("Wrong block number");
- return 1;
- }
-
- if (blockNo > MAX_ULC_BLOCKS ){
- PrintAndLog("Error: Maximum number of blocks is 47 for Ultralight-C");
- return 1;
- }
-
- // key
- if ( strlen(Cmd) > 3){
- if (param_gethex(Cmd, 1, key, 32)) {
- PrintAndLog("Key must include %d HEX symbols", 32);
- return 1;
- } else {
- hasPwd = TRUE;
- }
- }
-
- //Read Block
- UsbCommand c = {CMD_MIFAREU_READBL, {blockNo}};
- if ( hasPwd ) {
- c.arg[1] = 1;
- memcpy(c.d.asBytes,key,16);
- }
- SendCommand(&c);
-
- if (WaitForResponseTimeout(CMD_ACK,&resp,1500)) {
- uint8_t isOK = resp.arg[0] & 0xff;
- if (isOK) {
- uint8_t *data = resp.d.asBytes;
- PrintAndLog("Block: %0d (0x%02X) [ %s]", (int)blockNo, blockNo, sprint_hex(data, 4));
- }
- else {
- PrintAndLog("Failed reading block: (%02x)", isOK);
- }
- } else {
- PrintAndLog("Command execute time-out");
- }
- return 0;
-}
-
-//
-// Mifare Ultralight C Write Single Block
-//
-int CmdHF14AMfUCWrBl(const char *Cmd){
-
- uint8_t blockNo = -1;
- bool chinese_card = FALSE;
- uint8_t bldata[16] = {0x00};
- UsbCommand resp;
-
- char cmdp = param_getchar(Cmd, 0);
-
- if (strlen(Cmd) < 3 || cmdp == 'h' || cmdp == 'H') {
- PrintAndLog("Usage: hf mfu cwrbl <block number> <block data (8 hex symbols)> [w]");
- PrintAndLog(" [block number]");
- PrintAndLog(" [block data] - (8 hex symbols)");
- PrintAndLog(" [w] - Chinese magic ultralight tag");
- PrintAndLog("");
- PrintAndLog(" sample: hf mfu cwrbl 0 01020304");
- PrintAndLog("");
- return 0;
- }
-
- blockNo = param_get8(Cmd, 0);
- if (blockNo > MAX_ULC_BLOCKS ){
- PrintAndLog("Error: Maximum number of blocks is 47 for Ultralight-C Cards!");
- return 1;
- }
-
- if (param_gethex(Cmd, 1, bldata, 8)) {
- PrintAndLog("Block data must include 8 HEX symbols");
- return 1;
- }
-
- if (strchr(Cmd,'w') != 0 || strchr(Cmd,'W') != 0 ) {
- chinese_card = TRUE;
- }
-
- if ( blockNo <= 3 ) {
- if (!chinese_card){
- PrintAndLog("Access Denied");
- return 1;
- } else {
- PrintAndLog("--Special block no: 0x%02x", blockNo);
- PrintAndLog("--Data: %s", sprint_hex(bldata, 4));
- UsbCommand d = {CMD_MIFAREU_WRITEBL, {blockNo}};
- memcpy(d.d.asBytes,bldata, 4);
- SendCommand(&d);
- if (WaitForResponseTimeout(CMD_ACK,&resp,1500)) {
- uint8_t isOK = resp.arg[0] & 0xff;
- PrintAndLog("isOk:%02x", isOK);
- } else {
- PrintAndLog("Command execute timeout");
- return 1;
- }
- }
- } else {
- PrintAndLog("--Block no : 0x%02x", blockNo);
- PrintAndLog("--Data: %s", sprint_hex(bldata, 4));
- UsbCommand e = {CMD_MIFAREU_WRITEBL, {blockNo}};
- memcpy(e.d.asBytes,bldata, 4);
- SendCommand(&e);
- if (WaitForResponseTimeout(CMD_ACK,&resp,1500)) {
- uint8_t isOK = resp.arg[0] & 0xff;
- PrintAndLog("isOk : %02x", isOK);
- } else {
- PrintAndLog("Command execute timeout");
- return 1;
- }
- }
- return 0;
-}
-
//
// Mifare Ultralight C - Set password
//
int CmdHF14AMfucSetPwd(const char *Cmd){
- uint8_t pwd[16] = {0x00};
+ uint8_t pwd[16] = {0x00};
+ uint8_t key[16];
char cmdp = param_getchar(Cmd, 0);
-
+
if (strlen(Cmd) == 0 || cmdp == 'h' || cmdp == 'H') {
PrintAndLog("Usage: hf mfu setpwd <password (32 hex symbols)>");
PrintAndLog(" [password] - (32 hex symbols)");
PrintAndLog("Password must include 32 HEX symbols");
return 1;
}
+
+ if (blockNo > MAX_ULC_BLOCKS ){
+ PrintAndLog("Error: Maximum number of blocks is 47 for Ultralight-C");
+ return 1;
+ }
UsbCommand c = {CMD_MIFAREUC_SETPWD};
memcpy( c.d.asBytes, pwd, 16);
PrintAndLog("Command execute timeout");
return 2;
}
-
+
// save old block2.
uint8_t oldblock2[4] = {0x00};
memcpy(resp.d.asBytes, oldblock2, 4);
PrintAndLog("Command execute timeout");
return 3;
}
-
+
// block 1.
c.arg[0] = 1;
c.d.asBytes[0] = uid[3];
{"dbg", CmdHF14AMfDbg, 0, "Set default debug mode"},
{"info", CmdHF14AMfUInfo, 0, "Tag information"},
{"dump", CmdHF14AMfUDump, 0, "Dump Ultralight / Ultralight-C tag to binary file"},
- {"rdbl", CmdHF14AMfURdBl, 0, "Read block - Ultralight"},
- {"wrbl", CmdHF14AMfUWrBl, 0, "Write block - Ultralight"},
- {"crdbl", CmdHF14AMfUCRdBl, 0, "Read block - Ultralight C"},
- {"cwrbl", CmdHF14AMfUCWrBl, 0, "Write block - Ultralight C"},
+ {"rdbl", CmdHF14AMfURdBl, 0, "Read block"},
+ {"wrbl", CmdHF14AMfUWrBl, 0, "Write block"},
{"cauth", CmdHF14AMfucAuth, 0, "Authentication - Ultralight C"},
{"setpwd", CmdHF14AMfucSetPwd, 1, "Set 3des password - Ultralight-C"},
{"setuid", CmdHF14AMfucSetUid, 1, "Set UID - MAGIC tags only"},
#ifndef CMDHFMFU_H__
#define CMDHFMFU_H__
-//standard ultralight
int CmdHF14AMfUWrBl(const char *Cmd);
int CmdHF14AMfURdBl(const char *Cmd);
//Crypto Cards
-int CmdHF14AMfUCRdBl(const char *Cmd);
-int CmdHF14AMfUCRdCard(const char *Cmd);
int CmdHF14AMfucAuth(const char *Cmd);
//general stuff
int CmdHF14AMfUDump(const char *Cmd);
int CmdHF14AMfUInfo(const char *Cmd);
-uint32_t GetHF14AMfU_Type(void);
+uint32_t GetHF14AMfU_Type(void);
int ul_print_type(uint32_t tagtype, uint8_t spacer);
void ul_switch_off_field(void);
int usage_hf_mfu_dump(void);
int usage_hf_mfu_info(void);
+int usage_hf_mfu_rdbl(void);
+int usage_hf_mfu_wrbl(void);
int CmdHFMFUltra(const char *Cmd);
--- /dev/null
+//-----------------------------------------------------------------------------
+// Copyright (C) 2015 Piwi
+//
+// 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 Topaz (NFC Type 1) commands
+//-----------------------------------------------------------------------------
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include "cmdmain.h"
+#include "cmdparser.h"
+#include "cmdhftopaz.h"
+#include "cmdhf14a.h"
+#include "ui.h"
+#include "mifare.h"
+#include "proxmark3.h"
+#include "iso14443crc.h"
+#include "protocols.h"
+
+#define TOPAZ_MAX_MEMORY 2048
+
+static struct {
+ uint8_t HR01[2];
+ uint8_t uid[7];
+ uint8_t size;
+ uint8_t data_blocks[TOPAZ_MAX_MEMORY/8][8];
+ uint8_t *dynamic_lock_areas;
+ uint8_t *dynamic_reserved_areas;
+} topaz_tag;
+
+
+static void topaz_switch_on_field(void)
+{
+ UsbCommand c = {CMD_READER_ISO_14443a, {ISO14A_CONNECT | ISO14A_NO_SELECT | ISO14A_NO_DISCONNECT | ISO14A_TOPAZMODE, 0, 0}};
+ SendCommand(&c);
+}
+
+
+static void topaz_switch_off_field(void)
+{
+ UsbCommand c = {CMD_READER_ISO_14443a, {0, 0, 0}};
+ SendCommand(&c);
+}
+
+
+static int topaz_send_cmd_raw(uint8_t *cmd, uint8_t len, uint8_t *response)
+{
+ UsbCommand c = {CMD_READER_ISO_14443a, {ISO14A_RAW | ISO14A_NO_DISCONNECT | ISO14A_TOPAZMODE, len, 0}};
+ memcpy(c.d.asBytes, cmd, len);
+ SendCommand(&c);
+
+ UsbCommand resp;
+ WaitForResponse(CMD_ACK, &resp);
+
+ if (resp.arg[0] > 0) {
+ memcpy(response, resp.d.asBytes, resp.arg[0]);
+ }
+
+ return resp.arg[0];
+}
+
+
+static int topaz_send_cmd(uint8_t *cmd, uint8_t len, uint8_t *response)
+{
+ if (len > 1) {
+ uint8_t first, second;
+ ComputeCrc14443(CRC_14443_B, cmd, len-2, &first, &second);
+ cmd[len-2] = first;
+ cmd[len-1] = second;
+ }
+
+ return topaz_send_cmd_raw(cmd, len, response);
+}
+
+
+static int topaz_select(uint8_t *atqa, uint8_t *rid_response)
+{
+ // ToDo: implement anticollision
+
+ uint8_t wupa_cmd[] = {TOPAZ_WUPA};
+ uint8_t rid_cmd[] = {TOPAZ_RID, 0, 0, 0, 0, 0, 0, 0, 0};
+
+ topaz_switch_on_field();
+
+ if (!topaz_send_cmd(wupa_cmd, sizeof(wupa_cmd), atqa)) {
+ topaz_switch_off_field();
+ return -1; // WUPA failed
+ }
+
+ if (!topaz_send_cmd(rid_cmd, sizeof(rid_cmd), rid_response)) {
+ topaz_switch_off_field();
+ return -2; // RID failed
+ }
+
+ return 0; // OK
+}
+
+
+static int topaz_rall(uint8_t *uid, uint8_t *response)
+{
+ uint8_t rall_cmd[] = {TOPAZ_RALL, 0, 0, 0, 0, 0, 0, 0, 0};
+
+ memcpy(&rall_cmd[3], uid, 4);
+ if (!topaz_send_cmd(rall_cmd, sizeof(rall_cmd), response)) {
+ topaz_switch_off_field();
+ return -1; // RALL failed
+ }
+
+ return 0;
+}
+
+
+static bool topaz_block_is_locked(uint8_t blockno, uint8_t *lockbits)
+{
+ if(lockbits[blockno/8] >> (blockno % 8) & 0x01) {
+ return true;
+ } else {
+ return false;
+ }
+}
+
+
+static int topaz_print_CC(uint8_t *data)
+{
+ if(data[0] != 0xe1) {
+ return -1; // no NDEF message
+ }
+
+ PrintAndLog("Capability Container: %02x %02x %02x %02x", data[0], data[1], data[2], data[3]);
+ PrintAndLog(" %02x: NDEF Magic Number", data[0]);
+ PrintAndLog(" %02x: version %d.%d supported by tag", data[1], (data[1] & 0xF0) >> 4, data[1] & 0x0f);
+ PrintAndLog(" %02x: Physical Memory Size of this tag: %d bytes", data[2], (data[2] + 1) * 8);
+ PrintAndLog(" %02x: %s / %s", data[3],
+ (data[3] & 0xF0) ? "(RFU)" : "Read access granted without any security",
+ (data[3] & 0x0F)==0 ? "Write access granted without any security" : (data[3] & 0x0F)==0x0F ? "No write access granted at all" : "(RFU)");
+ return 0;
+}
+
+
+static void get_TLV(uint8_t **TLV_ptr, uint8_t *tag, uint16_t *length, uint8_t **value)
+{
+ *length = 0;
+ *value = NULL;
+
+ *tag = **TLV_ptr;
+ *TLV_ptr += 1;
+ switch (*tag) {
+ case 0x00: // NULL TLV.
+ case 0xFE: // Terminator TLV.
+ break;
+ case 0x01: // Lock Control TLV
+ case 0x02: // Reserved Memory TLV
+ case 0x03: // NDEF message TLV
+ case 0xFD: // proprietary TLV
+ *length = **TLV_ptr;
+ *TLV_ptr += 1;
+ if (*length == 0xff) {
+ *length = **TLV_ptr << 8;
+ *TLV_ptr += 1;
+ *length |= **TLV_ptr;
+ *TLV_ptr += 1;
+ }
+ *value = *TLV_ptr;
+ *TLV_ptr += *length;
+ break;
+ default: // RFU
+ break;
+ }
+}
+
+
+static bool topaz_print_lock_control_TLVs(uint8_t *memory)
+{
+ uint8_t *TLV_ptr = memory;
+ uint8_t tag = 0;
+ uint16_t length;
+ uint8_t *value;
+ bool lock_TLV_present = false;
+
+ while(*TLV_ptr != 0x03 && *TLV_ptr != 0xFD && *TLV_ptr != 0xFE) {
+ // all Lock Control TLVs shall be present before the NDEF message TLV, the proprietary TLV (and the Terminator TLV)
+ get_TLV(&TLV_ptr, &tag, &length, &value);
+ if (tag == 0x01) { // the Lock Control TLV
+ uint8_t pages_addr = value[0] >> 4;
+ uint8_t byte_offset = value[0] & 0x0f;
+ uint8_t size_in_bits = value[1] ? value[1] : 256;
+ uint8_t bytes_per_page = 1 << (value[2] & 0x0f);
+ uint8_t bytes_locked_per_bit = 1 << (value[2] >> 4);
+ PrintAndLog("Lock Area of %d bits at byte offset 0x%02x. Each Lock Bit locks %d bytes.",
+ size_in_bits,
+ pages_addr * bytes_per_page + byte_offset,
+ bytes_locked_per_bit);
+ lock_TLV_present = true;
+ }
+ }
+
+ if (!lock_TLV_present) {
+ PrintAndLog("(No Lock Control TLV present)");
+ return -1;
+ } else {
+ return 0;
+ }
+}
+
+
+static int topaz_print_reserved_memory_control_TLVs(uint8_t *memory)
+{
+ uint8_t *TLV_ptr = memory;
+ uint8_t tag = 0;
+ uint16_t length;
+ uint8_t *value;
+ bool reserved_memory_control_TLV_present = false;
+
+ while(*TLV_ptr != 0x03 && *TLV_ptr != 0xFD && *TLV_ptr != 0xFE) {
+ // all Reserved Memory Control TLVs shall be present before the NDEF message TLV, the proprietary TLV (and the Terminator TLV)
+ get_TLV(&TLV_ptr, &tag, &length, &value);
+ if (tag == 0x02) { // the Reserved Memory Control TLV
+ uint8_t pages_addr = value[0] >> 4;
+ uint8_t byte_offset = value[0] & 0x0f;
+ uint8_t size_in_bytes = value[1] ? value[1] : 256;
+ uint8_t bytes_per_page = 1 << (value[2] & 0x0f);
+ PrintAndLog("Reserved Memory of %d bytes at byte offset 0x%02x.",
+ size_in_bytes,
+ pages_addr * bytes_per_page + byte_offset);
+ reserved_memory_control_TLV_present = true;
+ }
+ }
+
+ if (!reserved_memory_control_TLV_present) {
+ PrintAndLog("(No Reserved Memory Control TLV present)");
+ return -1;
+ } else {
+ return 0;
+ }
+}
+
+
+static void topaz_print_lifecycle_state(uint8_t *data)
+{
+
+}
+
+
+static void topaz_print_NDEF(uint8_t *data)
+{
+
+}
+
+
+int CmdHFTopazReader(const char *Cmd)
+{
+ int status;
+ uint8_t atqa[2];
+ uint8_t rid_response[8];
+ uint8_t *uid_echo = &rid_response[2];
+ uint8_t rall_response[124];
+
+ status = topaz_select(atqa, rid_response);
+
+ if (status == -1) {
+ PrintAndLog("Error: couldn't receive ATQA");
+ return -1;
+ }
+
+ PrintAndLog("ATQA : %02x %02x", atqa[1], atqa[0]);
+ if (atqa[1] != 0x0c && atqa[0] != 0x00) {
+ PrintAndLog("Tag doesn't support the Topaz protocol.");
+ topaz_switch_off_field();
+ return -1;
+ }
+
+ if (status == -2) {
+ PrintAndLog("Error: tag didn't answer to RID");
+ topaz_switch_off_field();
+ return -1;
+ }
+
+ topaz_tag.HR01[0] = rid_response[0];
+ topaz_tag.HR01[1] = rid_response[1];
+
+ // ToDo: CRC check
+ PrintAndLog("HR0 : %02x (%sa Topaz tag (%scapable of carrying a NDEF message), %s memory map)", rid_response[0],
+ (rid_response[0] & 0xF0) == 0x10 ? "" : "not ",
+ (rid_response[0] & 0xF0) == 0x10 ? "" : "not ",
+ (rid_response[0] & 0x0F) == 0x10 ? "static" : "dynamic");
+ PrintAndLog("HR1 : %02x", rid_response[1]);
+
+ status = topaz_rall(uid_echo, rall_response);
+
+ if(status == -1) {
+ PrintAndLog("Error: tag didn't answer to RALL");
+ topaz_switch_off_field();
+ return -1;
+ }
+
+ memcpy(topaz_tag.uid, rall_response+2, 7);
+ PrintAndLog("UID : %02x %02x %02x %02x %02x %02x %02x",
+ topaz_tag.uid[6],
+ topaz_tag.uid[5],
+ topaz_tag.uid[4],
+ topaz_tag.uid[3],
+ topaz_tag.uid[2],
+ topaz_tag.uid[1],
+ topaz_tag.uid[0]);
+ PrintAndLog(" UID[6] (Manufacturer Byte) = %02x, Manufacturer: %s",
+ topaz_tag.uid[6],
+ getTagInfo(topaz_tag.uid[6]));
+
+ memcpy(topaz_tag.data_blocks, rall_response+2, 0x10*8);
+ PrintAndLog("");
+ PrintAndLog("Static Data blocks 00 to 0c:");
+ PrintAndLog("block# | offset | Data | Locked?");
+ char line[80];
+ for (uint16_t i = 0; i <= 0x0c; i++) {
+ for (uint16_t j = 0; j < 8; j++) {
+ sprintf(&line[3*j], "%02x ", topaz_tag.data_blocks[i][j] /*rall_response[2 + 8*i + j]*/);
+ }
+ PrintAndLog(" 0x%02x | 0x%02x | %s| %-3s", i, i*8, line, topaz_block_is_locked(i, &topaz_tag.data_blocks[0x0e][0]) ? "yes" : "no");
+ }
+
+ PrintAndLog("");
+ PrintAndLog("Static Reserved block 0d:");
+ for (uint16_t j = 0; j < 8; j++) {
+ sprintf(&line[3*j], "%02x ", topaz_tag.data_blocks[0x0d][j]);
+ }
+ PrintAndLog(" 0x%02x | 0x%02x | %s| %-3s", 0x0d, 0x0d*8, line, "n/a");
+
+ PrintAndLog("");
+ PrintAndLog("Static Lockbits and OTP Bytes:");
+ for (uint16_t j = 0; j < 8; j++) {
+ sprintf(&line[3*j], "%02x ", topaz_tag.data_blocks[0x0e][j]);
+ }
+ PrintAndLog(" 0x%02x | 0x%02x | %s| %-3s", 0x0e, 0x0e*8, line, "n/a");
+
+ PrintAndLog("");
+
+ status = topaz_print_CC(&topaz_tag.data_blocks[1][0]);
+
+ if (status == -1) {
+ PrintAndLog("No NDEF message present");
+ topaz_switch_off_field();
+ return 0;
+ }
+
+ PrintAndLog("");
+ bool lock_TLV_present = topaz_print_lock_control_TLVs(&topaz_tag.data_blocks[1][4]);
+
+ PrintAndLog("");
+ bool reserved_mem_present = topaz_print_reserved_memory_control_TLVs(&topaz_tag.data_blocks[1][4]);
+
+ topaz_print_lifecycle_state(&topaz_tag.data_blocks[1][0]);
+
+ topaz_print_NDEF(&topaz_tag.data_blocks[1][0]);
+
+ topaz_switch_off_field();
+ return 0;
+}
+
+
+int CmdHFTopazSim(const char *Cmd)
+{
+ PrintAndLog("not yet implemented");
+ return 0;
+}
+
+
+int CmdHFTopazCmdRaw(const char *Cmd)
+{
+ PrintAndLog("not yet implemented");
+ return 0;
+}
+
+
+static int CmdHelp(const char *Cmd);
+
+
+static command_t CommandTable[] =
+{
+ {"help", CmdHelp, 1, "This help"},
+ {"reader", CmdHFTopazReader, 0, "Act like a Topaz reader"},
+ {"sim", CmdHFTopazSim, 0, "<UID> -- Simulate Topaz tag"},
+ {"sniff", CmdHF14ASniff, 0, "Sniff Topaz reader-tag communication"},
+ {"raw", CmdHFTopazCmdRaw, 0, "Send raw hex data to tag"},
+ {NULL, NULL, 0, NULL}
+};
+
+
+int CmdHFTopaz(const char *Cmd) {
+ // flush
+ WaitForResponseTimeout(CMD_ACK,NULL,100);
+
+ // parse
+ CmdsParse(CommandTable, Cmd);
+ return 0;
+}
+
+static int CmdHelp(const char *Cmd)
+{
+ CmdsHelp(CommandTable);
+ return 0;
+}
+
+
--- /dev/null
+//-----------------------------------------------------------------------------
+// Copyright (C) 2015 Piwi
+//
+// 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 Topaz (NFC Type 1) commands
+//-----------------------------------------------------------------------------
+
+#ifndef CMDHFTOPAZ_H__
+#define CMDHFTOPAZ_H__
+
+int CmdHFTopaz(const char *Cmd);
+
+#endif
#include "ui.h"
#include "proxmark3.h"
#include "cmdparser.h"
+#include "cmddata.h"
#include "cmdhw.h"
#include "cmdmain.h"
#include "cmddata.h"
/* send a command before reading */
int CmdLFCommandRead(const char *Cmd)
{
- static char dummy[3];
+ static char dummy[3];
- dummy[0]= ' ';
+ dummy[0]= ' ';
- UsbCommand c = {CMD_MOD_THEN_ACQUIRE_RAW_ADC_SAMPLES_125K};
- sscanf(Cmd, "%"lli" %"lli" %"lli" %s %s", &c.arg[0], &c.arg[1], &c.arg[2],(char*)(&c.d.asBytes),(char*)(&dummy+1));
- // in case they specified 'h'
- strcpy((char *)&c.d.asBytes + strlen((char *)c.d.asBytes), dummy);
- SendCommand(&c);
- return 0;
+ UsbCommand c = {CMD_MOD_THEN_ACQUIRE_RAW_ADC_SAMPLES_125K};
+ sscanf(Cmd, "%"lli" %"lli" %"lli" %s %s", &c.arg[0], &c.arg[1], &c.arg[2],(char*)(&c.d.asBytes),(char*)(&dummy+1));
+ // in case they specified 'h'
+ strcpy((char *)&c.d.asBytes + strlen((char *)c.d.asBytes), dummy);
+ SendCommand(&c);
+ return 0;
}
int CmdFlexdemod(const char *Cmd)
{
- int i;
- for (i = 0; i < GraphTraceLen; ++i) {
- if (GraphBuffer[i] < 0) {
- GraphBuffer[i] = -1;
- } else {
- GraphBuffer[i] = 1;
- }
- }
+ int i;
+ for (i = 0; i < GraphTraceLen; ++i) {
+ if (GraphBuffer[i] < 0) {
+ GraphBuffer[i] = -1;
+ } else {
+ GraphBuffer[i] = 1;
+ }
+ }
#define LONG_WAIT 100
- int start;
- for (start = 0; start < GraphTraceLen - LONG_WAIT; start++) {
- int first = GraphBuffer[start];
- for (i = start; i < start + LONG_WAIT; i++) {
- if (GraphBuffer[i] != first) {
- break;
- }
- }
- if (i == (start + LONG_WAIT)) {
- break;
- }
- }
- if (start == GraphTraceLen - LONG_WAIT) {
- PrintAndLog("nothing to wait for");
- return 0;
- }
-
- GraphBuffer[start] = 2;
- GraphBuffer[start+1] = -2;
+ int start;
+ for (start = 0; start < GraphTraceLen - LONG_WAIT; start++) {
+ int first = GraphBuffer[start];
+ for (i = start; i < start + LONG_WAIT; i++) {
+ if (GraphBuffer[i] != first) {
+ break;
+ }
+ }
+ if (i == (start + LONG_WAIT)) {
+ break;
+ }
+ }
+ if (start == GraphTraceLen - LONG_WAIT) {
+ PrintAndLog("nothing to wait for");
+ return 0;
+ }
+
+ GraphBuffer[start] = 2;
+ GraphBuffer[start+1] = -2;
uint8_t bits[64] = {0x00};
int bit, sum;
- i = start;
- for (bit = 0; bit < 64; bit++) {
+ i = start;
+ for (bit = 0; bit < 64; bit++) {
sum = 0;
for (int j = 0; j < 16; j++) {
- sum += GraphBuffer[i++];
- }
+ sum += GraphBuffer[i++];
+ }
bits[bit] = (sum > 0) ? 1 : 0;
- PrintAndLog("bit %d sum %d", bit, sum);
- }
-
- for (bit = 0; bit < 64; bit++) {
- int j;
- int sum = 0;
- for (j = 0; j < 16; j++) {
- sum += GraphBuffer[i++];
- }
- if (sum > 0 && bits[bit] != 1) {
- PrintAndLog("oops1 at %d", bit);
- }
- if (sum < 0 && bits[bit] != 0) {
- PrintAndLog("oops2 at %d", bit);
- }
- }
+ PrintAndLog("bit %d sum %d", bit, sum);
+ }
+
+ for (bit = 0; bit < 64; bit++) {
+ int j;
+ int sum = 0;
+ for (j = 0; j < 16; j++) {
+ sum += GraphBuffer[i++];
+ }
+ if (sum > 0 && bits[bit] != 1) {
+ PrintAndLog("oops1 at %d", bit);
+ }
+ if (sum < 0 && bits[bit] != 0) {
+ PrintAndLog("oops2 at %d", bit);
+ }
+ }
// HACK writing back to graphbuffer.
- GraphTraceLen = 32*64;
- i = 0;
- int phase = 0;
- for (bit = 0; bit < 64; bit++) {
+ GraphTraceLen = 32*64;
+ i = 0;
+ int phase = 0;
+ for (bit = 0; bit < 64; bit++) {
phase = (bits[bit] == 0) ? 0 : 1;
- int j;
- for (j = 0; j < 32; j++) {
- GraphBuffer[i++] = phase;
- phase = !phase;
- }
- }
-
- RepaintGraphWindow();
- return 0;
+ int j;
+ for (j = 0; j < 32; j++) {
+ GraphBuffer[i++] = phase;
+ phase = !phase;
+ }
+ }
+
+ RepaintGraphWindow();
+ return 0;
}
-
+
int CmdIndalaDemod(const char *Cmd)
{
- // Usage: recover 64bit UID by default, specify "224" as arg to recover a 224bit UID
+ // Usage: recover 64bit UID by default, specify "224" as arg to recover a 224bit UID
- int state = -1;
- int count = 0;
- int i, j;
+ int state = -1;
+ int count = 0;
+ int i, j;
- // worst case with GraphTraceLen=64000 is < 4096
- // under normal conditions it's < 2048
+ // worst case with GraphTraceLen=64000 is < 4096
+ // under normal conditions it's < 2048
- uint8_t rawbits[4096];
- int rawbit = 0;
- int worst = 0, worstPos = 0;
+ uint8_t rawbits[4096];
+ int rawbit = 0;
+ int worst = 0, worstPos = 0;
// PrintAndLog("Expecting a bit less than %d raw bits", GraphTraceLen / 32);
- for (i = 0; i < GraphTraceLen-1; i += 2) {
- count += 1;
- if ((GraphBuffer[i] > GraphBuffer[i + 1]) && (state != 1)) {
- if (state == 0) {
- for (j = 0; j < count - 8; j += 16) {
- rawbits[rawbit++] = 0;
- }
- if ((abs(count - j)) > worst) {
- worst = abs(count - j);
- worstPos = i;
- }
- }
- state = 1;
- count = 0;
- } else if ((GraphBuffer[i] < GraphBuffer[i + 1]) && (state != 0)) {
- if (state == 1) {
- for (j = 0; j < count - 8; j += 16) {
- rawbits[rawbit++] = 1;
- }
- if ((abs(count - j)) > worst) {
- worst = abs(count - j);
- worstPos = i;
- }
- }
- state = 0;
- count = 0;
- }
- }
-
- if (rawbit>0){
- PrintAndLog("Recovered %d raw bits, expected: %d", rawbit, GraphTraceLen/32);
- PrintAndLog("worst metric (0=best..7=worst): %d at pos %d", worst, worstPos);
+ for (i = 0; i < GraphTraceLen-1; i += 2) {
+ count += 1;
+ if ((GraphBuffer[i] > GraphBuffer[i + 1]) && (state != 1)) {
+ if (state == 0) {
+ for (j = 0; j < count - 8; j += 16) {
+ rawbits[rawbit++] = 0;
+ }
+ if ((abs(count - j)) > worst) {
+ worst = abs(count - j);
+ worstPos = i;
+ }
+ }
+ state = 1;
+ count = 0;
+ } else if ((GraphBuffer[i] < GraphBuffer[i + 1]) && (state != 0)) {
+ if (state == 1) {
+ for (j = 0; j < count - 8; j += 16) {
+ rawbits[rawbit++] = 1;
+ }
+ if ((abs(count - j)) > worst) {
+ worst = abs(count - j);
+ worstPos = i;
+ }
+ }
+ state = 0;
+ count = 0;
+ }
+ }
+
+ if (rawbit>0){
+ PrintAndLog("Recovered %d raw bits, expected: %d", rawbit, GraphTraceLen/32);
+ PrintAndLog("worst metric (0=best..7=worst): %d at pos %d", worst, worstPos);
} else {
return 0;
}
- // Finding the start of a UID
- int uidlen, long_wait;
- if (strcmp(Cmd, "224") == 0) {
- uidlen = 224;
- long_wait = 30;
- } else {
- uidlen = 64;
- long_wait = 29;
- }
-
- int start;
- int first = 0;
- for (start = 0; start <= rawbit - uidlen; start++) {
- first = rawbits[start];
- for (i = start; i < start + long_wait; i++) {
- if (rawbits[i] != first) {
- break;
- }
- }
- if (i == (start + long_wait)) {
- break;
- }
- }
-
- if (start == rawbit - uidlen + 1) {
- PrintAndLog("nothing to wait for");
- return 0;
- }
-
- // Inverting signal if needed
- if (first == 1) {
- for (i = start; i < rawbit; i++) {
- rawbits[i] = !rawbits[i];
- }
- }
-
- // Dumping UID
+ // Finding the start of a UID
+ int uidlen, long_wait;
+ if (strcmp(Cmd, "224") == 0) {
+ uidlen = 224;
+ long_wait = 30;
+ } else {
+ uidlen = 64;
+ long_wait = 29;
+ }
+
+ int start;
+ int first = 0;
+ for (start = 0; start <= rawbit - uidlen; start++) {
+ first = rawbits[start];
+ for (i = start; i < start + long_wait; i++) {
+ if (rawbits[i] != first) {
+ break;
+ }
+ }
+ if (i == (start + long_wait)) {
+ break;
+ }
+ }
+
+ if (start == rawbit - uidlen + 1) {
+ PrintAndLog("nothing to wait for");
+ return 0;
+ }
+
+ // Inverting signal if needed
+ if (first == 1) {
+ for (i = start; i < rawbit; i++) {
+ rawbits[i] = !rawbits[i];
+ }
+ }
+
+ // Dumping UID
uint8_t bits[224] = {0x00};
char showbits[225] = {0x00};
- int bit;
- i = start;
- int times = 0;
-
- if (uidlen > rawbit) {
- PrintAndLog("Warning: not enough raw bits to get a full UID");
- for (bit = 0; bit < rawbit; bit++) {
- bits[bit] = rawbits[i++];
- // As we cannot know the parity, let's use "." and "/"
- showbits[bit] = '.' + bits[bit];
- }
- showbits[bit+1]='\0';
- PrintAndLog("Partial UID=%s", showbits);
- return 0;
- } else {
- for (bit = 0; bit < uidlen; bit++) {
- bits[bit] = rawbits[i++];
- showbits[bit] = '0' + bits[bit];
- }
- times = 1;
- }
+ int bit;
+ i = start;
+ int times = 0;
- //convert UID to HEX
- uint32_t uid1, uid2, uid3, uid4, uid5, uid6, uid7;
- int idx;
+ if (uidlen > rawbit) {
+ PrintAndLog("Warning: not enough raw bits to get a full UID");
+ for (bit = 0; bit < rawbit; bit++) {
+ bits[bit] = rawbits[i++];
+ // As we cannot know the parity, let's use "." and "/"
+ showbits[bit] = '.' + bits[bit];
+ }
+ showbits[bit+1]='\0';
+ PrintAndLog("Partial UID=%s", showbits);
+ return 0;
+ } else {
+ for (bit = 0; bit < uidlen; bit++) {
+ bits[bit] = rawbits[i++];
+ showbits[bit] = '0' + bits[bit];
+ }
+ times = 1;
+ }
+
+ //convert UID to HEX
+ uint32_t uid1, uid2, uid3, uid4, uid5, uid6, uid7;
+ int idx;
uid1 = uid2 = 0;
- if (uidlen==64){
- for( idx=0; idx<64; idx++) {
- if (showbits[idx] == '0') {
- uid1=(uid1<<1)|(uid2>>31);
- uid2=(uid2<<1)|0;
- } else {
- uid1=(uid1<<1)|(uid2>>31);
- uid2=(uid2<<1)|1;
- }
- }
- PrintAndLog("UID=%s (%x%08x)", showbits, uid1, uid2);
- }
- else {
+ if (uidlen==64){
+ for( idx=0; idx<64; idx++) {
+ if (showbits[idx] == '0') {
+ uid1=(uid1<<1)|(uid2>>31);
+ uid2=(uid2<<1)|0;
+ } else {
+ uid1=(uid1<<1)|(uid2>>31);
+ uid2=(uid2<<1)|1;
+ }
+ }
+ PrintAndLog("UID=%s (%x%08x)", showbits, uid1, uid2);
+ }
+ else {
uid3 = uid4 = uid5 = uid6 = uid7 = 0;
- for( idx=0; idx<224; idx++) {
- uid1=(uid1<<1)|(uid2>>31);
- uid2=(uid2<<1)|(uid3>>31);
- uid3=(uid3<<1)|(uid4>>31);
- uid4=(uid4<<1)|(uid5>>31);
- uid5=(uid5<<1)|(uid6>>31);
- uid6=(uid6<<1)|(uid7>>31);
+ for( idx=0; idx<224; idx++) {
+ uid1=(uid1<<1)|(uid2>>31);
+ uid2=(uid2<<1)|(uid3>>31);
+ uid3=(uid3<<1)|(uid4>>31);
+ uid4=(uid4<<1)|(uid5>>31);
+ uid5=(uid5<<1)|(uid6>>31);
+ uid6=(uid6<<1)|(uid7>>31);
if (showbits[idx] == '0')
uid7 = (uid7<<1) | 0;
else
uid7 = (uid7<<1) | 1;
- }
- PrintAndLog("UID=%s (%x%08x%08x%08x%08x%08x%08x)", showbits, uid1, uid2, uid3, uid4, uid5, uid6, uid7);
- }
+ }
+ PrintAndLog("UID=%s (%x%08x%08x%08x%08x%08x%08x)", showbits, uid1, uid2, uid3, uid4, uid5, uid6, uid7);
+ }
- // Checking UID against next occurrences
- int failed = 0;
+ // Checking UID against next occurrences
+ int failed = 0;
for (; i + uidlen <= rawbit;) {
failed = 0;
- for (bit = 0; bit < uidlen; bit++) {
- if (bits[bit] != rawbits[i++]) {
- failed = 1;
- break;
- }
- }
- if (failed == 1) {
- break;
- }
- times += 1;
- }
-
- PrintAndLog("Occurrences: %d (expected %d)", times, (rawbit - start) / uidlen);
-
- // Remodulating for tag cloning
+ for (bit = 0; bit < uidlen; bit++) {
+ if (bits[bit] != rawbits[i++]) {
+ failed = 1;
+ break;
+ }
+ }
+ if (failed == 1) {
+ break;
+ }
+ times += 1;
+ }
+
+ PrintAndLog("Occurrences: %d (expected %d)", times, (rawbit - start) / uidlen);
+
+ // Remodulating for tag cloning
// HACK: 2015-01-04 this will have an impact on our new way of seening lf commands (demod)
// since this changes graphbuffer data.
- GraphTraceLen = 32*uidlen;
- i = 0;
- int phase = 0;
- for (bit = 0; bit < uidlen; bit++) {
- if (bits[bit] == 0) {
- phase = 0;
- } else {
- phase = 1;
- }
- int j;
- for (j = 0; j < 32; j++) {
- GraphBuffer[i++] = phase;
- phase = !phase;
- }
- }
-
- RepaintGraphWindow();
- return 1;
+ GraphTraceLen = 32*uidlen;
+ i = 0;
+ int phase = 0;
+ for (bit = 0; bit < uidlen; bit++) {
+ if (bits[bit] == 0) {
+ phase = 0;
+ } else {
+ phase = 1;
+ }
+ int j;
+ for (j = 0; j < 32; j++) {
+ GraphBuffer[i++] = phase;
+ phase = !phase;
+ }
+ }
+
+ RepaintGraphWindow();
+ return 1;
}
int CmdIndalaClone(const char *Cmd)
{
- UsbCommand c;
+ UsbCommand c;
unsigned int uid1, uid2, uid3, uid4, uid5, uid6, uid7;
uid1 = uid2 = uid3 = uid4 = uid5 = uid6 = uid7 = 0;
- int n = 0, i = 0;
-
- if (strchr(Cmd,'l') != 0) {
- while (sscanf(&Cmd[i++], "%1x", &n ) == 1) {
- uid1 = (uid1 << 4) | (uid2 >> 28);
- uid2 = (uid2 << 4) | (uid3 >> 28);
- uid3 = (uid3 << 4) | (uid4 >> 28);
- uid4 = (uid4 << 4) | (uid5 >> 28);
- uid5 = (uid5 << 4) | (uid6 >> 28);
- uid6 = (uid6 << 4) | (uid7 >> 28);
- uid7 = (uid7 << 4) | (n & 0xf);
- }
- PrintAndLog("Cloning 224bit tag with UID %x%08x%08x%08x%08x%08x%08x", uid1, uid2, uid3, uid4, uid5, uid6, uid7);
- c.cmd = CMD_INDALA_CLONE_TAG_L;
- c.d.asDwords[0] = uid1;
- c.d.asDwords[1] = uid2;
- c.d.asDwords[2] = uid3;
- c.d.asDwords[3] = uid4;
- c.d.asDwords[4] = uid5;
- c.d.asDwords[5] = uid6;
- c.d.asDwords[6] = uid7;
+ int n = 0, i = 0;
+
+ if (strchr(Cmd,'l') != 0) {
+ while (sscanf(&Cmd[i++], "%1x", &n ) == 1) {
+ uid1 = (uid1 << 4) | (uid2 >> 28);
+ uid2 = (uid2 << 4) | (uid3 >> 28);
+ uid3 = (uid3 << 4) | (uid4 >> 28);
+ uid4 = (uid4 << 4) | (uid5 >> 28);
+ uid5 = (uid5 << 4) | (uid6 >> 28);
+ uid6 = (uid6 << 4) | (uid7 >> 28);
+ uid7 = (uid7 << 4) | (n & 0xf);
+ }
+ PrintAndLog("Cloning 224bit tag with UID %x%08x%08x%08x%08x%08x%08x", uid1, uid2, uid3, uid4, uid5, uid6, uid7);
+ c.cmd = CMD_INDALA_CLONE_TAG_L;
+ c.d.asDwords[0] = uid1;
+ c.d.asDwords[1] = uid2;
+ c.d.asDwords[2] = uid3;
+ c.d.asDwords[3] = uid4;
+ c.d.asDwords[4] = uid5;
+ c.d.asDwords[5] = uid6;
+ c.d.asDwords[6] = uid7;
} else {
- while (sscanf(&Cmd[i++], "%1x", &n ) == 1) {
- uid1 = (uid1 << 4) | (uid2 >> 28);
- uid2 = (uid2 << 4) | (n & 0xf);
- }
- PrintAndLog("Cloning 64bit tag with UID %x%08x", uid1, uid2);
- c.cmd = CMD_INDALA_CLONE_TAG;
- c.arg[0] = uid1;
- c.arg[1] = uid2;
- }
-
- SendCommand(&c);
- return 0;
+ while (sscanf(&Cmd[i++], "%1x", &n ) == 1) {
+ uid1 = (uid1 << 4) | (uid2 >> 28);
+ uid2 = (uid2 << 4) | (n & 0xf);
+ }
+ PrintAndLog("Cloning 64bit tag with UID %x%08x", uid1, uid2);
+ c.cmd = CMD_INDALA_CLONE_TAG;
+ c.arg[0] = uid1;
+ c.arg[1] = uid2;
+ }
+
+ SendCommand(&c);
+ return 0;
}
int usage_lf_read()
//And ship it to device
UsbCommand c = {CMD_ACQUIRE_RAW_ADC_SAMPLES_125K, {arg1,0,0}};
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 void ChkBitstream(const char *str)
{
- int i;
+ int i;
- /* convert to bitstream if necessary */
+ /* convert to bitstream if necessary */
for (i = 0; i < (int)(GraphTraceLen / 2); i++){
if (GraphBuffer[i] > 1 || GraphBuffer[i] < 0) {
- CmdGetBitStream("");
- break;
- }
- }
+ CmdGetBitStream("");
+ break;
+ }
+ }
}
//Attempt to simulate any wave in buffer (one bit per output sample)
// converts GraphBuffer to bitstream (based on zero crossings) if needed.
int CmdLFSim(const char *Cmd)
{
- int i,j;
- static int gap;
+ int i,j;
+ static int gap;
- sscanf(Cmd, "%i", &gap);
+ sscanf(Cmd, "%i", &gap);
// convert to bitstream if necessary
- ChkBitstream(Cmd);
+ ChkBitstream(Cmd);
//can send only 512 bits at a time (1 byte sent per bit...)
- printf("Sending [%d bytes]", GraphTraceLen);
- for (i = 0; i < GraphTraceLen; i += USB_CMD_DATA_SIZE) {
- UsbCommand c={CMD_DOWNLOADED_SIM_SAMPLES_125K, {i, 0, 0}};
-
- for (j = 0; j < USB_CMD_DATA_SIZE; j++) {
- c.d.asBytes[j] = GraphBuffer[i+j];
- }
- SendCommand(&c);
- WaitForResponse(CMD_ACK,NULL);
- printf(".");
- }
-
- printf("\n");
- PrintAndLog("Starting to simulate");
- UsbCommand c = {CMD_SIMULATE_TAG_125K, {GraphTraceLen, gap, 0}};
- SendCommand(&c);
- return 0;
+ printf("Sending [%d bytes]", GraphTraceLen);
+ for (i = 0; i < GraphTraceLen; i += USB_CMD_DATA_SIZE) {
+ UsbCommand c={CMD_DOWNLOADED_SIM_SAMPLES_125K, {i, 0, 0}};
+
+ for (j = 0; j < USB_CMD_DATA_SIZE; j++) {
+ c.d.asBytes[j] = GraphBuffer[i+j];
+ }
+ SendCommand(&c);
+ WaitForResponse(CMD_ACK,NULL);
+ printf(".");
+ }
+
+ printf("\n");
+ PrintAndLog("Starting to simulate");
+ UsbCommand c = {CMD_SIMULATE_TAG_125K, {GraphTraceLen, gap, 0}};
+ SendCommand(&c);
+ return 0;
}
int usage_lf_simfsk(void)
{
- //print help
- PrintAndLog("Usage: lf simfsk [c <clock>] [i] [H <fcHigh>] [L <fcLow>] [d <hexdata>]");
- PrintAndLog("Options: ");
- PrintAndLog(" h This help");
- PrintAndLog(" c <clock> Manually set clock - can autodetect if using DemodBuffer");
- PrintAndLog(" i invert data");
- PrintAndLog(" H <fcHigh> Manually set the larger Field Clock");
- PrintAndLog(" L <fcLow> Manually set the smaller Field Clock");
- //PrintAndLog(" s TBD- -to enable a gap between playback repetitions - default: no gap");
- PrintAndLog(" d <hexdata> Data to sim as hex - omit to sim from DemodBuffer");
- PrintAndLog("\n NOTE: if you set one clock manually set them all manually");
- return 0;
+ //print help
+ PrintAndLog("Usage: lf simfsk [c <clock>] [i] [H <fcHigh>] [L <fcLow>] [d <hexdata>]");
+ PrintAndLog("Options: ");
+ PrintAndLog(" h This help");
+ PrintAndLog(" c <clock> Manually set clock - can autodetect if using DemodBuffer");
+ PrintAndLog(" i invert data");
+ PrintAndLog(" H <fcHigh> Manually set the larger Field Clock");
+ PrintAndLog(" L <fcLow> Manually set the smaller Field Clock");
+ //PrintAndLog(" s TBD- -to enable a gap between playback repetitions - default: no gap");
+ PrintAndLog(" d <hexdata> Data to sim as hex - omit to sim from DemodBuffer");
+ PrintAndLog("\n NOTE: if you set one clock manually set them all manually");
+ return 0;
}
int usage_lf_simask(void)
{
- //print help
- PrintAndLog("Usage: lf simask [c <clock>] [i] [b|m|r] [s] [d <raw hex to sim>]");
- PrintAndLog("Options: ");
- PrintAndLog(" h This help");
- PrintAndLog(" c <clock> Manually set clock - can autodetect if using DemodBuffer");
- PrintAndLog(" i invert data");
- PrintAndLog(" b sim ask/biphase");
- PrintAndLog(" m sim ask/manchester - Default");
- PrintAndLog(" r sim ask/raw");
- PrintAndLog(" s TBD- -to enable a gap between playback repetitions - default: no gap");
- PrintAndLog(" d <hexdata> Data to sim as hex - omit to sim from DemodBuffer");
- return 0;
+ //print help
+ PrintAndLog("Usage: lf simask [c <clock>] [i] [b|m|r] [s] [d <raw hex to sim>]");
+ PrintAndLog("Options: ");
+ PrintAndLog(" h This help");
+ PrintAndLog(" c <clock> Manually set clock - can autodetect if using DemodBuffer");
+ PrintAndLog(" i invert data");
+ PrintAndLog(" b sim ask/biphase");
+ PrintAndLog(" m sim ask/manchester - Default");
+ PrintAndLog(" r sim ask/raw");
+ PrintAndLog(" s TBD- -to enable a gap between playback repetitions - default: no gap");
+ PrintAndLog(" d <hexdata> Data to sim as hex - omit to sim from DemodBuffer");
+ return 0;
}
int usage_lf_simpsk(void)
{
- //print help
- PrintAndLog("Usage: lf simpsk [1|2|3] [c <clock>] [i] [r <carrier>] [d <raw hex to sim>]");
- PrintAndLog("Options: ");
- PrintAndLog(" h This help");
- PrintAndLog(" c <clock> Manually set clock - can autodetect if using DemodBuffer");
- PrintAndLog(" i invert data");
- PrintAndLog(" 1 set PSK1 (default)");
- PrintAndLog(" 2 set PSK2");
- PrintAndLog(" 3 set PSK3");
- PrintAndLog(" r <carrier> 2|4|8 are valid carriers: default = 2");
- PrintAndLog(" d <hexdata> Data to sim as hex - omit to sim from DemodBuffer");
- return 0;
+ //print help
+ PrintAndLog("Usage: lf simpsk [1|2|3] [c <clock>] [i] [r <carrier>] [d <raw hex to sim>]");
+ PrintAndLog("Options: ");
+ PrintAndLog(" h This help");
+ PrintAndLog(" c <clock> Manually set clock - can autodetect if using DemodBuffer");
+ PrintAndLog(" i invert data");
+ PrintAndLog(" 1 set PSK1 (default)");
+ PrintAndLog(" 2 set PSK2");
+ PrintAndLog(" 3 set PSK3");
+ PrintAndLog(" r <carrier> 2|4|8 are valid carriers: default = 2");
+ PrintAndLog(" d <hexdata> Data to sim as hex - omit to sim from DemodBuffer");
+ return 0;
}
// by marshmellow - sim ask data given clock, fcHigh, fcLow, invert
{
//might be able to autodetect FCs and clock from Graphbuffer if using demod buffer
// otherwise will need FChigh, FClow, Clock, and bitstream
- uint8_t fcHigh=0, fcLow=0, clk=0;
- uint8_t invert=0;
- bool errors = FALSE;
- char hexData[32] = {0x00}; // store entered hex data
- uint8_t data[255] = {0x00};
- int dataLen = 0;
- uint8_t cmdp = 0;
- while(param_getchar(Cmd, cmdp) != 0x00)
- {
- switch(param_getchar(Cmd, cmdp))
- {
- case 'h':
- return usage_lf_simfsk();
- case 'i':
- invert = 1;
- cmdp++;
- break;
- case 'c':
- errors |= param_getdec(Cmd,cmdp+1,&clk);
- cmdp+=2;
- break;
- case 'H':
- errors |= param_getdec(Cmd,cmdp+1,&fcHigh);
- cmdp+=2;
- break;
- case 'L':
- errors |= param_getdec(Cmd,cmdp+1,&fcLow);
- cmdp+=2;
- break;
- //case 's':
- // separator=1;
- // cmdp++;
- // break;
- case 'd':
- dataLen = param_getstr(Cmd, cmdp+1, hexData);
- if (dataLen==0) {
- errors=TRUE;
- } else {
- dataLen = hextobinarray((char *)data, hexData);
- }
- if (dataLen==0) errors=TRUE;
- if (errors) PrintAndLog ("Error getting hex data");
- cmdp+=2;
- break;
- default:
- PrintAndLog("Unknown parameter '%c'", param_getchar(Cmd, cmdp));
- errors = TRUE;
- break;
- }
- if(errors) break;
- }
- if(cmdp == 0 && DemodBufferLen == 0)
- {
- errors = TRUE;// No args
- }
-
- //Validations
- if(errors)
- {
- return usage_lf_simfsk();
- }
-
- if (dataLen == 0){ //using DemodBuffer
- if (clk==0 || fcHigh==0 || fcLow==0){ //manual settings must set them all
- uint8_t ans = fskClocks(&fcHigh, &fcLow, &clk, 0);
- if (ans==0){
- if (!fcHigh) fcHigh=10;
- if (!fcLow) fcLow=8;
- if (!clk) clk=50;
- }
- }
- } else {
- setDemodBuf(data, dataLen, 0);
- }
+ uint8_t fcHigh=0, fcLow=0, clk=0;
+ uint8_t invert=0;
+ bool errors = FALSE;
+ char hexData[32] = {0x00}; // store entered hex data
+ uint8_t data[255] = {0x00};
+ int dataLen = 0;
+ uint8_t cmdp = 0;
+ while(param_getchar(Cmd, cmdp) != 0x00)
+ {
+ switch(param_getchar(Cmd, cmdp))
+ {
+ case 'h':
+ return usage_lf_simfsk();
+ case 'i':
+ invert = 1;
+ cmdp++;
+ break;
+ case 'c':
+ errors |= param_getdec(Cmd,cmdp+1,&clk);
+ cmdp+=2;
+ break;
+ case 'H':
+ errors |= param_getdec(Cmd,cmdp+1,&fcHigh);
+ cmdp+=2;
+ break;
+ case 'L':
+ errors |= param_getdec(Cmd,cmdp+1,&fcLow);
+ cmdp+=2;
+ break;
+ //case 's':
+ // separator=1;
+ // cmdp++;
+ // break;
+ case 'd':
+ dataLen = param_getstr(Cmd, cmdp+1, hexData);
+ if (dataLen==0) {
+ errors=TRUE;
+ } else {
+ dataLen = hextobinarray((char *)data, hexData);
+ }
+ if (dataLen==0) errors=TRUE;
+ if (errors) PrintAndLog ("Error getting hex data");
+ cmdp+=2;
+ break;
+ default:
+ PrintAndLog("Unknown parameter '%c'", param_getchar(Cmd, cmdp));
+ errors = TRUE;
+ break;
+ }
+ if(errors) break;
+ }
+ if(cmdp == 0 && DemodBufferLen == 0)
+ {
+ errors = TRUE;// No args
+ }
+
+ //Validations
+ if(errors)
+ {
+ return usage_lf_simfsk();
+ }
+
+ if (dataLen == 0){ //using DemodBuffer
+ if (clk==0 || fcHigh==0 || fcLow==0){ //manual settings must set them all
+ uint8_t ans = fskClocks(&fcHigh, &fcLow, &clk, 0);
+ if (ans==0){
+ if (!fcHigh) fcHigh=10;
+ if (!fcLow) fcLow=8;
+ if (!clk) clk=50;
+ }
+ }
+ } else {
+ setDemodBuf(data, dataLen, 0);
+ }
//default if not found
- if (clk == 0) clk = 50;
- if (fcHigh == 0) fcHigh = 10;
- if (fcLow == 0) fcLow = 8;
-
- uint16_t arg1, arg2;
- arg1 = fcHigh << 8 | fcLow;
- arg2 = invert << 8 | clk;
- size_t size = DemodBufferLen;
- if (size > USB_CMD_DATA_SIZE) {
- PrintAndLog("DemodBuffer too long for current implementation - length: %d - max: %d", size, USB_CMD_DATA_SIZE);
- size = USB_CMD_DATA_SIZE;
- }
- UsbCommand c = {CMD_FSK_SIM_TAG, {arg1, arg2, size}};
-
- memcpy(c.d.asBytes, DemodBuffer, size);
- SendCommand(&c);
- return 0;
+ if (clk == 0) clk = 50;
+ if (fcHigh == 0) fcHigh = 10;
+ if (fcLow == 0) fcLow = 8;
+
+ uint16_t arg1, arg2;
+ arg1 = fcHigh << 8 | fcLow;
+ arg2 = invert << 8 | clk;
+ size_t size = DemodBufferLen;
+ if (size > USB_CMD_DATA_SIZE) {
+ PrintAndLog("DemodBuffer too long for current implementation - length: %d - max: %d", size, USB_CMD_DATA_SIZE);
+ size = USB_CMD_DATA_SIZE;
+ }
+ UsbCommand c = {CMD_FSK_SIM_TAG, {arg1, arg2, size}};
+
+ memcpy(c.d.asBytes, DemodBuffer, size);
+ SendCommand(&c);
+ return 0;
}
// by marshmellow - sim ask data given clock, invert, manchester or raw, separator
// - allow pull data from DemodBuffer
int CmdLFaskSim(const char *Cmd)
{
- //autodetect clock from Graphbuffer if using demod buffer
+ //autodetect clock from Graphbuffer if using demod buffer
// needs clock, invert, manchester/raw as m or r, separator as s, and bitstream
- uint8_t encoding = 1, separator = 0;
- uint8_t clk=0, invert=0;
- bool errors = FALSE;
- char hexData[32] = {0x00};
- uint8_t data[255]= {0x00}; // store entered hex data
- int dataLen = 0;
- uint8_t cmdp = 0;
- while(param_getchar(Cmd, cmdp) != 0x00)
- {
- switch(param_getchar(Cmd, cmdp))
- {
- case 'h':
- return usage_lf_simask();
- case 'i':
- invert = 1;
- cmdp++;
- break;
- case 'c':
- errors |= param_getdec(Cmd,cmdp+1,&clk);
- cmdp+=2;
- break;
- case 'b':
- encoding=2; //biphase
- cmdp++;
- break;
- case 'm':
- encoding=1;
- cmdp++;
- break;
- case 'r':
- encoding=0;
- cmdp++;
- break;
- case 's':
- separator=1;
- cmdp++;
- break;
- case 'd':
- dataLen = param_getstr(Cmd, cmdp+1, hexData);
- if (dataLen==0) {
- errors=TRUE;
- } else {
- dataLen = hextobinarray((char *)data, hexData);
- }
- if (dataLen==0) errors=TRUE;
- if (errors) PrintAndLog ("Error getting hex data, datalen: %d",dataLen);
- cmdp+=2;
- break;
- default:
- PrintAndLog("Unknown parameter '%c'", param_getchar(Cmd, cmdp));
- errors = TRUE;
- break;
- }
- if(errors) break;
- }
- if(cmdp == 0 && DemodBufferLen == 0)
- {
- errors = TRUE;// No args
- }
-
- //Validations
- if(errors)
- {
- return usage_lf_simask();
- }
- if (dataLen == 0){ //using DemodBuffer
- if (clk == 0) clk = GetAskClock("0", false, false);
- } else {
- setDemodBuf(data, dataLen, 0);
- }
- if (clk == 0) clk = 64;
- if (encoding == 0) clk = clk/2; //askraw needs to double the clock speed
- uint16_t arg1, arg2;
- size_t size=DemodBufferLen;
- arg1 = clk << 8 | encoding;
- arg2 = invert << 8 | separator;
- if (size > USB_CMD_DATA_SIZE) {
- PrintAndLog("DemodBuffer too long for current implementation - length: %d - max: %d", size, USB_CMD_DATA_SIZE);
- size = USB_CMD_DATA_SIZE;
- }
- UsbCommand c = {CMD_ASK_SIM_TAG, {arg1, arg2, size}};
- PrintAndLog("preparing to sim ask data: %d bits", size);
- memcpy(c.d.asBytes, DemodBuffer, size);
- SendCommand(&c);
- return 0;
+ uint8_t encoding = 1, separator = 0;
+ uint8_t clk=0, invert=0;
+ bool errors = FALSE;
+ char hexData[32] = {0x00};
+ uint8_t data[255]= {0x00}; // store entered hex data
+ int dataLen = 0;
+ uint8_t cmdp = 0;
+ while(param_getchar(Cmd, cmdp) != 0x00)
+ {
+ switch(param_getchar(Cmd, cmdp))
+ {
+ case 'h':
+ return usage_lf_simask();
+ case 'i':
+ invert = 1;
+ cmdp++;
+ break;
+ case 'c':
+ errors |= param_getdec(Cmd,cmdp+1,&clk);
+ cmdp+=2;
+ break;
+ case 'b':
+ encoding=2; //biphase
+ cmdp++;
+ break;
+ case 'm':
+ encoding=1;
+ cmdp++;
+ break;
+ case 'r':
+ encoding=0;
+ cmdp++;
+ break;
+ case 's':
+ separator=1;
+ cmdp++;
+ break;
+ case 'd':
+ dataLen = param_getstr(Cmd, cmdp+1, hexData);
+ if (dataLen==0) {
+ errors=TRUE;
+ } else {
+ dataLen = hextobinarray((char *)data, hexData);
+ }
+ if (dataLen==0) errors=TRUE;
+ if (errors) PrintAndLog ("Error getting hex data, datalen: %d",dataLen);
+ cmdp+=2;
+ break;
+ default:
+ PrintAndLog("Unknown parameter '%c'", param_getchar(Cmd, cmdp));
+ errors = TRUE;
+ break;
+ }
+ if(errors) break;
+ }
+ if(cmdp == 0 && DemodBufferLen == 0)
+ {
+ errors = TRUE;// No args
+ }
+
+ //Validations
+ if(errors)
+ {
+ return usage_lf_simask();
+ }
+ if (dataLen == 0){ //using DemodBuffer
+ if (clk == 0) clk = GetAskClock("0", false, false);
+ } else {
+ setDemodBuf(data, dataLen, 0);
+ }
+ if (clk == 0) clk = 64;
+ if (encoding == 0) clk = clk/2; //askraw needs to double the clock speed
+ uint16_t arg1, arg2;
+ size_t size=DemodBufferLen;
+ arg1 = clk << 8 | encoding;
+ arg2 = invert << 8 | separator;
+ if (size > USB_CMD_DATA_SIZE) {
+ PrintAndLog("DemodBuffer too long for current implementation - length: %d - max: %d", size, USB_CMD_DATA_SIZE);
+ size = USB_CMD_DATA_SIZE;
+ }
+ UsbCommand c = {CMD_ASK_SIM_TAG, {arg1, arg2, size}};
+ PrintAndLog("preparing to sim ask data: %d bits", size);
+ memcpy(c.d.asBytes, DemodBuffer, size);
+ SendCommand(&c);
+ return 0;
}
// by marshmellow - sim psk data given carrier, clock, invert
// - allow pull data from DemodBuffer or parameters
int CmdLFpskSim(const char *Cmd)
{
- //might be able to autodetect FC and clock from Graphbuffer if using demod buffer
- //will need carrier, Clock, and bitstream
- uint8_t carrier=0, clk=0;
- uint8_t invert=0;
- bool errors = FALSE;
- char hexData[32] = {0x00}; // store entered hex data
- uint8_t data[255] = {0x00};
- int dataLen = 0;
- uint8_t cmdp = 0;
- uint8_t pskType = 1;
- while(param_getchar(Cmd, cmdp) != 0x00)
- {
- switch(param_getchar(Cmd, cmdp))
- {
- case 'h':
- return usage_lf_simpsk();
- case 'i':
- invert = 1;
- cmdp++;
- break;
- case 'c':
- errors |= param_getdec(Cmd,cmdp+1,&clk);
- cmdp+=2;
- break;
- case 'r':
- errors |= param_getdec(Cmd,cmdp+1,&carrier);
- cmdp+=2;
- break;
- case '1':
- pskType=1;
- cmdp++;
- break;
- case '2':
- pskType=2;
- cmdp++;
- break;
- case '3':
- pskType=3;
- cmdp++;
- break;
- case 'd':
- dataLen = param_getstr(Cmd, cmdp+1, hexData);
- if (dataLen==0) {
- errors=TRUE;
- } else {
- dataLen = hextobinarray((char *)data, hexData);
- }
- if (dataLen==0) errors=TRUE;
- if (errors) PrintAndLog ("Error getting hex data");
- cmdp+=2;
- break;
- default:
- PrintAndLog("Unknown parameter '%c'", param_getchar(Cmd, cmdp));
- errors = TRUE;
- break;
- }
- if (errors) break;
- }
- if (cmdp == 0 && DemodBufferLen == 0)
- {
- errors = TRUE;// No args
- }
-
- //Validations
- if (errors)
- {
- return usage_lf_simpsk();
- }
- if (dataLen == 0){ //using DemodBuffer
- PrintAndLog("Getting Clocks");
- if (clk==0) clk = GetPskClock("", FALSE, FALSE);
- PrintAndLog("clk: %d",clk);
- if (!carrier) carrier = GetPskCarrier("", FALSE, FALSE);
- PrintAndLog("carrier: %d", carrier);
- } else {
- setDemodBuf(data, dataLen, 0);
- }
-
- if (clk <= 0) clk = 32;
- if (carrier == 0) carrier = 2;
- if (pskType != 1){
- if (pskType == 2){
- //need to convert psk2 to psk1 data before sim
- psk2TOpsk1(DemodBuffer, DemodBufferLen);
- } else {
- PrintAndLog("Sorry, PSK3 not yet available");
- }
- }
- uint16_t arg1, arg2;
- arg1 = clk << 8 | carrier;
- arg2 = invert;
- size_t size=DemodBufferLen;
- if (size > USB_CMD_DATA_SIZE) {
- PrintAndLog("DemodBuffer too long for current implementation - length: %d - max: %d", size, USB_CMD_DATA_SIZE);
- size=USB_CMD_DATA_SIZE;
- }
- UsbCommand c = {CMD_PSK_SIM_TAG, {arg1, arg2, size}};
- PrintAndLog("DEBUG: Sending DemodBuffer Length: %d", size);
- memcpy(c.d.asBytes, DemodBuffer, size);
- SendCommand(&c);
-
- return 0;
+ //might be able to autodetect FC and clock from Graphbuffer if using demod buffer
+ //will need carrier, Clock, and bitstream
+ uint8_t carrier=0, clk=0;
+ uint8_t invert=0;
+ bool errors = FALSE;
+ char hexData[32] = {0x00}; // store entered hex data
+ uint8_t data[255] = {0x00};
+ int dataLen = 0;
+ uint8_t cmdp = 0;
+ uint8_t pskType = 1;
+ while(param_getchar(Cmd, cmdp) != 0x00)
+ {
+ switch(param_getchar(Cmd, cmdp))
+ {
+ case 'h':
+ return usage_lf_simpsk();
+ case 'i':
+ invert = 1;
+ cmdp++;
+ break;
+ case 'c':
+ errors |= param_getdec(Cmd,cmdp+1,&clk);
+ cmdp+=2;
+ break;
+ case 'r':
+ errors |= param_getdec(Cmd,cmdp+1,&carrier);
+ cmdp+=2;
+ break;
+ case '1':
+ pskType=1;
+ cmdp++;
+ break;
+ case '2':
+ pskType=2;
+ cmdp++;
+ break;
+ case '3':
+ pskType=3;
+ cmdp++;
+ break;
+ case 'd':
+ dataLen = param_getstr(Cmd, cmdp+1, hexData);
+ if (dataLen==0) {
+ errors=TRUE;
+ } else {
+ dataLen = hextobinarray((char *)data, hexData);
+ }
+ if (dataLen==0) errors=TRUE;
+ if (errors) PrintAndLog ("Error getting hex data");
+ cmdp+=2;
+ break;
+ default:
+ PrintAndLog("Unknown parameter '%c'", param_getchar(Cmd, cmdp));
+ errors = TRUE;
+ break;
+ }
+ if (errors) break;
+ }
+ if (cmdp == 0 && DemodBufferLen == 0)
+ {
+ errors = TRUE;// No args
+ }
+
+ //Validations
+ if (errors)
+ {
+ return usage_lf_simpsk();
+ }
+ if (dataLen == 0){ //using DemodBuffer
+ PrintAndLog("Getting Clocks");
+ if (clk==0) clk = GetPskClock("", FALSE, FALSE);
+ PrintAndLog("clk: %d",clk);
+ if (!carrier) carrier = GetPskCarrier("", FALSE, FALSE);
+ PrintAndLog("carrier: %d", carrier);
+ } else {
+ setDemodBuf(data, dataLen, 0);
+ }
+
+ if (clk <= 0) clk = 32;
+ if (carrier == 0) carrier = 2;
+ if (pskType != 1){
+ if (pskType == 2){
+ //need to convert psk2 to psk1 data before sim
+ psk2TOpsk1(DemodBuffer, DemodBufferLen);
+ } else {
+ PrintAndLog("Sorry, PSK3 not yet available");
+ }
+ }
+ uint16_t arg1, arg2;
+ arg1 = clk << 8 | carrier;
+ arg2 = invert;
+ size_t size=DemodBufferLen;
+ if (size > USB_CMD_DATA_SIZE) {
+ PrintAndLog("DemodBuffer too long for current implementation - length: %d - max: %d", size, USB_CMD_DATA_SIZE);
+ size=USB_CMD_DATA_SIZE;
+ }
+ UsbCommand c = {CMD_PSK_SIM_TAG, {arg1, arg2, size}};
+ PrintAndLog("DEBUG: Sending DemodBuffer Length: %d", size);
+ memcpy(c.d.asBytes, DemodBuffer, size);
+ SendCommand(&c);
+
+ return 0;
}
int CmdLFSimBidir(const char *Cmd)
{
- // Set ADC to twice the carrier for a slight supersampling
- // HACK: not implemented in ARMSRC.
- PrintAndLog("Not implemented yet.");
- UsbCommand c = {CMD_LF_SIMULATE_BIDIR, {47, 384, 0}};
- SendCommand(&c);
- return 0;
+ // Set ADC to twice the carrier for a slight supersampling
+ // HACK: not implemented in ARMSRC.
+ PrintAndLog("Not implemented yet.");
+ UsbCommand c = {CMD_LF_SIMULATE_BIDIR, {47, 384, 0}};
+ SendCommand(&c);
+ return 0;
}
int CmdVchDemod(const char *Cmd)
{
- // Is this the entire sync pattern, or does this also include some
- // data bits that happen to be the same everywhere? That would be
- // lovely to know.
- static const int SyncPattern[] = {
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
- 1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
- 1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
- 1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
- 1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
- 1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
- };
-
- // So first, we correlate for the sync pattern, and mark that.
- int bestCorrel = 0, bestPos = 0;
- int i;
- // It does us no good to find the sync pattern, with fewer than
- // 2048 samples after it...
- for (i = 0; i < (GraphTraceLen-2048); i++) {
- int sum = 0;
- int j;
- for (j = 0; j < arraylen(SyncPattern); j++) {
- sum += GraphBuffer[i+j]*SyncPattern[j];
- }
- if (sum > bestCorrel) {
- bestCorrel = sum;
- bestPos = i;
- }
- }
- PrintAndLog("best sync at %d [metric %d]", bestPos, bestCorrel);
-
- char bits[257];
- bits[256] = '\0';
-
- int worst = INT_MAX;
- int worstPos = 0;
-
- for (i = 0; i < 2048; i += 8) {
- int sum = 0;
- int j;
- for (j = 0; j < 8; j++) {
- sum += GraphBuffer[bestPos+i+j];
- }
- if (sum < 0) {
- bits[i/8] = '.';
- } else {
- bits[i/8] = '1';
- }
- if(abs(sum) < worst) {
- worst = abs(sum);
- worstPos = i;
- }
- }
- PrintAndLog("bits:");
- PrintAndLog("%s", bits);
- PrintAndLog("worst metric: %d at pos %d", worst, worstPos);
-
- if (strcmp(Cmd, "clone")==0) {
- GraphTraceLen = 0;
- char *s;
- for(s = bits; *s; s++) {
- int j;
- for(j = 0; j < 16; j++) {
- GraphBuffer[GraphTraceLen++] = (*s == '1') ? 1 : 0;
- }
- }
- RepaintGraphWindow();
- }
- return 0;
+ // Is this the entire sync pattern, or does this also include some
+ // data bits that happen to be the same everywhere? That would be
+ // lovely to know.
+ static const int SyncPattern[] = {
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ };
+
+ // So first, we correlate for the sync pattern, and mark that.
+ int bestCorrel = 0, bestPos = 0;
+ int i;
+ // It does us no good to find the sync pattern, with fewer than
+ // 2048 samples after it...
+ for (i = 0; i < (GraphTraceLen-2048); i++) {
+ int sum = 0;
+ int j;
+ for (j = 0; j < arraylen(SyncPattern); j++) {
+ sum += GraphBuffer[i+j]*SyncPattern[j];
+ }
+ if (sum > bestCorrel) {
+ bestCorrel = sum;
+ bestPos = i;
+ }
+ }
+ PrintAndLog("best sync at %d [metric %d]", bestPos, bestCorrel);
+
+ char bits[257];
+ bits[256] = '\0';
+
+ int worst = INT_MAX;
+ int worstPos = 0;
+
+ for (i = 0; i < 2048; i += 8) {
+ int sum = 0;
+ int j;
+ for (j = 0; j < 8; j++) {
+ sum += GraphBuffer[bestPos+i+j];
+ }
+ if (sum < 0) {
+ bits[i/8] = '.';
+ } else {
+ bits[i/8] = '1';
+ }
+ if(abs(sum) < worst) {
+ worst = abs(sum);
+ worstPos = i;
+ }
+ }
+ PrintAndLog("bits:");
+ PrintAndLog("%s", bits);
+ PrintAndLog("worst metric: %d at pos %d", worst, worstPos);
+
+ if (strcmp(Cmd, "clone")==0) {
+ GraphTraceLen = 0;
+ char *s;
+ for(s = bits; *s; s++) {
+ int j;
+ for(j = 0; j < 16; j++) {
+ GraphBuffer[GraphTraceLen++] = (*s == '1') ? 1 : 0;
+ }
+ }
+ RepaintGraphWindow();
+ }
+ return 0;
}
//by marshmellow
int CmdLFfind(const char *Cmd)
{
- int ans=0;
- char cmdp = param_getchar(Cmd, 0);
- char testRaw = param_getchar(Cmd, 1);
- if (strlen(Cmd) > 3 || cmdp == 'h' || cmdp == 'H') {
- PrintAndLog("Usage: lf search <0|1> [u]");
- PrintAndLog(" <use data from Graphbuffer> , if not set, try reading data from tag.");
- PrintAndLog(" [Search for Unknown tags] , if not set, reads only known tags.");
- PrintAndLog("");
- PrintAndLog(" sample: lf search = try reading data from tag & search for known tags");
- PrintAndLog(" : lf search 1 = use data from GraphBuffer & search for known tags");
- PrintAndLog(" : lf search u = try reading data from tag & search for known and unknown tags");
- PrintAndLog(" : lf search 1 u = use data from GraphBuffer & search for known and unknown tags");
-
- return 0;
- }
-
- if (!offline && (cmdp != '1')){
+ int ans=0;
+ char cmdp = param_getchar(Cmd, 0);
+ char testRaw = param_getchar(Cmd, 1);
+ if (strlen(Cmd) > 3 || cmdp == 'h' || cmdp == 'H') {
+ PrintAndLog("Usage: lf search <0|1> [u]");
+ PrintAndLog(" <use data from Graphbuffer> , if not set, try reading data from tag.");
+ PrintAndLog(" [Search for Unknown tags] , if not set, reads only known tags.");
+ PrintAndLog("");
+ PrintAndLog(" sample: lf search = try reading data from tag & search for known tags");
+ PrintAndLog(" : lf search 1 = use data from GraphBuffer & search for known tags");
+ PrintAndLog(" : lf search u = try reading data from tag & search for known and unknown tags");
+ PrintAndLog(" : lf search 1 u = use data from GraphBuffer & search for known and unknown tags");
+ return 0;
+ }
+
+ if (!offline && (cmdp != '1')){
CmdLFRead("s");
getSamples("30000",false);
- } else if (GraphTraceLen < 1000) {
- PrintAndLog("Data in Graphbuffer was too small.");
- return 0;
- }
- if (cmdp == 'u' || cmdp == 'U') testRaw = 'u';
-
- PrintAndLog("NOTE: some demods output possible binary\n if it finds something that looks like a tag");
- PrintAndLog("False Positives ARE possible\n");
- PrintAndLog("\nChecking for known tags:\n");
-
- ans=CmdFSKdemodIO("");
- if (ans>0) {
- PrintAndLog("\nValid IO Prox ID Found!");
- return 1;
- }
-
- ans=CmdFSKdemodPyramid("");
- if (ans>0) {
- PrintAndLog("\nValid Pyramid ID Found!");
- return 1;
- }
-
- ans=CmdFSKdemodParadox("");
- if (ans>0) {
- PrintAndLog("\nValid Paradox ID Found!");
- return 1;
- }
-
- ans=CmdFSKdemodAWID("");
- if (ans>0) {
- PrintAndLog("\nValid AWID ID Found!");
- return 1;
- }
-
- ans=CmdFSKdemodHID("");
- if (ans>0) {
- PrintAndLog("\nValid HID Prox ID Found!");
- return 1;
- }
-
- //add psk and indala
- ans=CmdIndalaDecode("");
- if (ans>0) {
- PrintAndLog("\nValid Indala ID Found!");
- return 1;
- }
-
- ans=CmdAskEM410xDemod("");
- if (ans>0) {
- PrintAndLog("\nValid EM410x ID Found!");
- return 1;
- }
-
- ans=CmdG_Prox_II_Demod("");
- if (ans>0) {
- PrintAndLog("\nValid G Prox II ID Found!");
- return 1;
- }
+ } else if (GraphTraceLen < 1000) {
+ PrintAndLog("Data in Graphbuffer was too small.");
+ return 0;
+ }
+ if (cmdp == 'u' || cmdp == 'U') testRaw = 'u';
+
+ PrintAndLog("NOTE: some demods output possible binary\n if it finds something that looks like a tag");
+ PrintAndLog("False Positives ARE possible\n");
+ PrintAndLog("\nChecking for known tags:\n");
+
+ ans=CmdFSKdemodIO("");
+
+ if (ans>0) {
+ PrintAndLog("\nValid IO Prox ID Found!");
+ return 1;
+ }
+
+ ans=CmdFSKdemodPyramid("");
+ if (ans>0) {
+ PrintAndLog("\nValid Pyramid ID Found!");
+ return 1;
+ }
+
+ ans=CmdFSKdemodParadox("");
+ if (ans>0) {
+ PrintAndLog("\nValid Paradox ID Found!");
+ return 1;
+ }
+
+ ans=CmdFSKdemodAWID("");
+ if (ans>0) {
+ PrintAndLog("\nValid AWID ID Found!");
+ return 1;
+ }
+
+ ans=CmdFSKdemodHID("");
+ if (ans>0) {
+ PrintAndLog("\nValid HID Prox ID Found!");
+ return 1;
+ }
+
+ //add psk and indala
+ ans=CmdIndalaDecode("");
+ if (ans>0) {
+ PrintAndLog("\nValid Indala ID Found!");
+ return 1;
+ }
+
+ ans=CmdAskEM410xDemod("");
+ if (ans>0) {
+ PrintAndLog("\nValid EM410x ID Found!");
+ return 1;
+ }
+
+ ans=CmdG_Prox_II_Demod("");
+ if (ans>0) {
+ PrintAndLog("\nValid G Prox II ID Found!");
+ return 1;
+ }
ans=EM4x50Read("", false);
if (ans>0) {
return 1;
}
- PrintAndLog("\nNo Known Tags Found!\n");
- if (testRaw=='u' || testRaw=='U'){
- //test unknown tag formats (raw mode)
- PrintAndLog("\nChecking for Unknown tags:\n");
- ans=AutoCorrelate(4000, FALSE, FALSE);
- if (ans > 0) PrintAndLog("Possible Auto Correlation of %d repeating samples",ans);
- ans=GetFskClock("",FALSE,FALSE);
- if (ans != 0){ //fsk
- ans=FSKrawDemod("",TRUE);
- if (ans>0) {
- PrintAndLog("\nUnknown FSK Modulated Tag Found!");
- return 1;
+ PrintAndLog("\nNo Known Tags Found!\n");
+ if (testRaw=='u' || testRaw=='U'){
+ //test unknown tag formats (raw mode)
+ PrintAndLog("\nChecking for Unknown tags:\n");
+ ans=AutoCorrelate(4000, FALSE, FALSE);
+
+ if (ans > 0) {
+
+ PrintAndLog("Possible Auto Correlation of %d repeating samples",ans);
+
+ if ( ans % 8 == 0) {
+ int bytes = (ans / 8);
+ PrintAndLog("Possible %d bytes", bytes);
+ int blocks = 0;
+ if ( bytes % 2 == 0) {
+ blocks = (bytes / 2);
+ PrintAndLog("Possible 2 blocks, width %d", blocks);
+ }
+ if ( bytes % 4 == 0) {
+ blocks = (bytes / 4);
+ PrintAndLog("Possible 4 blocks, width %d", blocks);
+ }
+ if ( bytes % 8 == 0) {
+ blocks = (bytes / 8);
+ PrintAndLog("Possible 8 blocks, width %d", blocks);
+ }
+ if ( bytes % 16 == 0) {
+ blocks = (bytes / 16);
+ PrintAndLog("Possible 16 blocks, width %d", blocks);
}
}
- ans=ASKDemod("0 0 0",TRUE,FALSE,1);
- if (ans>0) {
- PrintAndLog("\nUnknown ASK Modulated and Manchester encoded Tag Found!");
- PrintAndLog("\nif it does not look right it could instead be ASK/Biphase - try 'data rawdemod ab'");
- return 1;
- }
- ans=CmdPSK1rawDemod("");
- if (ans>0) {
- PrintAndLog("Possible unknown PSK1 Modulated Tag Found above!\n\nCould also be PSK2 - try 'data rawdemod p2'");
- PrintAndLog("\nCould also be PSK3 - [currently not supported]");
- PrintAndLog("\nCould also be NRZ - try 'data nrzrawdemod");
- return 1;
- }
- PrintAndLog("\nNo Data Found!\n");
}
- return 0;
+ ans=GetFskClock("",FALSE,FALSE);
+ if (ans != 0){ //fsk
+ ans=FSKrawDemod("",TRUE);
+ if (ans>0) {
+ PrintAndLog("\nUnknown FSK Modulated Tag Found!");
+ return 1;
+ }
+ }
+ ans=ASKDemod("0 0 0",TRUE,FALSE,1);
+ if (ans>0) {
+ PrintAndLog("\nUnknown ASK Modulated and Manchester encoded Tag Found!");
+ PrintAndLog("\nif it does not look right it could instead be ASK/Biphase - try 'data rawdemod ab'");
+ return 1;
+ }
+ ans=CmdPSK1rawDemod("");
+ if (ans>0) {
+ PrintAndLog("Possible unknown PSK1 Modulated Tag Found above!\n\nCould also be PSK2 - try 'data rawdemod p2'");
+ PrintAndLog("\nCould also be PSK3 - [currently not supported]");
+ PrintAndLog("\nCould also be NRZ - try 'data nrzrawdemod");
+ return 1;
+ }
+ PrintAndLog("\nNo Data Found!\n");
+ }
+ 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... }"},
- {"config", CmdLFSetConfig, 0, "Set config for LF sampling, bit/sample, decimation, frequency"},
- {"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, "['s' silent] Read 125/134 kHz LF ID-only tag. Do 'lf read h' for help"},
- {"search", CmdLFfind, 1, "[offline] ['u'] Read and Search for valid known tag (in offline mode it you can load first then search) - 'u' to search for unknown tags"},
- {"sim", CmdLFSim, 0, "[GAP] -- Simulate LF tag from buffer with optional GAP (in microseconds)"},
- {"simask", CmdLFaskSim, 0, "[clock] [invert <1|0>] [manchester/raw <'m'|'r'>] [msg separator 's'] [d <hexdata>] -- Simulate LF ASK tag from demodbuffer or input"},
- {"simfsk", CmdLFfskSim, 0, "[c <clock>] [i] [H <fcHigh>] [L <fcLow>] [d <hexdata>] -- Simulate LF FSK tag from demodbuffer or input"},
- {"simpsk", CmdLFpskSim, 0, "[1|2|3] [c <clock>] [i] [r <carrier>] [d <raw hex to sim>] -- Simulate LF PSK tag from demodbuffer or input"},
- {"simbidir", CmdLFSimBidir, 0, "Simulate LF tag (with bidirectional data transmission between reader and 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}
+ {"help", CmdHelp, 1, "This help"},
+ {"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' 134] \n\t\t-- Modulate LF reader field to send command before read (all periods in microseconds)"},
+ {"flexdemod", CmdFlexdemod, 1, "Demodulate samples for FlexPass"},
+ {"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, "['s' silent] Read 125/134 kHz LF ID-only tag. Do 'lf read h' for help"},
+ {"search", CmdLFfind, 1, "[offline] ['u'] Read and Search for valid known tag (in offline mode it you can load first then search) \n\t\t- 'u' to search for unknown tags"},
+ {"sim", CmdLFSim, 0, "[GAP] -- Simulate LF tag from buffer with optional GAP (in microseconds)"},
+ {"simask", CmdLFaskSim, 0, "[clock] [invert <1|0>] [manchester/raw <'m'|'r'>] [msg separator 's'] [d <hexdata>] \n\t\t-- Simulate LF ASK tag from demodbuffer or input"},
+ {"simfsk", CmdLFfskSim, 0, "[c <clock>] [i] [H <fcHigh>] [L <fcLow>] [d <hexdata>] \n\t\t-- Simulate LF FSK tag from demodbuffer or input"},
+ {"simpsk", CmdLFpskSim, 0, "[1|2|3] [c <clock>] [i] [r <carrier>] [d <raw hex to sim>] \n\t\t-- Simulate LF PSK tag from demodbuffer or input"},
+ {"simbidir", CmdLFSimBidir, 0, "Simulate LF tag (with bidirectional data transmission between reader and tag)"},
+ {"snoop", CmdLFSnoop, 0, "['l'|'h'|<divisor>] [trigger threshold] -- Snoop LF (l:125khz, h:134khz)"},
+ {"vchdemod", CmdVchDemod, 1, "['clone'] -- Demodulate samples for VeriChip"},
+ {NULL, NULL, 0, NULL}
};
int CmdLF(const char *Cmd)
{
- CmdsParse(CommandTable, Cmd);
- return 0;
+ CmdsParse(CommandTable, Cmd);
+ return 0;
}
int CmdHelp(const char *Cmd)
{
- CmdsHelp(CommandTable);
- return 0;
+ 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 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
uint8_t uid[5] = {0x00};
if (cmdp == 'h' || cmdp == 'H') {
- PrintAndLog("Usage: lf em4x 410xsim <UID>");
+ PrintAndLog("Usage: lf em4x em410xsim <UID>");
PrintAndLog("");
- PrintAndLog(" sample: lf em4x 410xsim 0F0368568B");
+ PrintAndLog(" sample: lf em4x em410xsim 0F0368568B");
return 0;
}
#include "cmdmain.h"
#include "util.h"
#include "cmdscript.h"
+#include "cmdcrc.h"
unsigned int current_command = CMD_UNKNOWN;
static command_t CommandTable[] =
{
- {"help", CmdHelp, 1, "This help. Use '<command> help' for details of a particular command."},
- {"data", CmdData, 1, "{ Plot window / data buffer manipulation... }"},
- {"hf", CmdHF, 1, "{ High Frequency commands... }"},
- {"hw", CmdHW, 1, "{ Hardware commands... }"},
- {"lf", CmdLF, 1, "{ Low Frequency commands... }"},
- {"script", CmdScript, 1,"{ Scripting commands }"},
- {"quit", CmdQuit, 1, "Exit program"},
- {"exit", CmdQuit, 1, "Exit program"},
- {NULL, NULL, 0, NULL}
+ {"help", CmdHelp, 1, "This help. Use '<command> help' for details of a particular command."},
+ {"crc", CmdCrc, 1, "Crc calculations from the software reveng1-30"},
+ {"data", CmdData, 1, "{ Plot window / data buffer manipulation... }"},
+ {"hf", CmdHF, 1, "{ High Frequency commands... }"},
+ {"hw", CmdHW, 1, "{ Hardware commands... }"},
+ {"lf", CmdLF, 1, "{ Low Frequency commands... }"},
+ {"script", CmdScript, 1, "{ Scripting commands }"},
+ {"quit", CmdQuit, 1, "Exit program"},
+ {"exit", CmdQuit, 1, "Exit program"},
+ {NULL, NULL, 0, NULL}
};
command_t* getTopLevelCommandTable()
#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
--//ultralightC
CMD_MIFAREUC_AUTH = 0x0724,
- CMD_MIFAREUC_SETPWD = 0x0727,
- CMD_MIFAREU_SETUID = 0x0728,
+ CMD_MIFAREUC_SETPWD = 0x0727,
+ CMD_MIFAREU_SETUID = 0x0728,
--// mifare desfire
CMD_MIFARE_DESFIRE_READBL = 0x0728,
convert_bin_to_html = convert_bin_to_html,
convert_eml_to_html = convert_eml_to_html,
convert_eml_to_bin = convert_eml_to_bin,
- SaveAsBinary = save_BIN,
+ SaveAsBinary = save_BIN,
+ SaveAsText = save_TEXT,
+ SaveAsBinary = save_BIN,
SaveAsText = save_TEXT,
}
#include "mifarehost.h"\r
#include "proxmark3.h"\r
\r
+#define llx PRIx64\r
+\r
// MIFARE\r
int compar_int(const void * a, const void * b) {\r
// didn't work: (the result is truncated to 32 bits)\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
struct Crypto1State *traceCrypto1 = NULL;\r
\r
-struct Crypto1State *revstate;\r
-uint64_t lfsr;\r
-uint32_t ks2;\r
-uint32_t ks3;\r
+struct Crypto1State *revstate = NULL;\r
\r
-uint32_t uid; // serial number\r
-uint32_t nt; // tag challenge\r
-uint32_t nr_enc; // encrypted reader challenge\r
-uint32_t ar_enc; // encrypted reader response\r
-uint32_t at_enc; // encrypted tag response\r
+uint64_t key = 0;\r
+uint32_t ks2 = 0;\r
+uint32_t ks3 = 0;\r
+\r
+uint32_t uid = 0; // serial number\r
+uint32_t nt =0; // tag challenge\r
+uint32_t nr_enc =0; // encrypted reader challenge\r
+uint32_t ar_enc =0; // encrypted reader response\r
+uint32_t at_enc =0; // encrypted tag response\r
\r
int isTraceCardEmpty(void) {\r
return ((traceCard[0] == 0) && (traceCard[1] == 0) && (traceCard[2] == 0) && (traceCard[3] == 0));\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
lfsr_rollback_word(revstate, nr_enc, 1);\r
lfsr_rollback_word(revstate, uid ^ nt, 0);\r
\r
- crypto1_get_lfsr(revstate, &lfsr);\r
- printf("key> %x%x\n", (unsigned int)((lfsr & 0xFFFFFFFF00000000) >> 32), (unsigned int)(lfsr & 0xFFFFFFFF));\r
- AddLogUint64(logHexFileName, "key> ", lfsr); \r
+ crypto1_get_lfsr(revstate, &key);\r
+ printf("Key: %012"llx"\n",key);\r
+ AddLogUint64(logHexFileName, "key: ", key); \r
\r
int blockShift = ((traceCurBlock & 0xFC) + 3) * 16;\r
if (isBlockEmpty((traceCurBlock & 0xFC) + 3)) memcpy(traceCard + blockShift + 6, trailerAccessBytes, 4);\r
\r
if (traceCurKey) {\r
- num_to_bytes(lfsr, 6, traceCard + blockShift + 10);\r
+ num_to_bytes(key, 6, traceCard + blockShift + 10);\r
} else {\r
- num_to_bytes(lfsr, 6, traceCard + blockShift);\r
+ num_to_bytes(key, 6, traceCard + blockShift);\r
}\r
if (wantSaveToEmlFile) saveTraceCard();\r
\r
\r
// nt = crypto1_word(traceCrypto1, nt ^ uid, 1) ^ nt;\r
\r
- /* traceCrypto1 = crypto1_create(lfsr); // key in lfsr\r
+ /* traceCrypto1 = crypto1_create(key); // key in lfsr\r
crypto1_word(traceCrypto1, nt ^ uid, 0);\r
crypto1_word(traceCrypto1, ar, 1);\r
crypto1_word(traceCrypto1, 0, 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
}\r
\r
-\r
// initialize statelists: add all possible states which would result into the rightmost 2 bits of the keystream\r
for(i = 1 << 20; i >= 0; --i) {\r
if(filter(i) == (oks & 1))\r
\r
in = (in >> 16 & 0xff) | (in << 16) | (in & 0xff00); // Byte swapping\r
\r
- recover(odd_head, odd_tail, oks,\r
- even_head, even_tail, eks, 11, statelist, in << 1, bucket);\r
-\r
+ recover(odd_head, odd_tail, oks, even_head, even_tail, eks, 11, statelist, in << 1, bucket);\r
\r
out:\r
free(odd_head);\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
* It returns a zero terminated list of possible cipher states after the\r
* tag nonce was fed in\r
*/\r
-struct Crypto1State*\r
-lfsr_common_prefix(uint32_t pfx, uint32_t rr, uint8_t ks[8], uint8_t par[8][8], uint8_t no_par)\r
+struct Crypto1State* lfsr_common_prefix(uint32_t pfx, uint32_t rr, uint8_t ks[8], uint8_t par[8][8], uint8_t no_par)\r
{\r
struct Crypto1State *statelist, *s;\r
uint32_t *odd, *even, *o, *e, top;\r
statelist = malloc((sizeof *statelist) << 21); //how large should be?\r
if(!statelist || !odd || !even)\r
{\r
- free(statelist);\r
- free(odd);\r
- free(even);\r
- return 0;\r
+ free(statelist);\r
+ free(odd);\r
+ free(even);\r
+ return 0;\r
}\r
\r
s = statelist;\r
\r
return statelist;\r
}\r
+\r
+/*\r
+struct Crypto1State* lfsr_common_prefix(uint32_t pfx, uint32_t rr, uint8_t ks[8], uint8_t par[8][8], uint8_t no_par, uint32_t nt, uint32_t uid)\r
+{\r
+ long long int amount = 0;\r
+ struct Crypto1State *statelist, *s;\r
+ uint32_t *odd, *even, *o, *e, top;\r
+\r
+ odd = lfsr_prefix_ks(ks, 1);\r
+ even = lfsr_prefix_ks(ks, 0);\r
+\r
+ s = statelist = malloc((sizeof *statelist) << 20);\r
+ if(!s || !odd || !even) {\r
+ free(odd);\r
+ free(even);\r
+ free(statelist);\r
+ return 0;\r
+ }\r
+\r
+ char filename[50] = "archivo.txt";\r
+ sprintf(filename, "logs/%x.txt", nt);\r
+ PrintAndLog("Name: %s\n", filename);\r
+ FILE *file = fopen(filename,"w+");\r
+ if ( !file ) {\r
+ s->odd = s->even = 0;\r
+ free(odd);\r
+ free(even);\r
+ PrintAndLog("Failed to create file");\r
+ return 0;\r
+ }\r
+ PrintAndLog("Creating file... ");\r
+ uint32_t xored = uid^nt;\r
+ \r
+ int lastOdd = 0;\r
+ for(o = odd; *o + 1; ++o)\r
+ for(e = even; *e + 1; ++e)\r
+ for(top = 0; top < 64; ++top) {\r
+ *o += 1 << 21;\r
+ *e += (!(top & 7) + 1) << 21;\r
+\r
+ //added by MG\r
+ if(lastOdd != statelist->odd){\r
+ // Here I create a temporal crypto1 state, \r
+ // where I load the odd and even state and work with it,\r
+ // in order not to interfere with regular mechanism, This is what I save to file\r
+ struct Crypto1State *state;\r
+ lastOdd = state->odd = statelist->odd; state->even = statelist->even;\r
+ lfsr_rollback_word(state,xored,0);\r
+ fprintf(file,"%x %x \n",state->odd,state->even);\r
+ amount++;\r
+ }\r
+ //s = check_pfx_parity(pfx, rr, par, *o, *e, s); //This is not useful at all when attacking chineese cards\r
+ s = brute_top(pfx, rr, par, *o, *e, s, no_par); \r
+ }\r
+\r
+ PrintAndLog("File created, amount %u\n",amount);\r
+ fclose(file);\r
+ s->odd = s->even = 0;\r
+ free(odd);\r
+ free(even);\r
+ return statelist;\r
+}\r
+ */\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);
*/
static int l_SendCommand(lua_State *L){
- /*
- *
- The SendCommand (native) expects the following structure:
-
- typedef struct {
- uint64_t cmd; //8 bytes
- uint64_t arg[3]; // 8*3 bytes = 24 bytes
- union {
- uint8_t asBytes[USB_CMD_DATA_SIZE]; // 1 byte * 512 = 512 bytes (OR)
- uint32_t asDwords[USB_CMD_DATA_SIZE/4]; // 4 byte * 128 = 512 bytes
- } d;
- } PACKED UsbCommand;
-
- ==> A 544 byte buffer will do.
- **/
- //Pop cmd
- size_t size;
- const char *data = luaL_checklstring(L, 1, &size);
- if(size != sizeof(UsbCommand))
- {
- printf("Got data size %d, expected %d" , (int) size,(int) sizeof(UsbCommand));
- lua_pushstring(L,"Wrong data size");
- return 1;
- }
+ /*
+ *
+ The SendCommand (native) expects the following structure:
+
+ typedef struct {
+ uint64_t cmd; //8 bytes
+ uint64_t arg[3]; // 8*3 bytes = 24 bytes
+ union {
+ uint8_t asBytes[USB_CMD_DATA_SIZE]; // 1 byte * 512 = 512 bytes (OR)
+ uint32_t asDwords[USB_CMD_DATA_SIZE/4]; // 4 byte * 128 = 512 bytes
+ } d;
+ } PACKED UsbCommand;
+
+ ==> A 544 byte buffer will do.
+ **/
+ //Pop cmd
+ size_t size;
+ const char *data = luaL_checklstring(L, 1, &size);
+ if(size != sizeof(UsbCommand))
+ {
+ printf("Got data size %d, expected %d" , (int) size,(int) sizeof(UsbCommand));
+ lua_pushstring(L,"Wrong data size");
+ return 1;
+ }
// UsbCommand c = (*data);
- SendCommand((UsbCommand* )data);
- return 0; // no return values
+ SendCommand((UsbCommand* )data);
+ return 0; // no return values
}
/**
* @brief The following params expected:
*/
static int l_WaitForResponseTimeout(lua_State *L){
- uint32_t cmd = 0;
- size_t ms_timeout = -1;
-
- //Check number of arguments
- int n = lua_gettop(L);
- if(n == 0)
- {
- //signal error by returning Nil, errorstring
- lua_pushnil(L);
- lua_pushstring(L,"You need to supply at least command to wait for");
- return 2; // two return values
- }
- if(n >= 1)
- {
- //pop cmd
- cmd = luaL_checkunsigned(L,1);
- }
- if(n >= 2)
- {
- //Did the user send a timeout ?
- //Check if the current top of stack is an integer
- ms_timeout = luaL_checkunsigned(L,2);
- //printf("Timeout set to %dms\n" , (int) ms_timeout);
- }
-
- UsbCommand response;
-
- if(WaitForResponseTimeout(cmd, &response, ms_timeout))
- {
- //Push it as a string
- lua_pushlstring(L,(const char *)&response,sizeof(UsbCommand));
-
- return 1;// return 1 to signal one return value
- }else{
- //Push a Nil instead
- lua_pushnil(L);
- return 1;// one return value
- }
+ uint32_t cmd = 0;
+ size_t ms_timeout = -1;
+
+ //Check number of arguments
+ int n = lua_gettop(L);
+ if(n == 0)
+ {
+ //signal error by returning Nil, errorstring
+ lua_pushnil(L);
+ lua_pushstring(L,"You need to supply at least command to wait for");
+ return 2; // two return values
+ }
+ if(n >= 1)
+ {
+ //pop cmd
+ cmd = luaL_checkunsigned(L,1);
+ }
+ if(n >= 2)
+ {
+ //Did the user send a timeout ?
+ //Check if the current top of stack is an integer
+ ms_timeout = luaL_checkunsigned(L,2);
+ //printf("Timeout set to %dms\n" , (int) ms_timeout);
+ }
+
+ UsbCommand response;
+
+ if(WaitForResponseTimeout(cmd, &response, ms_timeout))
+ {
+ //Push it as a string
+ lua_pushlstring(L,(const char *)&response,sizeof(UsbCommand));
+
+ return 1;// return 1 to signal one return value
+ }else{
+ //Push a Nil instead
+ lua_pushnil(L);
+ return 1;// one return value
+ }
}
static int returnToLuaWithError(lua_State *L, const char* fmt, ...)
{
- char buffer[200];
- va_list args;
- va_start(args,fmt);
- vsnprintf(buffer, sizeof(buffer), fmt,args);
- va_end(args);
-
- lua_pushnil(L);
- lua_pushstring(L,buffer);
- return 2;
+ char buffer[200];
+ va_list args;
+ va_start(args,fmt);
+ vsnprintf(buffer, sizeof(buffer), fmt,args);
+ va_end(args);
+
+ lua_pushnil(L);
+ lua_pushstring(L,buffer);
+ return 2;
}
static int l_nonce2key(lua_State *L){
- size_t size;
- const char *p_uid = luaL_checklstring(L, 1, &size);
- if(size != 4) return returnToLuaWithError(L,"Wrong size of uid, got %d bytes, expected 4", (int) size);
+ size_t size;
+ const char *p_uid = luaL_checklstring(L, 1, &size);
+ if(size != 4) return returnToLuaWithError(L,"Wrong size of uid, got %d bytes, expected 4", (int) size);
- const char *p_nt = luaL_checklstring(L, 2, &size);
- if(size != 4) return returnToLuaWithError(L,"Wrong size of nt, got %d bytes, expected 4", (int) size);
+ const char *p_nt = luaL_checklstring(L, 2, &size);
+ if(size != 4) return returnToLuaWithError(L,"Wrong size of nt, got %d bytes, expected 4", (int) size);
- const char *p_nr = luaL_checklstring(L, 3, &size);
- if(size != 4) return returnToLuaWithError(L,"Wrong size of nr, got %d bytes, expected 4", (int) size);
+ const char *p_nr = luaL_checklstring(L, 3, &size);
+ if(size != 4) return returnToLuaWithError(L,"Wrong size of nr, got %d bytes, expected 4", (int) size);
- const char *p_par_info = luaL_checklstring(L, 4, &size);
- if(size != 8) return returnToLuaWithError(L,"Wrong size of par_info, got %d bytes, expected 8", (int) size);
+ const char *p_par_info = luaL_checklstring(L, 4, &size);
+ if(size != 8) return returnToLuaWithError(L,"Wrong size of par_info, got %d bytes, expected 8", (int) size);
- const char *p_pks_info = luaL_checklstring(L, 5, &size);
- if(size != 8) return returnToLuaWithError(L,"Wrong size of ks_info, got %d bytes, expected 8", (int) size);
+ const char *p_pks_info = luaL_checklstring(L, 5, &size);
+ if(size != 8) return returnToLuaWithError(L,"Wrong size of ks_info, got %d bytes, expected 8", (int) size);
- uint32_t uid = bytes_to_num(( uint8_t *)p_uid,4);
- uint32_t nt = bytes_to_num(( uint8_t *)p_nt,4);
+ uint32_t uid = bytes_to_num(( uint8_t *)p_uid,4);
+ uint32_t nt = bytes_to_num(( uint8_t *)p_nt,4);
- uint32_t nr = bytes_to_num(( uint8_t*)p_nr,4);
- uint64_t par_info = bytes_to_num(( uint8_t *)p_par_info,8);
- uint64_t ks_info = bytes_to_num(( uint8_t *)p_pks_info,8);
+ uint32_t nr = bytes_to_num(( uint8_t*)p_nr,4);
+ uint64_t par_info = bytes_to_num(( uint8_t *)p_par_info,8);
+ uint64_t ks_info = bytes_to_num(( uint8_t *)p_pks_info,8);
- uint64_t key = 0;
+ uint64_t key = 0;
- int retval = nonce2key(uid,nt, nr, par_info,ks_info, &key);
+ int retval = nonce2key(uid,nt, nr, par_info,ks_info, &key);
- //Push the retval on the stack
- lua_pushinteger(L,retval);
+ //Push the retval on the stack
+ lua_pushinteger(L,retval);
- //Push the key onto the stack
- uint8_t dest_key[8];
- num_to_bytes(key,sizeof(dest_key),dest_key);
+ //Push the key onto the stack
+ uint8_t dest_key[8];
+ num_to_bytes(key,sizeof(dest_key),dest_key);
- //printf("Pushing to lua stack: %012"llx"\n",key);
- lua_pushlstring(L,(const char *) dest_key,sizeof(dest_key));
+ //printf("Pushing to lua stack: %012"llx"\n",key);
+ lua_pushlstring(L,(const char *) dest_key,sizeof(dest_key));
- return 2; //Two return values
+ return 2; //Two return values
}
//static int l_PrintAndLog(lua_State *L){ return CmdHF14AMfDump(luaL_checkstring(L, 1));}
static int l_clearCommandBuffer(lua_State *L){
- clearCommandBuffer();
- return 0;
+ clearCommandBuffer();
+ return 0;
}
/**
* @brief l_foobar is a dummy function to test lua-integration with
*/
static int l_foobar(lua_State *L)
{
- //Check number of arguments
- int n = lua_gettop(L);
- printf("foobar called with %d arguments" , n);
- lua_settop(L, 0);
- printf("Arguments discarded, stack now contains %d elements", lua_gettop(L));
-
- // todo: this is not used, where was it intended for?
- // UsbCommand response = {CMD_MIFARE_READBL, {1337, 1338, 1339}};
-
- printf("Now returning a uint64_t as a string");
- uint64_t x = 0xDEADBEEF;
- uint8_t destination[8];
- num_to_bytes(x,sizeof(x),destination);
- lua_pushlstring(L,(const char *)&x,sizeof(x));
- lua_pushlstring(L,(const char *)destination,sizeof(destination));
-
- return 2;
+ //Check number of arguments
+ int n = lua_gettop(L);
+ printf("foobar called with %d arguments" , n);
+ lua_settop(L, 0);
+ printf("Arguments discarded, stack now contains %d elements", lua_gettop(L));
+
+ // todo: this is not used, where was it intended for?
+ // UsbCommand response = {CMD_MIFARE_READBL, {1337, 1338, 1339}};
+
+ printf("Now returning a uint64_t as a string");
+ uint64_t x = 0xDEADBEEF;
+ uint8_t destination[8];
+ num_to_bytes(x,sizeof(x),destination);
+ lua_pushlstring(L,(const char *)&x,sizeof(x));
+ lua_pushlstring(L,(const char *)destination,sizeof(destination));
+
+ return 2;
}
*/
static int l_ukbhit(lua_State *L)
{
- lua_pushboolean(L,ukbhit() ? true : false);
- return 1;
+ lua_pushboolean(L,ukbhit() ? true : false);
+ return 1;
}
/**
* @brief Calls the command line parser to deal with the command. This enables
*/
static int l_CmdConsole(lua_State *L)
{
- CommandReceived((char *)luaL_checkstring(L, 1));
- return 0;
+ CommandReceived((char *)luaL_checkstring(L, 1));
+ return 0;
}
static int l_iso15693_crc(lua_State *L)
{
- // uint16_t Iso15693Crc(uint8_t *v, int n);
- size_t size;
- const char *v = luaL_checklstring(L, 1, &size);
- uint16_t retval = Iso15693Crc((uint8_t *) v, size);
- lua_pushinteger(L, (int) retval);
- return 1;
+ // uint16_t Iso15693Crc(uint8_t *v, int n);
+ size_t size;
+ const char *v = luaL_checklstring(L, 1, &size);
+ uint16_t retval = Iso15693Crc((uint8_t *) v, size);
+ lua_pushinteger(L, (int) retval);
+ return 1;
}
/*
{
//Check number of arguments
int i;
- size_t size;
- const char *p_key = luaL_checklstring(L, 1, &size);
- if(size != 32) return returnToLuaWithError(L,"Wrong size of key, got %d bytes, expected 32", (int) size);
+ size_t size;
+ const char *p_key = luaL_checklstring(L, 1, &size);
+ if(size != 32) return returnToLuaWithError(L,"Wrong size of key, got %d bytes, expected 32", (int) size);
- const char *p_encTxt = luaL_checklstring(L, 2, &size);
+ const char *p_encTxt = luaL_checklstring(L, 2, &size);
unsigned char indata[16] = {0x00};
unsigned char outdata[16] = {0x00};
- unsigned char aes_key[16] = {0x00};
+ unsigned char aes_key[16] = {0x00};
unsigned char iv[16] = {0x00};
// convert key to bytearray and convert input to bytearray
sscanf(&p_key[i], "%02x", (unsigned int *)&aes_key[i / 2]);
}
- aes_context ctx;
- aes_init(&ctx);
+ aes_context ctx;
+ aes_init(&ctx);
+ //aes_setkey_enc(&ctx, (const unsigned char *)aes_key, 128);
aes_setkey_dec(&ctx, aes_key, 128);
- aes_crypt_cbc(&ctx,AES_DECRYPT,sizeof(indata), iv, indata,outdata );
- //Push decrypted array as a string
+ aes_crypt_cbc(&ctx, AES_DECRYPT, sizeof(indata), iv, indata, outdata );
+ //Push decrypted array as a string
lua_pushlstring(L,(const char *)&outdata, sizeof(outdata));
return 1;// return 1 to signal one return value
}
{
//Check number of arguments
int i;
- size_t size;
- const char *p_key = luaL_checklstring(L, 1, &size);
- if(size != 32) return returnToLuaWithError(L,"Wrong size of key, got %d bytes, expected 32", (int) size);
-
- const char *p_txt = luaL_checklstring(L, 2, &size);
+ size_t size;
+ const char *p_key = luaL_checklstring(L, 1, &size);
+ if(size != 32) return returnToLuaWithError(L,"Wrong size of key, got %d bytes, expected 32", (int) size);
+ const char *p_txt = luaL_checklstring(L, 2, &size);
+
unsigned char indata[16] = {0x00};
unsigned char outdata[16] = {0x00};
- unsigned char aes_key[16] = {0x00};
+ unsigned char aes_key[16] = {0x00};
unsigned char iv[16] = {0x00};
for (i = 0; i < 32; i += 2) {
sscanf(&p_key[i], "%02x", (unsigned int *)&aes_key[i / 2]);
}
- aes_context ctx;
- aes_init(&ctx);
+ aes_context ctx;
+ aes_init(&ctx);
aes_setkey_enc(&ctx, aes_key, 128);
aes_crypt_cbc(&ctx, AES_ENCRYPT, sizeof(indata), iv, indata, outdata );
//Push encrypted array as a string
const char *p_str = luaL_checklstring(L, 1, &size);
uint16_t retval = crc16_ccitt( (uint8_t*) p_str, size);
- lua_pushinteger(L, (int) retval);
- return 1;
+ lua_pushinteger(L, (int) retval);
+ return 1;
}
static int l_crc64(lua_State *L)
*/
int setLuaPath( lua_State* L, const char* path )
{
- lua_getglobal( L, "package" );
- lua_getfield( L, -1, "path" ); // get field "path" from table at top of stack (-1)
- const char* cur_path = lua_tostring( L, -1 ); // grab path string from top of stack
- int requiredLength = strlen(cur_path)+ strlen(path)+10; //A few bytes too many, whatever we can afford it
- char * buf = malloc(requiredLength);
- snprintf(buf, requiredLength, "%s;%s", cur_path, path);
- lua_pop( L, 1 ); // get rid of the string on the stack we just pushed on line 5
- lua_pushstring( L, buf ); // push the new one
- lua_setfield( L, -2, "path" ); // set the field "path" in table at -2 with value at top of stack
- lua_pop( L, 1 ); // get rid of package table from top of stack
+ lua_getglobal( L, "package" );
+ lua_getfield( L, -1, "path" ); // get field "path" from table at top of stack (-1)
+ const char* cur_path = lua_tostring( L, -1 ); // grab path string from top of stack
+ int requiredLength = strlen(cur_path)+ strlen(path)+10; //A few bytes too many, whatever we can afford it
+ char * buf = malloc(requiredLength);
+ snprintf(buf, requiredLength, "%s;%s", cur_path, path);
+ lua_pop( L, 1 ); // get rid of the string on the stack we just pushed on line 5
+ lua_pushstring( L, buf ); // push the new one
+ lua_setfield( L, -2, "path" ); // set the field "path" in table at -2 with value at top of stack
+ lua_pop( L, 1 ); // get rid of package table from top of stack
free(buf);
return 0; // all done!
}
int set_pm3_libraries(lua_State *L)
{
- static const luaL_Reg libs[] = {
- {"SendCommand", l_SendCommand},
- {"WaitForResponseTimeout", l_WaitForResponseTimeout},
- {"nonce2key", l_nonce2key},
- //{"PrintAndLog", l_PrintAndLog},
- {"foobar", l_foobar},
- {"ukbhit", l_ukbhit},
- {"clearCommandBuffer", l_clearCommandBuffer},
+ static const luaL_Reg libs[] = {
+ {"SendCommand", l_SendCommand},
+ {"WaitForResponseTimeout", l_WaitForResponseTimeout},
+ {"nonce2key", l_nonce2key},
+ //{"PrintAndLog", l_PrintAndLog},
+ {"foobar", l_foobar},
+ {"ukbhit", l_ukbhit},
+ {"clearCommandBuffer", l_clearCommandBuffer},
{"console", l_CmdConsole},
{"iso15693_crc", l_iso15693_crc},
{"aes128_decrypt", l_aes128decrypt},
{"aes128_encrypt", l_aes128encrypt},
{"crc16", l_crc16},
{"crc64", l_crc64},
- {NULL, NULL}
- };
-
- lua_pushglobaltable(L);
- // Core library is in this table. Contains '
- //this is 'pm3' table
- lua_newtable(L);
-
- //Put the function into the hash table.
- for (int i = 0; libs[i].name; i++) {
- lua_pushcfunction(L, libs[i].func);
- lua_setfield(L, -2, libs[i].name);//set the name, pop stack
- }
- //Name of 'core'
- lua_setfield(L, -2, "core");
-
- //-- remove the global environment table from the stack
- lua_pop(L, 1);
-
- //-- Last but not least, add to the LUA_PATH (package.path in lua)
- // so we can load libraries from the ./lualib/ - directory
- setLuaPath(L,"./lualibs/?.lua");
-
- return 1;
+ {NULL, NULL}
+ };
+
+ lua_pushglobaltable(L);
+ // Core library is in this table. Contains '
+ //this is 'pm3' table
+ lua_newtable(L);
+
+ //Put the function into the hash table.
+ for (int i = 0; libs[i].name; i++) {
+ lua_pushcfunction(L, libs[i].func);
+ lua_setfield(L, -2, libs[i].name);//set the name, pop stack
+ }
+ //Name of 'core'
+ lua_setfield(L, -2, "core");
+
+ //-- remove the global environment table from the stack
+ lua_pop(L, 1);
+
+ //-- Last but not least, add to the LUA_PATH (package.path in lua)
+ // so we can load libraries from the ./lualib/ - directory
+ setLuaPath(L,"./lualibs/?.lua");
+
+ return 1;
}
+++ /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
#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
printf("\n");
}
-char * sprint_hex(const uint8_t * data, const size_t len) {
+char *sprint_hex(const uint8_t *data, const size_t len) {
int maxLen = ( len > 1024/3) ? 1024/3 : len;
static char buf[1024];
size_t i;
for (i=0; i < maxLen; ++i, tmp += 3)
- sprintf(tmp, "%02x ", data[i]);
+ sprintf(tmp, "%02X ", data[i]);
return buf;
}
INCLUDES = ../include/proxmark3.h ../include/at91sam7s512.h ../include/config_gpio.h ../include/usb_cmd.h $(APP_INCLUDES)
-CFLAGS = -c $(INCLUDE) -Wall -Werror -pedantic -std=c99 $(APP_CFLAGS) -Os
+# compile hint: -flto to minimise size.
+CFLAGS = -c $(INCLUDE) -Wall -Werror -fdata-sections -ffunction-sections -pedantic -std=c99 -Os $(APP_CFLAGS)
+#CFLAGS = -c $(INCLUDE) -Wall -Werror -pedantic -std=c99 -Os $(APP_CFLAGS)
LDFLAGS = -nostartfiles -nodefaultlibs -Wl,-gc-sections -n
LIBS = -lgcc
--- /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;
#define ISO14443A_CMD_WUPA 0x52
#define ISO14443A_CMD_ANTICOLL_OR_SELECT 0x93
#define ISO14443A_CMD_ANTICOLL_OR_SELECT_2 0x95
-#define ISO14443A_CMD_WRITEBLOCK 0xA0 // or 0xA2 ?
+#define ISO14443A_CMD_WRITEBLOCK 0xA0
#define ISO14443A_CMD_HALT 0x50
#define ISO14443A_CMD_RATS 0xE0
#define MIFARE_ULC_AUTH_1 0x1A
#define MIFARE_ULC_AUTH_2 0xAF
-#define MIFARE_ULEV1_AUTH 0x1B
-#define MIFARE_ULEV1_VERSION 0x60
-#define MIFARE_ULEV1_FASTREAD 0x3A
-//#define MIFARE_ULEV1_WRITE 0xA2
-//#define MIFARE_ULEV1_COMP_WRITE 0xA0
-#define MIFARE_ULEV1_READ_CNT 0x39
-#define MIFARE_ULEV1_INCR_CNT 0xA5
-#define MIFARE_ULEV1_READSIG 0x3C
-#define MIFARE_ULEV1_CHECKTEAR 0x3E
-#define MIFARE_ULEV1_VCSL 0x4B
+#define MIFARE_ULEV1_AUTH 0x1B
+#define MIFARE_ULEV1_VERSION 0x60
+#define MIFARE_ULEV1_FASTREAD 0x3A
+#define MIFARE_ULEV1_READ_CNT 0x39
+#define MIFARE_ULEV1_INCR_CNT 0xA5
+#define MIFARE_ULEV1_READSIG 0x3C
+#define MIFARE_ULEV1_CHECKTEAR 0x3E
+#define MIFARE_ULEV1_VCSL 0x4B
/**
06 00 = INITIATE
#define ISO15693_READ_MULTI_SECSTATUS 0x2C
+// Topaz command set:
+#define TOPAZ_REQA 0x26 // Request
+#define TOPAZ_WUPA 0x52 // WakeUp
+#define TOPAZ_RID 0x78 // Read ID
+#define TOPAZ_RALL 0x00 // Read All (all bytes)
+#define TOPAZ_READ 0x01 // Read (a single byte)
+#define TOPAZ_WRITE_E 0x53 // Write-with-erase (a single byte)
+#define TOPAZ_WRITE_NE 0x1a // Write-no-erase (a single byte)
+// additional commands for Dynamic Memory Model
+#define TOPAZ_RSEG 0x10 // Read segment
+#define TOPAZ_READ8 0x02 // Read (eight bytes)
+#define TOPAZ_WRITE_E8 0x54 // Write-with-erase (eight bytes)
+#define TOPAZ_WRITE_NE8 0x1B // Write-no-erase (eight bytes)
+
+
#define ISO_14443A 0
#define ICLASS 1
#define ISO_14443B 2
+#define TOPAZ 3
//-- Picopass fuses
#define FUSE_FPERS 0x80
--- /dev/null
+cp armsrc/obj/*.elf /z
+cp armsrc/obj/*.s19 /z
+cp bootrom/obj/*.elf /z
+cp bootrom/obj/*.s19 /z
#ifndef _MIFARE_H_
#define _MIFARE_H_
-#include "common.h"
+#include "../include/common.h"
//-----------------------------------------------------------------------------
// ISO 14443A
} __attribute__((__packed__)) iso14a_card_select_t;
typedef enum ISO14A_COMMAND {
- ISO14A_CONNECT = 1,
- ISO14A_NO_DISCONNECT = 2,
- ISO14A_APDU = 4,
- ISO14A_RAW = 8,
- ISO14A_REQUEST_TRIGGER = 0x10,
- ISO14A_APPEND_CRC = 0x20,
- ISO14A_SET_TIMEOUT = 0x40,
- ISO14A_NO_SELECT = 0x80
+ ISO14A_CONNECT = (1 << 0),
+ ISO14A_NO_DISCONNECT = (1 << 1),
+ ISO14A_APDU = (1 << 2),
+ ISO14A_RAW = (1 << 3),
+ ISO14A_REQUEST_TRIGGER = (1 << 4),
+ ISO14A_APPEND_CRC = (1 << 5),
+ ISO14A_SET_TIMEOUT = (1 << 6),
+ ISO14A_NO_SELECT = (1 << 7),
+ ISO14A_TOPAZMODE = (1 << 8)
} iso14a_command_t;
#endif // _MIFARE_H_
#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_ICLASS_ISO14443A_WRITE 0x0397
+#define CMD_ICLASS_ISO14443A_WRITE 0x0397
#define CMD_ICLASS_EML_MEMSET 0x0398
// For measurements of the antenna tuning
#define CMD_MIFARE_READSC 0x0621
#define CMD_MIFAREU_READCARD 0x0721
#define CMD_MIFARE_WRITEBL 0x0622
-#define CMD_MIFAREU_WRITEBL 0x0722
-#define CMD_MIFAREU_WRITEBL_COMPAT 0x0723
+#define CMD_MIFAREU_WRITEBL 0x0722
+#define CMD_MIFAREU_WRITEBL_COMPAT 0x0723
#define CMD_MIFARE_CHKKEYS 0x0623
#define CMD_MIFARE_DESFIRE_INFO 0x072d
#define CMD_MIFARE_DESFIRE 0x072e
+#define CMD_MIFARE_COLLECT_NONCES 0x072f
+
#define CMD_UNKNOWN 0xFFFF
//Iclass reader flags
-#define FLAG_ICLASS_READER_ONLY_ONCE 0x01
-#define FLAG_ICLASS_READER_CC 0x02
-#define FLAG_ICLASS_READER_CSN 0x04
-#define FLAG_ICLASS_READER_CONF 0x08
-#define FLAG_ICLASS_READER_AA 0x10
+#define FLAG_ICLASS_READER_ONLY_ONCE 0x01
+#define FLAG_ICLASS_READER_CC 0x02
+#define FLAG_ICLASS_READER_CSN 0x04
+#define FLAG_ICLASS_READER_CONF 0x08
+#define FLAG_ICLASS_READER_AA 0x10
#define FLAG_ICLASS_READER_ONE_TRY 0x20
crypto1_word(t, uid ^ nt, 0);
crypto1_word(t, nr1_enc, 1);
if (ar1_enc == (crypto1_word(t, 0, 0) ^ prng_successor(nt, 64))) {
- printf("\nFound Key: [%012"llx"]\n\n",key);
- break;
- }
+ printf("\nFound Key: [%012"llx"]\n\n",key);
+ break;}
}
free(s);
my $clean = 2;
my @compiletime = gmtime();
-my $fullgitinfo = $gitbranch . '/' . $gitversion;
+my $fullgitinfo = 'iceman' . $gitbranch . '/' . $gitversion;
$fullgitinfo =~ s/(\s)//g;