TEST of creating branch simular to PM3master.

This commit is contained in:
iceman1001 2015-01-05 16:31:19 +01:00
commit 052bbe08d0
133 changed files with 4428 additions and 14173 deletions

View file

@ -1,68 +1,87 @@
The iceman fork.
NOTICE:
(2014-03-26)
This is now the official Proxmark repository!
The official Proxmark repository is found here: https://github.com/Proxmark/proxmark3
INTRODUCTION:
The proxmark3 is a powerful general purpose RFID tool, the size of a deck
of cards, designed to snoop, listen and emulate everything from
Low Frequency (125kHz) to High Frequency (13.56MHz) tags.
NEWS:
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.
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
RESOURCES:
* 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.
* This repository!
https://github.com/Proxmark/proxmark3
Give me a hint, and I'll see if I can't merge in the stuff you have.
* The Wiki
https://github.com/Proxmark/proxmark3/wiki
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.
* The GitHub page
http://proxmark.github.io/proxmark3/
PM3 GUI:
I do tend to rename and move stuff around, the official PM3-GUI from Gaucho will not work so well. *sorry*
* The Forum
http://www.proxmark.org/forum
* The IRC chanel
irc.freenode.org #proxmark3
-or-
http://webchat.freenode.net/?channels=#proxmark3
DEVELOPMENT:
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.
The tools required to build or run the project will vary depending on
your operating system. Please refer to the Wiki for details.
Common errors linux/macOS finds
Error:
* loclass/fileutils.c:15:2: warning: implicit declaration of function _stat [-Wimplicit-function-declaration]
Solution:
* Remove the "unscore" sign. In linux you use without underscore, in windows you need a underscore.
* https://github.com/Proxmark/proxmark3/wiki
Error:
* \client\makefile the parameter -lgdi32
Solution:
* Remove parameter.
OBTAINING HARDWARE:
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
The Proxmark 3 is available for purcahse (assembled and tested) from the
following locations:
TO
* http://proxmark3.com/
* http://www.xfpga.com/
CXXFLAGS = -I$(QTDIR)/include -I$(QTDIR)/include/QtCore -I$(QTDIR)/include/QtGui
QTLDLIBS = -L$(QTDIR)/lib -lQtCore4 -lQtGui4
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.
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.
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
January 2015, Sweden
iceman at host iuse.se
May 2007, Cambridge MA

View file

@ -6,7 +6,7 @@
// LCD code
//-----------------------------------------------------------------------------
#include "../include/proxmark3.h"
#include "proxmark3.h"
#include "apps.h"
#include "LCD.h"
#include "fonts.h"

View file

@ -10,7 +10,7 @@ APP_INCLUDES = apps.h
#remove one of the following defines and comment out the relevant line
#in the next section to remove that particular feature from compilation
APP_CFLAGS = -DWITH_LF -DWITH_ISO15693 -DWITH_ISO14443a -DWITH_ISO14443b -DWITH_ICLASS -DWITH_LEGICRF -DWITH_HITAG -DWITH_CRC -fno-strict-aliasing
APP_CFLAGS = -DWITH_LF -DWITH_ISO15693 -DWITH_ISO14443a -DWITH_ISO14443b -DWITH_ICLASS -DWITH_LEGICRF -DWITH_HITAG
#-DWITH_LCD
#SRC_LCD = fonts.c LCD.c
@ -18,8 +18,7 @@ SRC_LF = lfops.c hitag2.c
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 desfire_key.c desfire_crypto.c mifaredesfire.c
SRC_CRC = iso14443crc.c crc.c crc16.c crc32.c
SRC_CRAPTO1 = crapto1.c crypto1.c
THUMBSRC = start.c \
$(SRC_LCD) \
@ -35,14 +34,15 @@ THUMBSRC = start.c \
# These are to be compiled in ARM mode
ARMSRC = fpgaloader.c \
legicrf.c \
iso14443crc.c \
crc16.c \
lfdemod.c \
$(SRC_ISO14443a) \
$(SRC_ISO14443b) \
$(SRC_CRAPTO1) \
$(SRC_CRC) \
legic_prng.c \
iclass.c
iclass.c \
crc.c
# stdint.h provided locally until GCC 4.5 becomes C99 compliant
APP_CFLAGS += -I.

File diff suppressed because it is too large Load diff

View file

@ -1,30 +0,0 @@
/*
* AES Cryptographic Algorithm Header File. Include this header file in
* your source which uses these given APIs. (This source is kept under
* public domain)
*/
// AES context structure
typedef struct {
unsigned int Ek[60];
unsigned int Dk[60];
unsigned int Iv[4];
unsigned char Nr;
unsigned char Mode;
} AesCtx;
// key length in bytes
#define KEY128 16
#define KEY192 24
#define KEY256 32
// block size in bytes
#define BLOCKSZ 16
// mode
#define EBC 0
#define CBC 1
// AES API function prototype
int AesCtxIni(AesCtx *pCtx, unsigned char *pIV, unsigned char *pKey, unsigned int KeyLen, unsigned char Mode);
int AesEncrypt(AesCtx *pCtx, unsigned char *pData, unsigned char *pCipher, unsigned int DataLen);
int AesDecrypt(AesCtx *pCtx, unsigned char *pCipher, unsigned char *pData, unsigned int CipherLen);

View file

@ -10,20 +10,19 @@
// executes.
//-----------------------------------------------------------------------------
#include "../common/usb_cdc.h"
#include "../common/cmd.h"
#include "usb_cdc.h"
#include "cmd.h"
#include "../include/proxmark3.h"
#include "proxmark3.h"
#include "apps.h"
#include "util.h"
#include "printf.h"
#include "string.h"
#include <stdarg.h>
#include "legicrf.h"
#include "../include/hitag2.h"
#include <hitag2.h>
#ifdef WITH_LCD
#include "LCD.h"
@ -669,8 +668,9 @@ void UsbPacketReceived(uint8_t *packet, int len)
WriteTItag(c->arg[0],c->arg[1],c->arg[2]);
break;
case CMD_SIMULATE_TAG_125K:
SimulateTagLowFrequency(c->arg[0], c->arg[1], 0);
//SimulateTagLowFrequencyA(c->arg[0], c->arg[1]);
LED_A_ON();
SimulateTagLowFrequency(c->arg[0], c->arg[1], 1);
LED_A_OFF();
break;
case CMD_LF_SIMULATE_BIDIR:
SimulateTagLowFrequencyBidir(c->arg[0], c->arg[1]);
@ -792,10 +792,6 @@ void UsbPacketReceived(uint8_t *packet, int len)
EPA_PACE_Collect_Nonce(c);
break;
// case CMD_EPA_:
// EpaFoo(c);
// break;
case CMD_READER_MIFARE:
ReaderMifare(c->arg[0]);
break;
@ -805,17 +801,8 @@ void UsbPacketReceived(uint8_t *packet, int len)
case CMD_MIFAREU_READBL:
MifareUReadBlock(c->arg[0],c->d.asBytes);
break;
case CMD_MIFAREUC_AUTH1:
MifareUC_Auth1(c->arg[0],c->d.asBytes);
break;
case CMD_MIFAREUC_AUTH2:
MifareUC_Auth2(c->arg[0],c->d.asBytes);
break;
case CMD_MIFAREU_READCARD:
MifareUReadCard(c->arg[0],c->arg[1],c->d.asBytes);
break;
case CMD_MIFAREUC_READCARD:
MifareUReadCard(c->arg[0],c->arg[1],c->d.asBytes);
MifareUReadCard(c->arg[0],c->d.asBytes);
break;
case CMD_MIFARE_READSC:
MifareReadSector(c->arg[0], c->arg[1], c->arg[2], c->d.asBytes);
@ -871,28 +858,6 @@ void UsbPacketReceived(uint8_t *packet, int len)
case CMD_MIFARE_SNIFFER:
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;
#endif
#ifdef WITH_ICLASS

View file

@ -14,21 +14,9 @@
#include <stdint.h>
#include <stddef.h>
#include <stdlib.h>
#include <sys/types.h>
#include <string.h>
#include <strings.h>
#include "../include/common.h"
#include "../include/hitag2.h"
#include "../include/mifare.h"
//#include <openssl/des.h>
//#include <openssl/aes.h>
//#include "des.h"
//#include "aes.h"
#include "../common/desfire.h"
#include "../common/crc32.h"
#include "common.h"
#include "hitag2.h"
#include "mifare.h"
// The large multi-purpose buffer, typically used to hold A/D samples,
// maybe processed in some way.
@ -76,10 +64,7 @@ void ToSendReset(void);
void ListenReaderField(int limit);
void AcquireRawAdcSamples125k(int at134khz);
void SnoopLFRawAdcSamples(int divisor, int trigger_threshold);
void DoAcquisition125k_internal(int trigger_threshold, bool silent);
void DoAcquisition125k_threshold(int trigger_threshold);
void DoAcquisition125k();
void DoAcquisition125k(int trigger_threshold);
extern int ToSendMax;
extern uint8_t ToSend[];
extern uint32_t BigBuf[];
@ -144,10 +129,8 @@ void ReadTItag(void);
void WriteTItag(uint32_t idhi, uint32_t idlo, uint16_t crc);
void AcquireTiType(void);
void AcquireRawBitsTI(void);
void SimulateTagLowFrequency( uint16_t period, uint32_t gap, uint8_t ledcontrol);
void SimulateTagLowFrequencyA(int period, int gap);
void CmdHIDsimTAG(int hi, int lo, uint8_t ledcontrol);
void SimulateTagLowFrequency(int period, int gap, int ledcontrol);
void CmdHIDsimTAG(int hi, int lo, int ledcontrol);
void CmdHIDdemodFSK(int findone, int *high, int *low, int ledcontrol);
void CmdEM410xdemod(int findone, int *high, int *low, int ledcontrol);
void CmdIOdemodFSK(int findone, int *high, int *low, int ledcontrol);
@ -160,7 +143,6 @@ void CopyIndala224toT55x7(int uid1, int uid2, int uid3, int uid4, int uid5, int
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);
@ -195,9 +177,7 @@ void ReaderMifare(bool first_try);
int32_t dist_nt(uint32_t nt1, uint32_t nt2);
void MifareReadBlock(uint8_t arg0, uint8_t arg1, uint8_t arg2, uint8_t *data);
void MifareUReadBlock(uint8_t arg0,uint8_t *datain);
void MifareUC_Auth1(uint8_t arg0, uint8_t *datain);
void MifareUC_Auth2(uint32_t arg0, uint8_t *datain);
void MifareUReadCard(uint8_t arg0, int Pages, uint8_t *datain);
void MifareUReadCard(uint8_t arg0,uint8_t *datain);
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);
@ -214,36 +194,6 @@ void MifareCSetBlock(uint32_t arg0, uint32_t arg1, uint32_t arg2, uint8_t *datai
void MifareCGetBlock(uint32_t arg0, uint32_t arg1, uint32_t arg2, uint8_t *datain);
void MifareCIdent(); // is "magic chinese" card?
//desfire
void Mifare_DES_Auth1(uint8_t arg0,uint8_t *datain);
void Mifare_DES_Auth2(uint32_t arg0, uint8_t *datain);
// mifaredesfire.h
bool InitDesfireCard();
void MifareSendCommand(uint8_t arg0,uint8_t arg1, uint8_t *datain);
void MifareDesfireGetInformation();
void MifareDES_Auth1(uint8_t arg0,uint8_t arg1,uint8_t arg2, uint8_t *datain);
void ReaderMifareDES(uint32_t param, uint32_t param2, uint8_t * datain);
int DesfireAPDU(uint8_t *cmd, size_t cmd_len, uint8_t *dataout);
size_t CreateAPDU( uint8_t *datain, size_t len, uint8_t *dataout);
void OnSuccess();
void OnError();
// 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
void RecordRawAdcSamplesIso15693(void);
void AcquireRawAdcSamplesIso15693(void);

View file

@ -44,12 +44,12 @@ static void quicksort(uint32_t* const start, uint32_t* const stop)
else if(*rit > *start)
--rit;
else
*it ^= ( (*it ^= *rit ), *rit ^= *it);
*it ^= (*it ^= *rit, *rit ^= *it);
if(*rit >= *start)
--rit;
if(rit != start)
*rit ^= ( (*rit ^= *start), *start ^= *rit);
*rit ^= (*rit ^= *start, *start ^= *rit);
quicksort(start, rit - 1);
quicksort(rit + 1, stop);

View file

@ -1,383 +0,0 @@
/* des.c */
/*
This file is part of the ARM-Crypto-Lib.
Copyright (C) 2006-2010 Daniel Otte (daniel.otte@rub.de)
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 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 General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
/**
* \file des.c
* \author Daniel Otte
* \email daniel.otte@rub.de
* \date 2007-06-16
* \brief DES and EDE-DES implementation
* \license GPLv3 or later
*
*/
#include <stdint.h>
#include <string.h>
const uint8_t sbox[256] = {
/* S-box 1 */
0xE4, 0xD1, 0x2F, 0xB8, 0x3A, 0x6C, 0x59, 0x07,
0x0F, 0x74, 0xE2, 0xD1, 0xA6, 0xCB, 0x95, 0x38,
0x41, 0xE8, 0xD6, 0x2B, 0xFC, 0x97, 0x3A, 0x50,
0xFC, 0x82, 0x49, 0x17, 0x5B, 0x3E, 0xA0, 0x6D,
/* S-box 2 */
0xF1, 0x8E, 0x6B, 0x34, 0x97, 0x2D, 0xC0, 0x5A,
0x3D, 0x47, 0xF2, 0x8E, 0xC0, 0x1A, 0x69, 0xB5,
0x0E, 0x7B, 0xA4, 0xD1, 0x58, 0xC6, 0x93, 0x2F,
0xD8, 0xA1, 0x3F, 0x42, 0xB6, 0x7C, 0x05, 0xE9,
/* S-box 3 */
0xA0, 0x9E, 0x63, 0xF5, 0x1D, 0xC7, 0xB4, 0x28,
0xD7, 0x09, 0x34, 0x6A, 0x28, 0x5E, 0xCB, 0xF1,
0xD6, 0x49, 0x8F, 0x30, 0xB1, 0x2C, 0x5A, 0xE7,
0x1A, 0xD0, 0x69, 0x87, 0x4F, 0xE3, 0xB5, 0x2C,
/* S-box 4 */
0x7D, 0xE3, 0x06, 0x9A, 0x12, 0x85, 0xBC, 0x4F,
0xD8, 0xB5, 0x6F, 0x03, 0x47, 0x2C, 0x1A, 0xE9,
0xA6, 0x90, 0xCB, 0x7D, 0xF1, 0x3E, 0x52, 0x84,
0x3F, 0x06, 0xA1, 0xD8, 0x94, 0x5B, 0xC7, 0x2E,
/* S-box 5 */
0x2C, 0x41, 0x7A, 0xB6, 0x85, 0x3F, 0xD0, 0xE9,
0xEB, 0x2C, 0x47, 0xD1, 0x50, 0xFA, 0x39, 0x86,
0x42, 0x1B, 0xAD, 0x78, 0xF9, 0xC5, 0x63, 0x0E,
0xB8, 0xC7, 0x1E, 0x2D, 0x6F, 0x09, 0xA4, 0x53,
/* S-box 6 */
0xC1, 0xAF, 0x92, 0x68, 0x0D, 0x34, 0xE7, 0x5B,
0xAF, 0x42, 0x7C, 0x95, 0x61, 0xDE, 0x0B, 0x38,
0x9E, 0xF5, 0x28, 0xC3, 0x70, 0x4A, 0x1D, 0xB6,
0x43, 0x2C, 0x95, 0xFA, 0xBE, 0x17, 0x60, 0x8D,
/* S-box 7 */
0x4B, 0x2E, 0xF0, 0x8D, 0x3C, 0x97, 0x5A, 0x61,
0xD0, 0xB7, 0x49, 0x1A, 0xE3, 0x5C, 0x2F, 0x86,
0x14, 0xBD, 0xC3, 0x7E, 0xAF, 0x68, 0x05, 0x92,
0x6B, 0xD8, 0x14, 0xA7, 0x95, 0x0F, 0xE2, 0x3C,
/* S-box 8 */
0xD2, 0x84, 0x6F, 0xB1, 0xA9, 0x3E, 0x50, 0xC7,
0x1F, 0xD8, 0xA3, 0x74, 0xC5, 0x6B, 0x0E, 0x92,
0x7B, 0x41, 0x9C, 0xE2, 0x06, 0xAD, 0xF3, 0x58,
0x21, 0xE7, 0x4A, 0x8D, 0xFC, 0x90, 0x35, 0x6B
};
const uint8_t e_permtab[] ={
4, 6, /* 4 bytes in 6 bytes out*/
32, 1, 2, 3, 4, 5,
4, 5, 6, 7, 8, 9,
8, 9, 10, 11, 12, 13,
12, 13, 14, 15, 16, 17,
16, 17, 18, 19, 20, 21,
20, 21, 22, 23, 24, 25,
24, 25, 26, 27, 28, 29,
28, 29, 30, 31, 32, 1
};
const uint8_t p_permtab[] ={
4, 4, /* 32 bit -> 32 bit */
16, 7, 20, 21,
29, 12, 28, 17,
1, 15, 23, 26,
5, 18, 31, 10,
2, 8, 24, 14,
32, 27, 3, 9,
19, 13, 30, 6,
22, 11, 4, 25
};
const uint8_t ip_permtab[] ={
8, 8, /* 64 bit -> 64 bit */
58, 50, 42, 34, 26, 18, 10, 2,
60, 52, 44, 36, 28, 20, 12, 4,
62, 54, 46, 38, 30, 22, 14, 6,
64, 56, 48, 40, 32, 24, 16, 8,
57, 49, 41, 33, 25, 17, 9, 1,
59, 51, 43, 35, 27, 19, 11, 3,
61, 53, 45, 37, 29, 21, 13, 5,
63, 55, 47, 39, 31, 23, 15, 7
};
const uint8_t inv_ip_permtab[] ={
8, 8, /* 64 bit -> 64 bit */
40, 8, 48, 16, 56, 24, 64, 32,
39, 7, 47, 15, 55, 23, 63, 31,
38, 6, 46, 14, 54, 22, 62, 30,
37, 5, 45, 13, 53, 21, 61, 29,
36, 4, 44, 12, 52, 20, 60, 28,
35, 3, 43, 11, 51, 19, 59, 27,
34, 2, 42, 10, 50, 18, 58, 26,
33, 1, 41, 9, 49, 17, 57, 25
};
const uint8_t pc1_permtab[] ={
8, 7, /* 64 bit -> 56 bit*/
57, 49, 41, 33, 25, 17, 9,
1, 58, 50, 42, 34, 26, 18,
10, 2, 59, 51, 43, 35, 27,
19, 11, 3, 60, 52, 44, 36,
63, 55, 47, 39, 31, 23, 15,
7, 62, 54, 46, 38, 30, 22,
14, 6, 61, 53, 45, 37, 29,
21, 13, 5, 28, 20, 12, 4
};
const uint8_t pc2_permtab[] ={
7, 6, /* 56 bit -> 48 bit */
14, 17, 11, 24, 1, 5,
3, 28, 15, 6, 21, 10,
23, 19, 12, 4, 26, 8,
16, 7, 27, 20, 13, 2,
41, 52, 31, 37, 47, 55,
30, 40, 51, 45, 33, 48,
44, 49, 39, 56, 34, 53,
46, 42, 50, 36, 29, 32
};
const uint8_t splitin6bitword_permtab[] = {
8, 8, /* 64 bit -> 64 bit */
64, 64, 1, 6, 2, 3, 4, 5,
64, 64, 7, 12, 8, 9, 10, 11,
64, 64, 13, 18, 14, 15, 16, 17,
64, 64, 19, 24, 20, 21, 22, 23,
64, 64, 25, 30, 26, 27, 28, 29,
64, 64, 31, 36, 32, 33, 34, 35,
64, 64, 37, 42, 38, 39, 40, 41,
64, 64, 43, 48, 44, 45, 46, 47
};
const uint8_t shiftkey_permtab[] = {
7, 7, /* 56 bit -> 56 bit */
2, 3, 4, 5, 6, 7, 8, 9,
10, 11, 12, 13, 14, 15, 16, 17,
18, 19, 20, 21, 22, 23, 24, 25,
26, 27, 28, 1,
30, 31, 32, 33, 34, 35, 36, 37,
38, 39, 40, 41, 42, 43, 44, 45,
46, 47, 48, 49, 50, 51, 52, 53,
54, 55, 56, 29
};
const uint8_t shiftkeyinv_permtab[] = {
7, 7,
28, 1, 2, 3, 4, 5, 6, 7,
8, 9, 10, 11, 12, 13, 14, 15,
16, 17, 18, 19, 20, 21, 22, 23,
24, 25, 26, 27,
56, 29, 30, 31, 32, 33, 34, 35,
36, 37, 38, 39, 40, 41, 42, 43,
44, 45, 46, 47, 48, 49, 50, 51,
52, 53, 54, 55
};
/*
1 0
1 0
2 1
2 1
2 1
2 1
2 1
2 1
----
1 0
2 1
2 1
2 1
2 1
2 1
2 1
1 0
*/
#define ROTTABLE 0x7EFC
#define ROTTABLE_INV 0x3F7E
/******************************************************************************/
void permute(const uint8_t *ptable, const uint8_t *in, uint8_t *out){
uint8_t ob; /* in-bytes and out-bytes */
uint8_t byte, bit; /* counter for bit and byte */
ob = ptable[1];
ptable = &(ptable[2]);
for(byte=0; byte<ob; ++byte){
uint8_t x,t=0;
for(bit=0; bit<8; ++bit){
x=*ptable++ -1 ;
t<<=1;
if((in[x/8]) & (0x80>>(x%8)) ){
t|=0x01;
}
}
out[byte]=t;
}
}
/******************************************************************************/
void changeendian32(uint32_t * a){
*a = (*a & 0x000000FF) << 24 |
(*a & 0x0000FF00) << 8 |
(*a & 0x00FF0000) >> 8 |
(*a & 0xFF000000) >> 24;
}
/******************************************************************************/
static inline
void shiftkey(uint8_t *key){
uint8_t k[7];
memcpy(k, key, 7);
permute((uint8_t*)shiftkey_permtab, k, key);
}
/******************************************************************************/
static inline
void shiftkey_inv(uint8_t *key){
uint8_t k[7];
memcpy(k, key, 7);
permute((uint8_t*)shiftkeyinv_permtab, k, key);
}
/******************************************************************************/
static inline
uint64_t splitin6bitwords(uint64_t a){
uint64_t ret=0;
a &= 0x0000ffffffffffffLL;
permute((uint8_t*)splitin6bitword_permtab, (uint8_t*)&a, (uint8_t*)&ret);
return ret;
}
/******************************************************************************/
static inline
uint8_t substitute(uint8_t a, uint8_t * sbp){
uint8_t x;
x = sbp[a>>1];
x = (a&1)?x&0x0F:x>>4;
return x;
}
/******************************************************************************/
uint32_t des_f(uint32_t r, uint8_t* kr){
uint8_t i;
uint32_t t=0,ret;
uint64_t data;
uint8_t *sbp; /* sboxpointer */
permute((uint8_t*)e_permtab, (uint8_t*)&r, (uint8_t*)&data);
for(i=0; i<7; ++i)
((uint8_t*)&data)[i] ^= kr[i];
/* Sbox substitution */
data = splitin6bitwords(data);
sbp=(uint8_t*)sbox;
for(i=0; i<8; ++i){
uint8_t x;
x = substitute(((uint8_t*)&data)[i], sbp);
t<<=4;
t |= x;
sbp += 32;
}
changeendian32(&t);
permute((uint8_t*)p_permtab,(uint8_t*)&t, (uint8_t*)&ret);
return ret;
}
/******************************************************************************/
void des_enc(void* out, const void* in, const void* key){
#define R *((uint32_t*)&(data[4]))
#define L *((uint32_t*)&(data[0]))
uint8_t data[8],kr[6],k[7];
uint8_t i;
permute((uint8_t*)ip_permtab, (uint8_t*)in, data);
permute((uint8_t*)pc1_permtab, (const uint8_t*)key, k);
for(i=0; i<8; ++i){
shiftkey(k);
if(ROTTABLE&((1<<((i<<1)+0))) )
shiftkey(k);
permute((uint8_t*)pc2_permtab, k, kr);
L ^= des_f(R, kr);
shiftkey(k);
if(ROTTABLE&((1<<((i<<1)+1))) )
shiftkey(k);
permute((uint8_t*)pc2_permtab, k, kr);
R ^= des_f(L, kr);
}
/* L <-> R*/
R ^= L;
L ^= R;
R ^= L;
permute((uint8_t*)inv_ip_permtab, data, (uint8_t*)out);
}
/******************************************************************************/
void des_dec(void* out, const void* in, const uint8_t* key){
#define R *((uint32_t*)&(data[4]))
#define L *((uint32_t*)&(data[0]))
uint8_t data[8],kr[6],k[7];
int8_t i;
permute((uint8_t*)ip_permtab, (uint8_t*)in, data);
permute((uint8_t*)pc1_permtab, (const uint8_t*)key, k);
for(i=7; i>=0; --i){
permute((uint8_t*)pc2_permtab, k, kr);
L ^= des_f(R, kr);
shiftkey_inv(k);
if(ROTTABLE&((1<<((i<<1)+1))) ){
shiftkey_inv(k);
}
permute((uint8_t*)pc2_permtab, k, kr);
R ^= des_f(L, kr);
shiftkey_inv(k);
if(ROTTABLE&((1<<((i<<1)+0))) ){
shiftkey_inv(k);
}
}
/* L <-> R*/
R ^= L;
L ^= R;
R ^= L;
permute((uint8_t*)inv_ip_permtab, data, (uint8_t*)out);
}
/******************************************************************************/
void tdes_enc(void* out, void* in, const void* key){
des_enc(out, in, (uint8_t*)key + 0);
des_dec(out, out, (uint8_t*)key + 8);
des_enc(out, out, (uint8_t*)key +16);
}
/******************************************************************************/
void tdes_dec(void* out, void* in, const uint8_t* key){
des_dec(out, in, (uint8_t*)key +16);
des_enc(out, out, (uint8_t*)key + 8);
des_dec(out, out, (uint8_t*)key + 0);
}
/******************************************************************************/

View file

@ -1,107 +0,0 @@
/* des.h */
/*
This file is part of the ARM-Crypto-Lib.
Copyright (C) 2008 Daniel Otte (daniel.otte@rub.de)
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 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 General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
/**
* \file des.h
* \author Daniel Otte
* \date 2007-06-16
* \brief des and tdes declarations
* \license GPLv3 or later
*
*/
#ifndef DES_H_
#define DES_H_
/* the FIPS 46-3 (1999-10-25) name for triple DES is triple data encryption algorithm so TDEA.
* Also we only implement the three key mode */
/** \def tdea_enc
* \brief defining an alias for void tdes_enc(void* out, const void* in, const void* key)
*/
/** \def tdea_dec
* \brief defining an alias for void tdes_dec(void* out, const void* in, const void* key)
*/
#define tdea_enc tdes_enc
#define tdea_dec tdes_dec
/** \fn void des_enc(void* out, const void* in, const void* key)
* \brief encrypt a block with DES
*
* This function encrypts a block of 64 bits (8 bytes) with the DES algorithm.
* Key expansion is done automatically. The key is 64 bits long, but note that
* only 56 bits are used (the LSB of each byte is dropped). The input and output
* blocks may overlap.
*
* \param out pointer to the block (64 bit = 8 byte) where the ciphertext is written to
* \param in pointer to the block (64 bit = 8 byte) where the plaintext is read from
* \param key pointer to the key (64 bit = 8 byte)
*/
void des_enc(void* out, const void* in, const void* key);
/** \fn void des_dec(void* out, const void* in, const void* key)
* \brief decrypt a block with DES
*
* This function decrypts a block of 64 bits (8 bytes) with the DES algorithm.
* Key expansion is done automatically. The key is 64 bits long, but note that
* only 56 bits are used (the LSB of each byte is dropped). The input and output
* blocks may overlap.
*
* \param out pointer to the block (64 bit = 8 byte) where the plaintext is written to
* \param in pointer to the block (64 bit = 8 byte) where the ciphertext is read from
* \param key pointer to the key (64 bit = 8 byte)
*/
void des_dec(void* out, const void* in, const void* key);
/** \fn void tdes_enc(void* out, const void* in, const void* key)
* \brief encrypt a block with Tripple-DES
*
* This function encrypts a block of 64 bits (8 bytes) with the Tripple-DES (EDE)
* algorithm. Key expansion is done automatically. The key is 192 bits long, but
* note that only 178 bits are used (the LSB of each byte is dropped). The input
* and output blocks may overlap.
*
* \param out pointer to the block (64 bit = 8 byte) where the ciphertext is written to
* \param in pointer to the block (64 bit = 8 byte) where the plaintext is read from
* \param key pointer to the key (192 bit = 24 byte)
*/
void tdes_enc(void* out, const void* in, const void* key);
/** \fn void tdes_dec(void* out, const void* in, const void* key)
* \brief decrypt a block with Tripple-DES
*
* This function decrypts a block of 64 bits (8 bytes) with the Tripple-DES (EDE)
* algorithm. Key expansion is done automatically. The key is 192 bits long, but
* note that only 178 bits are used (the LSB of each byte is dropped). The input
* and output blocks may overlap.
*
* \param out pointer to the block (64 bit = 8 byte) where the plaintext is written to
* \param in pointer to the block (64 bit = 8 byte) where the ciphertext is read from
* \param key pointer to the key (192 bit = 24 byte)
*/
void tdes_dec(void* out, const void* in, const void* key);
#endif /*DES_H_*/
// Copied from des.h in desfire imp.
typedef unsigned long DES_KS[16][2]; /* Single-key DES key schedule */
typedef unsigned long DES3_KS[48][2]; /* Triple-DES key schedule */
extern int Asmversion; /* 1 if we're linked with an asm version, 0 if C */

View file

@ -1,642 +0,0 @@
/*-
* 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;
}
}

View file

@ -1,14 +0,0 @@
#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

View file

@ -1,155 +0,0 @@
/*-
* 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;
}
}

View file

@ -1,17 +0,0 @@
#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

View file

@ -13,7 +13,7 @@
#include "iso14443a.h"
#include "epa.h"
#include "../common/cmd.h"
#include "cmd.h"
// Protocol and Parameter Selection Request
// use regular (1x) speed in both directions
@ -254,13 +254,11 @@ void EPA_PACE_Collect_Nonce(UsbCommand *c)
func_return = EPA_Setup();
if (func_return != 0) {
EPA_PACE_Collect_Nonce_Abort(1, func_return);
Dbprintf("epa: setup fucked up! %d", func_return);
return;
}
// increase the timeout (at least some cards really do need this!)
iso14a_set_timeout(0x0002FFFF);
Dbprintf("epa: Epic!");
// read the CardAccess file
// this array will hold the CardAccess file
@ -268,13 +266,10 @@ void EPA_PACE_Collect_Nonce(UsbCommand *c)
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
@ -286,8 +281,6 @@ void EPA_PACE_Collect_Nonce(UsbCommand *c)
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);

View file

@ -9,8 +9,7 @@
// Routines to load the FPGA image, and then to configure the FPGA's major
// mode once it is configured.
//-----------------------------------------------------------------------------
#include "../include/proxmark3.h"
#include "proxmark3.h"
#include "apps.h"
#include "util.h"
#include "string.h"

View file

@ -16,10 +16,10 @@
// (c) 2012 Roel Verdult
//-----------------------------------------------------------------------------
#include "../include/proxmark3.h"
#include "proxmark3.h"
#include "apps.h"
#include "util.h"
#include "../include/hitag2.h"
#include "hitag2.h"
#include "string.h"
static bool bQuiet;
@ -744,7 +744,7 @@ void SnoopHitag(uint32_t type) {
// Set up eavesdropping mode, frequency divisor which will drive the FPGA
// and analog mux selection.
FpgaDownloadAndGo(FPGA_BITSTREAM_LF);
FpgaWriteConfWord(FPGA_MAJOR_MODE_LF_EDGE_DETECT | FPGA_LF_EDGE_DETECT_TOGGLE_MODE);
FpgaWriteConfWord(FPGA_MAJOR_MODE_LF_EDGE_DETECT);
FpgaSendCommand(FPGA_CMD_SET_DIVISOR, 95); //125Khz
SetAdcMuxFor(GPIO_MUXSEL_LOPKD);
RELAY_OFF();
@ -968,7 +968,7 @@ void SimulateHitagTag(bool tag_mem_supplied, byte_t* data) {
// Set up simulator mode, frequency divisor which will drive the FPGA
// and analog mux selection.
FpgaDownloadAndGo(FPGA_BITSTREAM_LF);
FpgaWriteConfWord(FPGA_MAJOR_MODE_LF_EDGE_DETECT | FPGA_LF_EDGE_DETECT_READER_FIELD);
FpgaWriteConfWord(FPGA_MAJOR_MODE_LF_EDGE_DETECT);
FpgaSendCommand(FPGA_CMD_SET_DIVISOR, 95); //125Khz
SetAdcMuxFor(GPIO_MUXSEL_LOPKD);
RELAY_OFF();
@ -1158,7 +1158,7 @@ void ReaderHitag(hitag_function htf, hitag_data* htd) {
case RHT2F_CRYPTO: {
DbpString("Authenticating using key:");
memcpy(key,htd->crypto.key,6); // 4 or 6 ??
memcpy(key,htd->crypto.key,4); //HACK; 4 or 6?? I read both in the code.
Dbhexdump(6,key,false);
blocknr = 0;
bQuiet = false;

View file

@ -36,7 +36,7 @@
//
//-----------------------------------------------------------------------------
#include "../include/proxmark3.h"
#include "proxmark3.h"
#include "apps.h"
#include "util.h"
#include "string.h"
@ -45,11 +45,9 @@
// Needed for CRC in emulation mode;
// same construction as in ISO 14443;
// different initial value (CRC_ICLASS)
#include "../common/iso14443crc.h"
#include "../common/iso15693tools.h"
#include "iso14443crc.h"
#include "iso15693tools.h"
static int timeout = 4096;
@ -1702,7 +1700,7 @@ void IClass_iso14443A_write(uint8_t arg0, uint8_t blockNo, uint8_t *data, uint8_
uint16_t crc = 0;
uint8_t* resp = (((uint8_t *)BigBuf) + RECV_RESP_OFFSET);
uint8_t* resp = (((uint8_t *)BigBuf) + 3560);
// Reset trace buffer
memset(trace, 0x44, RECV_CMD_OFFSET);

View file

@ -10,12 +10,12 @@
// supported.
//-----------------------------------------------------------------------------
#include "../include/proxmark3.h"
#include "proxmark3.h"
#include "apps.h"
#include "util.h"
#include "string.h"
#include "../common/iso14443crc.h"
#include "iso14443crc.h"
//static void GetSamplesFor14443(int weTx, int n);

View file

@ -10,12 +10,13 @@
// Routines to support ISO 14443 type A.
//-----------------------------------------------------------------------------
#include "../include/proxmark3.h"
#include "proxmark3.h"
#include "apps.h"
#include "util.h"
#include "string.h"
#include "../common/cmd.h"
#include "../common/iso14443crc.h"
#include "cmd.h"
#include "iso14443crc.h"
#include "iso14443a.h"
#include "crapto1.h"
#include "mifareutil.h"
@ -1721,26 +1722,18 @@ int ReaderReceive(uint8_t *receivedAnswer, uint8_t *parity)
* fills the uid pointer unless NULL
* fills resp_data unless NULL */
int iso14443a_select_card(byte_t *uid_ptr, iso14a_card_select_t *p_hi14a_card, uint32_t *cuid_ptr) {
//uint8_t deselect[] = {0xc2}; //DESELECT
//uint8_t halt[] = { 0x50, 0x00, 0x57, 0xCD }; // HALT
uint8_t wupa[] = { 0x52 }; // WAKE-UP
//uint8_t reqa[] = { 0x26 }; // REQUEST A
uint8_t wupa[] = { 0x52 }; // 0x26 - REQA 0x52 - WAKE-UP
uint8_t sel_all[] = { 0x93,0x20 };
uint8_t sel_uid[] = { 0x93,0x70,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
uint8_t rats[] = { 0xE0,0x80,0x00,0x00 }; // FSD=256, FSDI=8, CID=0
uint8_t *resp = ((uint8_t *)BigBuf) + RECV_RESP_OFFSET;
uint8_t *resp_par = ((uint8_t *)BigBuf) + RECV_RESP_PAR_OFFSET;
byte_t uid_resp[4];
size_t uid_resp_len;
uint8_t sak = 0x04; // cascade uid
int cascade_level = 0;
int len =0;
// test for the SKYLANDERS TOY.
// ReaderTransmit(deselect,sizeof(deselect), NULL);
// len = ReaderReceive(resp, resp_par);
int len;
// Broadcast for a card, WUPA (0x52) will force response from all cards in the field
ReaderTransmitBitsPar(wupa,7,0, NULL);
@ -1816,14 +1809,10 @@ int iso14443a_select_card(byte_t* uid_ptr, iso14a_card_select_t* p_hi14a_card, u
ReaderTransmit(sel_uid, sizeof(sel_uid), NULL);
// Receive the SAK
if (!ReaderReceive(resp, resp_par)){
return 0;
}
if (!ReaderReceive(resp, resp_par)) return 0;
sak = resp[0];
// Test if more parts of the uid are coming
// Test if more parts of the uid are comming
if ((sak & 0x04) /* && uid_resp[0] == 0x88 */) {
// Remove first byte, 0x88 is not an UID byte, it CT, see page 3 of:
// http://www.nxp.com/documents/application_note/AN10927.pdf
@ -1877,7 +1866,8 @@ void iso14443a_setup(uint8_t fpga_minor_mode) {
SetAdcMuxFor(GPIO_MUXSEL_HIPKD);
// Signal field is on with the appropriate LED
if (fpga_minor_mode == FPGA_HF_ISO14443A_READER_MOD || fpga_minor_mode == FPGA_HF_ISO14443A_READER_LISTEN) {
if (fpga_minor_mode == FPGA_HF_ISO14443A_READER_MOD
|| fpga_minor_mode == FPGA_HF_ISO14443A_READER_LISTEN) {
LED_D_ON();
} else {
LED_D_OFF();
@ -1890,7 +1880,7 @@ void iso14443a_setup(uint8_t fpga_minor_mode) {
DemodReset();
UartReset();
NextTransferTime = 2*DELAY_ARM2AIR_AS_READER;
iso14a_set_timeout(1050); // 10ms default 10*105 =
iso14a_set_timeout(1050); // 10ms default
}
int iso14_apdu(uint8_t *cmd, uint16_t cmd_len, void *data) {

View file

@ -12,7 +12,7 @@
#ifndef __ISO14443A_H
#define __ISO14443A_H
#include "../include/common.h"
#include "common.h"
#include "mifaresniff.h"
typedef struct {

View file

@ -58,14 +58,12 @@
// *) document all the functions
#include "../include/proxmark3.h"
#include "proxmark3.h"
#include "util.h"
#include "apps.h"
#include "string.h"
#include "../common/iso15693tools.h"
#include "../common/cmd.h"
#include "crapto1.h"
#include "mifareutil.h"
#include "iso15693tools.h"
#include "cmd.h"
#define arraylen(x) (sizeof(x)/sizeof((x)[0]))
@ -470,8 +468,20 @@ static int GetIso15693AnswerFromSniff(uint8_t *receivedResponse, int maxLen, int
// every other is Q. We just want power, so abs(I) + abs(Q) is
// close to what we want.
if(getNext) {
int8_t r;
dest[c++] = abs(b) + abs(prev);
if(b < 0) {
r = -b;
} else {
r = b;
}
if(prev < 0) {
r -= prev;
} else {
r += prev;
}
dest[c++] = (uint8_t)r;
if(c >= 20000) {
break;

View file

@ -8,14 +8,14 @@
// LEGIC RF simulation code
//-----------------------------------------------------------------------------
#include "../include/proxmark3.h"
#include "proxmark3.h"
#include "apps.h"
#include "util.h"
#include "string.h"
#include "legicrf.h"
#include "../include/legic_prng.h"
#include "../common/crc.h"
#include "legic_prng.h"
#include "crc.h"
static struct legic_frame {
int bits;

View file

@ -8,25 +8,66 @@
// Also routines for raw mode reading/simulating of LF waveform
//-----------------------------------------------------------------------------
#include "../include/proxmark3.h"
#include "proxmark3.h"
#include "apps.h"
#include "util.h"
#include "../common/crc16.h"
#include "../common/lfdemod.h"
#include "hitag2.h"
#include "crc16.h"
#include "string.h"
#include "crapto1.h"
#include "mifareutil.h"
#include "../include/hitag2.h"
#include "lfdemod.h"
// 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
#define T0 192
#define SHORT_COIL() LOW(GPIO_SSC_DOUT)
#define OPEN_COIL() HIGH(GPIO_SSC_DOUT)
/**
* Does the sample acquisition. If threshold is specified, the actual sampling
* is not commenced until the threshold has been reached.
* @param trigger_threshold - the threshold
* @param silent - is true, now outputs are made. If false, dbprints the status
*/
void DoAcquisition125k_internal(int trigger_threshold,bool silent)
{
uint8_t *dest = (uint8_t *)BigBuf;
int n = sizeof(BigBuf);
int i;
memset(dest, 0, n);
i = 0;
for(;;) {
if (AT91C_BASE_SSC->SSC_SR & AT91C_SSC_TXRDY) {
AT91C_BASE_SSC->SSC_THR = 0x43;
LED_D_ON();
}
if (AT91C_BASE_SSC->SSC_SR & AT91C_SSC_RXRDY) {
dest[i] = (uint8_t)AT91C_BASE_SSC->SSC_RHR;
LED_D_OFF();
if (trigger_threshold != -1 && dest[i] < trigger_threshold)
continue;
else
trigger_threshold = -1;
if (++i >= n) break;
}
}
if(!silent)
{
Dbprintf("buffer samples: %02x %02x %02x %02x %02x %02x %02x %02x ...",
dest[0], dest[1], dest[2], dest[3], dest[4], dest[5], dest[6], dest[7]);
}
}
/**
* Perform sample aquisition.
*/
void DoAcquisition125k(int trigger_threshold)
{
DoAcquisition125k_internal(trigger_threshold, false);
}
/**
* Setup the FPGA to listen for samples. This method downloads the FPGA bitstream
* if not already loaded, sets divisor and starts up the antenna.
* @param divisor : 1, 88> 255 or negative ==> 134.8 KHz
* 0 or 95 ==> 125 KHz
*
**/
void LFSetupFPGAForADC(int divisor, bool lf_field)
{
FpgaDownloadAndGo(FPGA_BITSTREAM_LF);
@ -41,76 +82,52 @@ void LFSetupFPGAForADC(int divisor, bool lf_field)
// Connect the A/D to the peak-detected low-frequency path.
SetAdcMuxFor(GPIO_MUXSEL_LOPKD);
// Give it a bit of time for the resonant antenna to settle.
SpinDelay(150);
SpinDelay(50);
// Now set up the SSC to get the ADC samples that are now streaming at us.
FpgaSetupSsc();
}
/**
* Initializes the FPGA, and acquires the samples.
**/
void AcquireRawAdcSamples125k(int divisor)
{
LFSetupFPGAForADC(divisor, true);
DoAcquisition125k();
// Now call the acquisition routine
DoAcquisition125k_internal(-1,false);
}
/**
* Initializes the FPGA for snoop-mode, and acquires the samples.
**/
void SnoopLFRawAdcSamples(int divisor, int trigger_threshold)
{
LFSetupFPGAForADC(divisor, false);
DoAcquisition125k_threshold(trigger_threshold);
}
// split into two routines so we can avoid timing issues after sending commands //
void DoAcquisition125k_internal(int trigger_threshold, bool silent)
{
uint8_t *dest = (uint8_t *)BigBuf;
uint16_t i = 0;
memset(dest, 0x00, BIGBUF_SIZE);
for(;;) {
if (AT91C_BASE_SSC->SSC_SR & AT91C_SSC_TXRDY) {
AT91C_BASE_SSC->SSC_THR = 0x43;
LED_D_ON();
}
if (AT91C_BASE_SSC->SSC_SR & AT91C_SSC_RXRDY) {
dest[i] = (uint8_t)AT91C_BASE_SSC->SSC_RHR;
LED_D_OFF();
if (trigger_threshold != -1 && dest[i] < trigger_threshold)
continue;
else
trigger_threshold = -1;
if (++i >= BIGBUF_SIZE) break;
}
}
if (!silent){
Dbprintf("buffer samples: %02x %02x %02x %02x %02x %02x %02x %02x ...",
dest[0], dest[1], dest[2], dest[3], dest[4], dest[5], dest[6], dest[7]);
}
}
void DoAcquisition125k_threshold(int trigger_threshold) {
DoAcquisition125k_internal(trigger_threshold, true);
}
void DoAcquisition125k() {
DoAcquisition125k_internal(-1, true);
DoAcquisition125k(trigger_threshold);
}
void ModThenAcquireRawAdcSamples125k(int delay_off, int period_0, int period_1, uint8_t *command)
{
FpgaDownloadAndGo(FPGA_BITSTREAM_LF);
/* Make sure the tag is reset */
FpgaDownloadAndGo(FPGA_BITSTREAM_LF);
FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
SpinDelay(2500);
int divisor = 95; // 125 KHz
// see if 'h' was specified
if (command[strlen((char *) command) - 1] == 'h')
divisor = 88; // 134.8 KHz
FpgaSendCommand(FPGA_CMD_SET_DIVISOR, divisor);
int divisor_used = 95; // 125 KHz
// see if 'h' was specified
if (command[strlen((char *) command) - 1] == 'h')
divisor_used = 88; // 134.8 KHz
FpgaSendCommand(FPGA_CMD_SET_DIVISOR, divisor_used);
FpgaWriteConfWord(FPGA_MAJOR_MODE_LF_ADC | FPGA_LF_ADC_READER_FIELD);
// Give it a bit of time for the resonant antenna to settle.
SpinDelay(50);
// And a little more time for the tag to fully power up
SpinDelay(2000);
// Now set up the SSC to get the ADC samples that are now streaming at us.
@ -121,7 +138,7 @@ void ModThenAcquireRawAdcSamples125k(int delay_off, int period_0, int period_1,
FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
LED_D_OFF();
SpinDelayUs(delay_off);
FpgaSendCommand(FPGA_CMD_SET_DIVISOR, divisor);
FpgaSendCommand(FPGA_CMD_SET_DIVISOR, divisor_used);
FpgaWriteConfWord(FPGA_MAJOR_MODE_LF_ADC | FPGA_LF_ADC_READER_FIELD);
LED_D_ON();
@ -133,7 +150,8 @@ void ModThenAcquireRawAdcSamples125k(int delay_off, int period_0, int period_1,
FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
LED_D_OFF();
SpinDelayUs(delay_off);
FpgaSendCommand(FPGA_CMD_SET_DIVISOR, divisor);
FpgaSendCommand(FPGA_CMD_SET_DIVISOR, divisor_used);
FpgaWriteConfWord(FPGA_MAJOR_MODE_LF_ADC | FPGA_LF_ADC_READER_FIELD);
// now do the read
@ -289,17 +307,17 @@ void WriteTIbyte(uint8_t b)
{
if (b&(1<<i)) {
// stop modulating antenna
SHORT_COIL();
LOW(GPIO_SSC_DOUT);
SpinDelayUs(1000);
// modulate antenna
OPEN_COIL();
HIGH(GPIO_SSC_DOUT);
SpinDelayUs(1000);
} else {
// stop modulating antenna
SHORT_COIL();
LOW(GPIO_SSC_DOUT);
SpinDelayUs(300);
// modulate antenna
OPEN_COIL();
HIGH(GPIO_SSC_DOUT);
SpinDelayUs(1700);
}
}
@ -447,167 +465,61 @@ void WriteTItag(uint32_t idhi, uint32_t idlo, uint16_t crc)
DbpString("Now use tiread to check");
}
// PIO_CODR = Clear Output Data Register
// PIO_SODR = Set Output Data Register
//#define LOW(x) AT91C_BASE_PIOA->PIO_CODR = (x)
//#define HIGH(x) AT91C_BASE_PIOA->PIO_SODR = (x)
void SimulateTagLowFrequency( uint16_t period, uint32_t gap, uint8_t ledcontrol)
void SimulateTagLowFrequency(int period, int gap, int ledcontrol)
{
int i;
uint8_t *tab = (uint8_t *)BigBuf;
FpgaDownloadAndGo(FPGA_BITSTREAM_LF);
FpgaWriteConfWord(FPGA_MAJOR_MODE_LF_EDGE_DETECT);
AT91C_BASE_PIOA->PIO_PER = GPIO_SSC_DOUT | GPIO_SSC_CLK;
AT91C_BASE_PIOA->PIO_OER = GPIO_SSC_DOUT;
AT91C_BASE_PIOA->PIO_ODR = GPIO_SSC_CLK;
#define SHORT_COIL() LOW(GPIO_SSC_DOUT)
#define OPEN_COIL() HIGH(GPIO_SSC_DOUT)
i = 0;
for(;;) {
while(!(AT91C_BASE_PIOA->PIO_PDSR & GPIO_SSC_CLK)) {
if(BUTTON_PRESS()) {
DbpString("Stopped");
return;
}
WDT_HIT();
}
if (ledcontrol)
LED_D_ON();
uint16_t i = 0;
uint8_t send = 0;
//int overflow = 0;
uint8_t *buf = (uint8_t *)BigBuf;
FpgaDownloadAndGo(FPGA_BITSTREAM_LF);
FpgaWriteConfWord(FPGA_MAJOR_MODE_LF_EDGE_DETECT | FPGA_LF_EDGE_DETECT_READER_FIELD);
FpgaSendCommand(FPGA_CMD_SET_DIVISOR, 95); //125Khz
SetAdcMuxFor(GPIO_MUXSEL_LOPKD);
RELAY_OFF();
// Configure output pin that is connected to the FPGA (for modulating)
AT91C_BASE_PIOA->PIO_OER = GPIO_SSC_DOUT;
AT91C_BASE_PIOA->PIO_PER = GPIO_SSC_DOUT;
if(tab[i])
OPEN_COIL();
else
SHORT_COIL();
// Enable Peripheral Clock for TIMER_CLOCK0, used to measure exact timing before answering
AT91C_BASE_PMC->PMC_PCER = (1 << AT91C_ID_TC0);
// Enable Peripheral Clock for TIMER_CLOCK1, used to capture edges of the reader frames
AT91C_BASE_PMC->PMC_PCER = (1 << AT91C_ID_TC1);
AT91C_BASE_PIOA->PIO_BSR = GPIO_SSC_FRAME;
// 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,
// external trigger rising edge, load RA on rising edge of TIOA.
AT91C_BASE_TC1->TC_CMR = AT91C_TC_CLKS_TIMER_DIV1_CLOCK | AT91C_TC_ETRGEDG_RISING | AT91C_TC_ABETRG | AT91C_TC_LDRA_RISING;
// Enable and reset counter
//AT91C_BASE_TC0->TC_CCR = AT91C_TC_CLKEN | AT91C_TC_SWTRG;
AT91C_BASE_TC1->TC_CCR = AT91C_TC_CLKEN | AT91C_TC_SWTRG;
while(!BUTTON_PRESS()) {
WDT_HIT();
// Receive frame, watch for at most T0*EOF periods
while (AT91C_BASE_TC1->TC_CV < T0 * 55) {
// Check if rising edge in modulation is detected
if(AT91C_BASE_TC1->TC_SR & AT91C_TC_LDRAS) {
// Retrieve the new timing values
//int ra = (AT91C_BASE_TC1->TC_RA/T0) + overflow;
//Dbprintf("Timing value - %d %d", ra, overflow);
//overflow = 0;
// Reset timer every frame, we have to capture the last edge for timing
AT91C_BASE_TC0->TC_CCR = AT91C_TC_CLKEN | AT91C_TC_SWTRG;
send = 1;
LED_B_ON();
}
}
if ( send ) {
// Disable timer 1 with external trigger to avoid triggers during our own modulation
AT91C_BASE_TC1->TC_CCR = AT91C_TC_CLKDIS;
// Wait for HITAG_T_WAIT_1 carrier periods after the last reader bit,
// not that since the clock counts since the rising edge, but T_Wait1 is
// with respect to the falling edge, we need to wait actually (T_Wait1 - T_Low)
// periods. The gap time T_Low varies (4..10). All timer values are in
// terms of T0 units
while(AT91C_BASE_TC0->TC_CV < T0 * 16 );
// datat kommer in som 1 bit för varje position i arrayn
for(i = 0; i < period; ++i) {
// Reset clock for the next bit
AT91C_BASE_TC0->TC_CCR = AT91C_TC_SWTRG;
if ( buf[i] > 0 )
HIGH(GPIO_SSC_DOUT);
else
LOW(GPIO_SSC_DOUT);
while(AT91C_BASE_TC0->TC_CV < T0 * 1 );
}
// Drop modulation
LOW(GPIO_SSC_DOUT);
// Enable and reset external trigger in timer for capturing future frames
AT91C_BASE_TC1->TC_CCR = AT91C_TC_CLKEN | AT91C_TC_SWTRG;
LED_B_OFF();
}
send = 0;
// Save the timer overflow, will be 0 when frame was received
//overflow += (AT91C_BASE_TC1->TC_CV/T0);
// Reset the timer to restart while-loop that receives frames
AT91C_BASE_TC1->TC_CCR = AT91C_TC_SWTRG;
}
LED_B_OFF();
if (ledcontrol)
LED_D_OFF();
AT91C_BASE_TC1->TC_CCR = AT91C_TC_CLKDIS;
AT91C_BASE_TC0->TC_CCR = AT91C_TC_CLKDIS;
FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
DbpString("Sim Stopped");
while(AT91C_BASE_PIOA->PIO_PDSR & GPIO_SSC_CLK) {
if(BUTTON_PRESS()) {
DbpString("Stopped");
return;
}
void SimulateTagLowFrequencyA(int len, int gap)
{
uint8_t *buf = (uint8_t *)BigBuf;
FpgaDownloadAndGo(FPGA_BITSTREAM_LF);
FpgaSendCommand(FPGA_CMD_SET_DIVISOR, 95); //125Khz
FpgaWriteConfWord(FPGA_MAJOR_MODE_LF_EDGE_DETECT | FPGA_LF_EDGE_DETECT_TOGGLE_MODE); // new izsh toggle mode!
// Connect the A/D to the peak-detected low-frequency path.
SetAdcMuxFor(GPIO_MUXSEL_LOPKD);
// Now set up the SSC to get the ADC samples that are now streaming at us.
FpgaSetupSsc();
SpinDelay(5);
AT91C_BASE_SSC->SSC_THR = 0x00;
int i = 0;
while(!BUTTON_PRESS()) {
WDT_HIT();
if (AT91C_BASE_SSC->SSC_SR & AT91C_SSC_TXRDY) {
}
if ( buf[i] > 0 )
AT91C_BASE_SSC->SSC_THR = 0x43;
else
AT91C_BASE_SSC->SSC_THR = 0x00;
++i;
LED_A_ON();
if (i >= len){
i++;
if(i == period) {
i = 0;
if (gap) {
SHORT_COIL();
SpinDelayUs(gap);
}
}
if (AT91C_BASE_SSC->SSC_SR & AT91C_SSC_RXRDY) {
volatile uint32_t r = AT91C_BASE_SSC->SSC_RHR;
(void)r;
LED_A_OFF();
}
}
DbpString("lf simulate stopped");
FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
}
#define DEBUG_FRAME_CONTENTS 1
void SimulateTagLowFrequencyBidir(int divisor, int t0)
@ -615,7 +527,7 @@ void SimulateTagLowFrequencyBidir(int divisor, int t0)
}
// compose fc/8 fc/10 waveform
static void fc(int c, uint16_t *n) {
static void fc(int c, int *n) {
uint8_t *dest = (uint8_t *)BigBuf;
int idx;
@ -663,9 +575,9 @@ static void fc(int c, uint16_t *n) {
// prepare a waveform pattern in the buffer based on the ID given then
// simulate a HID tag until the button is pressed
void CmdHIDsimTAG(int hi, int lo, uint8_t ledcontrol)
void CmdHIDsimTAG(int hi, int lo, int ledcontrol)
{
uint16_t n = 0, i = 0;
int n=0, i=0;
/*
HID tag bitstream format
The tag contains a 44bit unique code. This is sent out MSB first in sets of 4 bits
@ -722,10 +634,12 @@ void CmdHIDsimTAG(int hi, int lo, uint8_t ledcontrol)
void CmdHIDdemodFSK(int findone, int *high, int *low, int ledcontrol)
{
uint8_t *dest = (uint8_t *)BigBuf;
size_t size=0; //, found=0;
uint32_t hi2=0, hi=0, lo=0;
// Configure to go in 125Khz listen mode
LFSetupFPGAForADC(0, true);
LFSetupFPGAForADC(95, true);
while(!BUTTON_PRESS()) {
@ -733,31 +647,25 @@ void CmdHIDdemodFSK(int findone, int *high, int *low, int ledcontrol)
if (ledcontrol) LED_A_ON();
DoAcquisition125k_internal(-1,true);
size = sizeof(BigBuf);
if (size < 2000) continue;
// FSK demodulator
int bitLen = HIDdemodFSK(dest,BIGBUF_SIZE,&hi2,&hi,&lo);
int bitLen = HIDdemodFSK(dest,size,&hi2,&hi,&lo);
WDT_HIT();
if (bitLen>0 && lo>0){
// final loop, go over previously decoded manchester data and decode into usable tag ID
// 111000 bit pattern represent start of frame, 01 pattern represents a 1 and 10 represents a 0
if (hi2 != 0){
//extra large HID tags
if (hi2 != 0){ //extra large HID tags
Dbprintf("TAG ID: %x%08x%08x (%d)",
(unsigned int) hi2,
(unsigned int) hi,
(unsigned int) lo,
(unsigned int) (lo >> 1) & 0xFFFF);
} else {
//standard HID tags <38 bits
(unsigned int) hi2, (unsigned int) hi, (unsigned int) lo, (unsigned int) (lo>>1) & 0xFFFF);
}else { //standard HID tags <38 bits
//Dbprintf("TAG ID: %x%08x (%d)",(unsigned int) hi, (unsigned int) lo, (unsigned int) (lo>>1) & 0xFFFF); //old print cmd
uint8_t bitlen = 0;
uint32_t fc = 0;
uint32_t cardnum = 0;
if (((hi>>5)&1)==1){//if bit 38 is set then < 37 bit format is used
uint32_t lo2=0;
lo2=(((hi & 31) << 12) | (lo>>20)); //get bits 21-37 to check for format len bit
@ -795,13 +703,11 @@ void CmdHIDdemodFSK(int findone, int *high, int *low, int ledcontrol)
fc = ((hi&0xF)<<12)|(lo>>20);
}
}
//Dbprintf("TAG ID: %x%08x (%d)",
// (unsigned int) hi, (unsigned int) lo, (unsigned int) (lo>>1) & 0xFFFF);
Dbprintf("TAG ID: %x%08x (%d) - Format Len: %dbit - FC: %d - Card: %d",
(unsigned int) hi,
(unsigned int) lo,
(unsigned int) (lo >> 1) & 0xFFFF,
(unsigned int) bitlen,
(unsigned int) fc,
(unsigned int) cardnum);
(unsigned int) hi, (unsigned int) lo, (unsigned int) (lo>>1) & 0xFFFF,
(unsigned int) bitlen, (unsigned int) fc, (unsigned int) cardnum);
}
if (findone){
if (ledcontrol) LED_A_OFF();
@ -819,12 +725,13 @@ void CmdHIDdemodFSK(int findone, int *high, int *low, int ledcontrol)
void CmdEM410xdemod(int findone, int *high, int *low, int ledcontrol)
{
uint8_t *dest = (uint8_t *)BigBuf;
size_t size=0; //, found=0;
uint32_t bitLen=0;
int clk=0, invert=0, errCnt=0;
uint64_t lo=0;
// Configure to go in 125Khz listen mode
LFSetupFPGAForADC(0, true);
LFSetupFPGAForADC(95, true);
while(!BUTTON_PRESS()) {
@ -832,33 +739,37 @@ void CmdEM410xdemod(int findone, int *high, int *low, int ledcontrol)
if (ledcontrol) LED_A_ON();
DoAcquisition125k_internal(-1,true);
size = sizeof(BigBuf);
if (size < 2000) continue;
// FSK demodulator
bitLen = BIGBUF_SIZE;
errCnt = askmandemod(dest,&bitLen,&clk,&invert);
if ( errCnt < 0 ) continue;
//int askmandemod(uint8_t *BinStream,uint32_t *BitLen,int *clk, int *invert);
bitLen=size;
//Dbprintf("DEBUG: Buffer got");
errCnt = askmandemod(dest,&bitLen,&clk,&invert); //HIDdemodFSK(dest,size,&hi2,&hi,&lo);
//Dbprintf("DEBUG: ASK Got");
WDT_HIT();
if (errCnt>=0){
lo = Em410xDecode(dest,bitLen);
if ( lo <= 0) continue;
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)
);
//Dbprintf("DEBUG: EM GOT");
//printEM410x(lo);
if (lo>0){
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();
return;
}
} else{
//Dbprintf("DEBUG: No Tag");
}
WDT_HIT();
lo = clk = invert = errCnt = 0;
lo = 0;
clk=0;
invert=0;
errCnt=0;
size=0;
//SpinDelay(50);
}
DbpString("Stopped");
if (ledcontrol) LED_A_OFF();
@ -872,22 +783,18 @@ void CmdIOdemodFSK(int findone, int *high, int *low, int ledcontrol)
uint8_t version=0;
uint8_t facilitycode=0;
uint16_t number=0;
LFSetupFPGAForADC(0, true);
// Configure to go in 125Khz listen mode
LFSetupFPGAForADC(95, true);
while(!BUTTON_PRESS()) {
WDT_HIT();
if (ledcontrol) LED_A_ON();
DoAcquisition125k_internal(-1,true);
idx = IOdemodFSK(dest, BIGBUF_SIZE);
if ( idx < 0 )
continue;
//fskdemod and get start index
WDT_HIT();
idx = IOdemodFSK(dest,sizeof(BigBuf));
if (idx>0){
//valid tag found
//Index map
//0 10 20 30 40 50 60
@ -898,7 +805,6 @@ void CmdIOdemodFSK(int findone, int *high, int *low, int ledcontrol)
//
//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]);
@ -908,7 +814,6 @@ void CmdIOdemodFSK(int findone, int *high, int *low, int ledcontrol)
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
@ -916,8 +821,10 @@ void CmdIOdemodFSK(int findone, int *high, int *low, int ledcontrol)
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();
return;
}
code=code2=0;
@ -925,7 +832,8 @@ void CmdIOdemodFSK(int findone, int *high, int *low, int ledcontrol)
number=0;
idx=0;
}
WDT_HIT();
}
DbpString("Stopped");
if (ledcontrol) LED_A_OFF();
}
@ -989,20 +897,10 @@ void CmdIOdemodFSK(int findone, int *high, int *low, int ledcontrol)
* To compensate antenna falling times shorten the write times
* and enlarge the gap ones.
*/
#define START_GAP 30*8 // 10 - 50fc 250
#define WRITE_GAP 20*8 // 8 - 30fc
#define WRITE_0 24*8 // 16 - 31fc 24fc 192
#define WRITE_1 54*8 // 48 - 63fc 54fc 432 for T55x7; 448 for E5550
// VALUES TAKEN FROM EM4x function: SendForward
// START_GAP = 440; (55*8) cycles at 125Khz (8us = 1cycle)
// WRITE_GAP = 128; (16*8)
// WRITE_1 = 256 32*8; (32*8)
// These timings work for 4469/4269/4305 (with the 55*8 above)
// WRITE_0 = 23*8 , 9*8 SpinDelayUs(23*8);
#define T55xx_SAMPLES_SIZE 12000 // 32 x 32 x 10 (32 bit times numofblock (7), times clock skip..)
#define START_GAP 250
#define WRITE_GAP 160
#define WRITE_0 144 // 192
#define WRITE_1 400 // 432 for T55x7; 448 for E5550
// Write one bit to card
void T55xxWriteBit(int bit)
@ -1010,7 +908,7 @@ void T55xxWriteBit(int bit)
FpgaDownloadAndGo(FPGA_BITSTREAM_LF);
FpgaSendCommand(FPGA_CMD_SET_DIVISOR, 95); //125Khz
FpgaWriteConfWord(FPGA_MAJOR_MODE_LF_ADC | FPGA_LF_ADC_READER_FIELD);
if (!bit)
if (bit == 0)
SpinDelayUs(WRITE_0);
else
SpinDelayUs(WRITE_1);
@ -1021,11 +919,16 @@ void T55xxWriteBit(int bit)
// Write one card block in page 0, no lock
void T55xxWriteBlock(uint32_t Data, uint32_t Block, uint32_t Pwd, uint8_t PwdMode)
{
uint32_t i = 0;
//unsigned int i; //enio adjustment 12/10/14
uint32_t i;
// Set up FPGA, 125kHz
// Wait for config.. (192+8190xPOW)x8 == 67ms
LFSetupFPGAForADC(0, true);
FpgaDownloadAndGo(FPGA_BITSTREAM_LF);
FpgaSendCommand(FPGA_CMD_SET_DIVISOR, 95); //125Khz
FpgaWriteConfWord(FPGA_MAJOR_MODE_LF_ADC | FPGA_LF_ADC_READER_FIELD);
// Give it a bit of time for the resonant antenna to settle.
// And for the tag to fully power up
SpinDelay(150);
// Now start writting
FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
@ -1061,17 +964,27 @@ void T55xxWriteBlock(uint32_t Data, uint32_t Block, uint32_t Pwd, uint8_t PwdMod
// Read one card block in page 0
void T55xxReadBlock(uint32_t Block, uint32_t Pwd, uint8_t PwdMode)
{
uint8_t *dest = get_bigbufptr_recvrespbuf();
uint16_t bufferlength = T55xx_SAMPLES_SIZE;
uint32_t i = 0;
uint8_t *dest = (uint8_t *)BigBuf;
//int m=0, i=0; //enio adjustment 12/10/14
uint32_t m=0, i=0;
FpgaDownloadAndGo(FPGA_BITSTREAM_LF);
m = sizeof(BigBuf);
// Clear destination buffer before sending the command
memset(dest, 128, m);
// Connect the A/D to the peak-detected low-frequency path.
SetAdcMuxFor(GPIO_MUXSEL_LOPKD);
// Now set up the SSC to get the ADC samples that are now streaming at us.
FpgaSetupSsc();
// Clear destination buffer before sending the command 0x80 = average.
memset(dest, 0x80, bufferlength);
LED_D_ON();
FpgaSendCommand(FPGA_CMD_SET_DIVISOR, 95); //125Khz
FpgaWriteConfWord(FPGA_MAJOR_MODE_LF_ADC | FPGA_LF_ADC_READER_FIELD);
// Set up FPGA, 125kHz
// Wait for config.. (192+8190xPOW)x8 == 67ms
LFSetupFPGAForADC(0, true);
// Give it a bit of time for the resonant antenna to settle.
// And for the tag to fully power up
SpinDelay(150);
// Now start writting
FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
SpinDelayUs(START_GAP);
@ -1090,40 +1003,53 @@ void T55xxReadBlock(uint32_t Block, uint32_t Pwd, uint8_t PwdMode)
T55xxWriteBit(Block & i);
// Turn field on to read the response
TurnReadLFOn();
FpgaSendCommand(FPGA_CMD_SET_DIVISOR, 95); //125Khz
FpgaWriteConfWord(FPGA_MAJOR_MODE_LF_ADC | FPGA_LF_ADC_READER_FIELD);
// Now do the acquisition
i = 0;
for(;;) {
if (AT91C_BASE_SSC->SSC_SR & AT91C_SSC_TXRDY) {
AT91C_BASE_SSC->SSC_THR = 0x43;
//AT91C_BASE_SSC->SSC_THR = 0xff;
LED_D_ON();
}
if (AT91C_BASE_SSC->SSC_SR & AT91C_SSC_RXRDY) {
dest[i] = (uint8_t)AT91C_BASE_SSC->SSC_RHR;
++i;
LED_D_OFF();
if (i >= bufferlength) break;
// we don't care about actual value, only if it's more or less than a
// threshold essentially we capture zero crossings for later analysis
// if(dest[i] < 127) dest[i] = 0; else dest[i] = 1;
i++;
if (i >= m) break;
}
}
cmd_send(CMD_ACK,0,0,0,0,0);
FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); // field off
LED_D_OFF();
DbpString("DONE!");
}
// Read card traceability data (page 1)
void T55xxReadTrace(void){
uint8_t *dest = get_bigbufptr_recvrespbuf();
uint16_t bufferlength = T55xx_SAMPLES_SIZE;
uint32_t i = 0;
uint8_t *dest = (uint8_t *)BigBuf;
int m=0, i=0;
// Clear destination buffer before sending the command 0x80 = average
memset(dest, 0x80, bufferlength);
FpgaDownloadAndGo(FPGA_BITSTREAM_LF);
m = sizeof(BigBuf);
// Clear destination buffer before sending the command
memset(dest, 128, m);
// Connect the A/D to the peak-detected low-frequency path.
SetAdcMuxFor(GPIO_MUXSEL_LOPKD);
// Now set up the SSC to get the ADC samples that are now streaming at us.
FpgaSetupSsc();
LFSetupFPGAForADC(0, true);
LED_D_ON();
FpgaSendCommand(FPGA_CMD_SET_DIVISOR, 95); //125Khz
FpgaWriteConfWord(FPGA_MAJOR_MODE_LF_ADC | FPGA_LF_ADC_READER_FIELD);
// Give it a bit of time for the resonant antenna to settle.
// And for the tag to fully power up
SpinDelay(150);
// Now start writting
FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
SpinDelayUs(START_GAP);
@ -1132,34 +1058,25 @@ void T55xxReadTrace(void){
T55xxWriteBit(1); //Page 1
// Turn field on to read the response
TurnReadLFOn();
FpgaSendCommand(FPGA_CMD_SET_DIVISOR, 95); //125Khz
FpgaWriteConfWord(FPGA_MAJOR_MODE_LF_ADC | FPGA_LF_ADC_READER_FIELD);
// Now do the acquisition
i = 0;
for(;;) {
if (AT91C_BASE_SSC->SSC_SR & AT91C_SSC_TXRDY) {
AT91C_BASE_SSC->SSC_THR = 0x43;
LED_D_ON();
}
if (AT91C_BASE_SSC->SSC_SR & AT91C_SSC_RXRDY) {
dest[i] = (uint8_t)AT91C_BASE_SSC->SSC_RHR;
++i;
LED_D_OFF();
if (i >= bufferlength) break;
i++;
if (i >= m) break;
}
}
cmd_send(CMD_ACK,0,0,0,0,0);
FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); // field off
LED_D_OFF();
}
void TurnReadLFOn(){
FpgaSendCommand(FPGA_CMD_SET_DIVISOR, 95); //125Khz
FpgaWriteConfWord(FPGA_MAJOR_MODE_LF_ADC | FPGA_LF_ADC_READER_FIELD);
// Give it a bit of time for the resonant antenna to settle.
//SpinDelay(30);
SpinDelayUs(8*150);
DbpString("DONE!");
}
/*-------------- Cloning routines -----------*/
@ -1879,14 +1796,9 @@ void EM4xLogin(uint32_t Password) {
void EM4xReadWord(uint8_t Address, uint32_t Pwd, uint8_t PwdMode) {
uint8_t *dest = (uint8_t *)BigBuf;
uint16_t bufferlength = 12000;
uint32_t i = 0;
// Clear destination buffer before sending the command 0x80 = average.
memset(dest, 0x80, bufferlength);
uint8_t fwd_bit_count;
uint8_t *dest = (uint8_t *)BigBuf;
int m=0, i=0;
//If password mode do login
if (PwdMode == 1) EM4xLogin(Pwd);
@ -1895,6 +1807,9 @@ void EM4xReadWord(uint8_t Address, uint32_t Pwd, uint8_t PwdMode) {
fwd_bit_count = Prepare_Cmd( FWD_CMD_READ );
fwd_bit_count += Prepare_Addr( Address );
m = sizeof(BigBuf);
// 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.
@ -1902,9 +1817,6 @@ void EM4xReadWord(uint8_t Address, uint32_t Pwd, uint8_t PwdMode) {
SendForward(fwd_bit_count);
// // Turn field on to read the response
// TurnReadLFOn();
// Now do the acquisition
i = 0;
for(;;) {
@ -1913,12 +1825,10 @@ void EM4xReadWord(uint8_t Address, uint32_t Pwd, uint8_t PwdMode) {
}
if (AT91C_BASE_SSC->SSC_SR & AT91C_SSC_RXRDY) {
dest[i] = (uint8_t)AT91C_BASE_SSC->SSC_RHR;
++i;
if (i >= bufferlength) break;
i++;
if (i >= m) break;
}
}
cmd_send(CMD_ACK,0,0,0,0,0);
FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); // field off
LED_D_OFF();
}

View file

@ -15,9 +15,6 @@
#include "mifarecmd.h"
#include "apps.h"
#include "util.h"
#include "desfire.h"
#include "../common/crc.h"
//-----------------------------------------------------------------------------
// Select, Authenticate, Read a MIFARE tag.
@ -82,69 +79,7 @@ void MifareReadBlock(uint8_t arg0, uint8_t arg1, uint8_t arg2, uint8_t *datain)
cmd_send(CMD_ACK,isOK,0,0,dataoutbuf,16);
LED_B_OFF();
FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
LEDsoff();
}
void MifareUC_Auth1(uint8_t arg0, uint8_t *datain){
// variables
byte_t isOK = 0;
byte_t dataoutbuf[16];
uint8_t uid[10];
uint32_t cuid;
// clear trace
iso14a_clear_trace();
iso14443a_setup(FPGA_HF_ISO14443A_READER_LISTEN);
LED_A_ON();
LED_B_OFF();
LED_C_OFF();
if(!iso14443a_select_card(uid, NULL, &cuid)) {
if (MF_DBGLEVEL >= 1) Dbprintf("Can't select card, something went wrong before auth");
};
if(mifare_ultra_auth1(cuid, dataoutbuf)){
if (MF_DBGLEVEL >= 1) Dbprintf("Authentication part1: Fail.");
}
isOK=1;
if (MF_DBGLEVEL >= 2) DbpString("AUTH 1 FINISHED");
LED_B_ON();
cmd_send(CMD_ACK,isOK,cuid,0,dataoutbuf,11);
LED_B_OFF();
// Thats it...
LEDsoff();
}
void MifareUC_Auth2(uint32_t arg0, uint8_t *datain){
// params
uint32_t cuid = arg0;
uint8_t key[16]={0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
// variables
byte_t isOK = 0;
byte_t dataoutbuf[16];
memcpy(key, datain, 16);
LED_A_ON();
LED_B_OFF();
LED_C_OFF();
if(mifare_ultra_auth2(cuid, key, dataoutbuf)){
if (MF_DBGLEVEL >= 1) Dbprintf("Authentication part2: Fail...");
}
isOK=1;
if (MF_DBGLEVEL >= 2) DbpString("AUTH 2 FINISHED");
LED_B_ON();
cmd_send(CMD_ACK,isOK,0,0,dataoutbuf,11);
LED_B_OFF();
FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
LEDsoff();
}
@ -265,38 +200,37 @@ void MifareReadSector(uint8_t arg0, uint8_t arg1, uint8_t arg2, uint8_t *datain)
LEDsoff();
}
void MifareUReadCard(uint8_t arg0, int arg1, uint8_t *datain)
void MifareUReadCard(uint8_t arg0, uint8_t *datain)
{
// params
uint8_t sectorNo = arg0;
int Pages=arg1;
int count_Pages=0;
// variables
byte_t isOK = 0;
byte_t dataoutbuf[176];
byte_t dataoutbuf[16 * 4];
uint8_t uid[10];
uint32_t cuid;
// clear trace
iso14a_clear_trace();
// iso14a_set_tracing(false);
iso14443a_setup(FPGA_HF_ISO14443A_READER_LISTEN);
LED_A_ON();
LED_B_OFF();
LED_C_OFF();
Dbprintf("Pages %d",Pages);
while (true) {
if(!iso14443a_select_card(uid, NULL, &cuid)) {
if (MF_DBGLEVEL >= 1) Dbprintf("Can't select card");
break;
};
for(int sec=0;sec<Pages;sec++){
for(int sec=0;sec<16;sec++){
if(mifare_ultra_readblock(cuid, sectorNo * 4 + sec, dataoutbuf + 4 * sec)) {
if (MF_DBGLEVEL >= 1) Dbprintf("Read block %d error",sec);
break;
}else{
count_Pages++;
};
}
if(mifare_ultra_halt(cuid)) {
@ -307,13 +241,11 @@ void MifareUReadCard(uint8_t arg0, int arg1, uint8_t *datain)
isOK = 1;
break;
}
Dbprintf("Pages read %d",count_Pages);
if (MF_DBGLEVEL >= 2) DbpString("READ CARD FINISHED");
LED_B_ON();
if (Pages==16) cmd_send(CMD_ACK,isOK,0,0,dataoutbuf,64);
if (Pages==44 && count_Pages==16) cmd_send(CMD_ACK,isOK,0,0,dataoutbuf,64);
if (Pages==44 && count_Pages>16) cmd_send(CMD_ACK,isOK,0,0,dataoutbuf,176);
cmd_send(CMD_ACK,isOK,0,0,dataoutbuf,64);
LED_B_OFF();
// Thats it...
@ -599,7 +531,7 @@ void MifareNested(uint32_t arg0, uint32_t arg1, uint32_t calibrate, uint8_t *dat
};
nttmp = prng_successor(nt1, 100); //NXP Mifare is typical around 840,but for some unlicensed/compatible mifare card this can be 160
for (i = 141; i < 1200; i++) {
for (i = 101; i < 1200; i++) {
nttmp = prng_successor(nttmp, 1);
if (nttmp == nt2) break;
}
@ -636,15 +568,6 @@ void MifareNested(uint32_t arg0, uint32_t arg1, uint32_t calibrate, uint8_t *dat
// get crypted nonces for target sector
for(i=0; i < 2; i++) { // look for exactly two different nonces
WDT_HIT();
if(BUTTON_PRESS()) {
DbpString("Nested: cancelled");
crypto1_destroy(pcs);
FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
LEDsoff();
return;
}
target_nt[i] = 0;
while(target_nt[i] == 0) { // continue until we have an unambiguous nonce
@ -1148,75 +1071,3 @@ void MifareCIdent(){
//
// DESFIRE
//
void Mifare_DES_Auth1(uint8_t arg0, uint8_t *datain){
// variables
byte_t isOK = 0;
byte_t dataoutbuf[16];
uint8_t uid[10];
uint32_t cuid;
// clear trace
iso14a_clear_trace();
iso14443a_setup(FPGA_HF_ISO14443A_READER_LISTEN);
LED_A_ON();
LED_B_OFF();
LED_C_OFF();
if(!iso14443a_select_card(uid, NULL, &cuid)) {
if (MF_DBGLEVEL >= 1) Dbprintf("Can't select card, something went wrong before auth");
};
if(mifare_desfire_des_auth1(cuid, dataoutbuf)){
if (MF_DBGLEVEL >= 1) Dbprintf("Authentication part1: Fail.");
}
isOK=1;
if (MF_DBGLEVEL >= 2) DbpString("AUTH 1 FINISHED");
LED_B_ON();
cmd_send(CMD_ACK,isOK,cuid,0,dataoutbuf,11);
LED_B_OFF();
// Thats it...
//FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
LEDsoff();
}
void Mifare_DES_Auth2(uint32_t arg0, uint8_t *datain){
// params
uint32_t cuid = arg0;
uint8_t key[16]={0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
// variables
byte_t isOK = 0;
byte_t dataoutbuf[16];
memcpy(key, datain, 16);
// clear trace
//iso14a_clear_trace();
//iso14443a_setup(FPGA_HF_ISO14443A_READER_LISTEN);
LED_A_ON();
LED_B_OFF();
LED_C_OFF();
// Dbprintf("Sending %02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x",
// key[0],key[1],key[2],key[3],key[4],key[5],key[6],key[7],key[8],
// key[9],key[10],key[11],key[12],key[13],key[14],key[15]);
if(mifare_desfire_des_auth2(cuid, key, dataoutbuf)){
if (MF_DBGLEVEL >= 1) Dbprintf("Authentication part2: Fail...");
}
isOK=1;
if (MF_DBGLEVEL >= 2) DbpString("AUTH 2 FINISHED");
LED_B_ON();
cmd_send(CMD_ACK,isOK,0,0,dataoutbuf,12);
LED_B_OFF();
// Thats it...
FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
LEDsoff();
}

View file

@ -13,15 +13,16 @@
#ifndef __MIFARECMD_H
#define __MIFARECMD_H
#include "../include/proxmark3.h"
#include "proxmark3.h"
#include "apps.h"
#include "util.h"
#include "string.h"
#include "../common/iso14443crc.h"
#include "iso14443crc.h"
#include "iso14443a.h"
#include "crapto1.h"
#include "mifareutil.h"
#include "../include/common.h"
#include "common.h"
#endif

View file

@ -1,521 +0,0 @@
#include "mifaredesfire.h"
#include "des.h"
#define MAX_APPLICATION_COUNT 28
#define MAX_FILE_COUNT 16
#define MAX_DESFIRE_FRAME_SIZE 60
#define NOT_YET_AUTHENTICATED 255
#define FRAME_PAYLOAD_SIZE (MAX_DESFIRE_FRAME_SIZE - 5)
#define RECEIVE_SIZE 64
// the block number for the ISO14443-4 PCB
uint8_t pcb_blocknum = 0;
// Deselect card by sending a s-block. the crc is precalced for speed
static uint8_t deselect_cmd[] = {0xc2,0xe0,0xb4};
//static uint8_t __msg[MAX_FRAME_SIZE] = { 0x0A, 0x00, 0x00, /* ..., */ 0x00 };
/* PCB CID CMD PAYLOAD */
//static uint8_t __res[MAX_FRAME_SIZE];
bool InitDesfireCard(){
// Make sure it is off.
// FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
// SpinDelay(300);
byte_t cardbuf[USB_CMD_DATA_SIZE];
memset(cardbuf,0,sizeof(cardbuf));
iso14a_card_select_t *card = (iso14a_card_select_t*)cardbuf;
iso14a_set_tracing(TRUE);
iso14443a_setup(FPGA_HF_ISO14443A_READER_LISTEN);
int len = iso14443a_select_card(NULL,card,NULL);
if (!len) {
if (MF_DBGLEVEL >= 1) Dbprintf("Can't select card");
OnError();
return false;
}
return true;
}
// ARG0 flag enums
enum {
NONE = 0x00,
INIT = 0x01,
DISCONNECT = 0x02,
CLEARTRACE = 0x04,
BAR = 0x08,
} CmdOptions ;
void MifareSendCommand(uint8_t arg0, uint8_t arg1, uint8_t *datain){
/* ARG0 contains flags.
0x01 = init card.
0x02 = Disconnect
0x03
*/
uint8_t flags = arg0;
size_t datalen = arg1;
uint8_t resp[RECEIVE_SIZE];
memset(resp,0,sizeof(resp));
if (MF_DBGLEVEL >= 4) {
Dbprintf(" flags : %02X", flags);
Dbprintf(" len : %02X", datalen);
print_result(" RX : ", datain, datalen);
}
if ( flags & CLEARTRACE ){
iso14a_clear_trace();
}
if ( flags & INIT ){
if ( !InitDesfireCard() )
return;
}
int len = DesfireAPDU(datain, datalen, resp);
if (MF_DBGLEVEL >= 4) {
print_result("ERR <--: ", resp, len);
}
if ( !len ) {
OnError();
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];
uint8_t dataout[USB_CMD_DATA_SIZE];
byte_t cardbuf[USB_CMD_DATA_SIZE];
memset(resp,0,sizeof(resp));
memset(dataout,0, sizeof(dataout));
memset(cardbuf,0,sizeof(cardbuf));
/*
1 = PCB 1
2 = cid 2
3 = desfire command 3
4-5 = crc 4 key
5-6 crc
PCB == 0x0A because sending CID byte.
CID == 0x00 first card?
*/
iso14a_clear_trace();
iso14a_set_tracing(TRUE);
iso14443a_setup(FPGA_HF_ISO14443A_READER_LISTEN);
// card select - information
iso14a_card_select_t *card = (iso14a_card_select_t*)cardbuf;
byte_t isOK = iso14443a_select_card(NULL, card, NULL);
if ( isOK == 0) {
if (MF_DBGLEVEL >= 1) {
Dbprintf("Can't select card");
}
OnError();
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();
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();
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();
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* bigbuffer = get_bigbufptr_recvrespbuf();
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();
LED_A_ON();
LED_B_OFF();
LED_C_OFF();
// 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];
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 >= 1) {
DbpString("Authentication failed. Card timeout.");
}
OnError();
return;
}
if ( resp[2] == 0xaf ){
} else {
DbpString("Authetication failed. Invalid key number.");
OnError();
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 >= 1) {
DbpString("Authentication failed. Card timeout.");
}
OnError();
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();
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();
return;
}
}
}
break;
case 2:
//SendDesfireCommand(AUTHENTICATE_ISO, &keyno, resp);
break;
case 3:{
//defaultkey
uint8_t keybytes[16];
if (datain[1] == 0xff){
memcpy(keybytes,PICC_MASTER_KEY16,16);
} else{
memcpy(keybytes, datain+1, datalen);
}
struct desfire_key defaultkey = {0};
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();
return;
}
cmd[0] = AUTHENTICATE_AES;
cmd[1] = 0x00; //keynumber
len = DesfireAPDU(cmd, 2, resp);
if ( !len ) {
if (MF_DBGLEVEL >= 1) {
DbpString("Authentication failed. Card timeout.");
}
OnError();
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 >= 1) {
DbpString("Authentication failed. Card timeout.");
}
OnError();
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();
return;
}
break;
}
}
OnSuccess();
cmd_send(CMD_ACK,1,len,0,resp,len);
}
// 3 olika ISO sätt att skicka data till DESFIRE (direkt, inkapslat, inkapslat ISO)
// cmd = cmd bytes to send
// cmd_len = length of cmd
// dataout = pointer to response data array
int DesfireAPDU(uint8_t *cmd, size_t cmd_len, uint8_t *dataout){
size_t len = 0;
size_t wrappedLen = 0;
uint8_t wCmd[USB_CMD_DATA_SIZE] = {0};
uint8_t *resp = ((uint8_t *)BigBuf) + RECV_RESP_OFFSET;
uint8_t *resp_par = ((uint8_t *)BigBuf) + RECV_RESP_PAR_OFFSET;
wrappedLen = CreateAPDU( cmd, cmd_len, wCmd);
if (MF_DBGLEVEL >= 4) {
print_result("WCMD <--: ", wCmd, wrappedLen);
}
ReaderTransmit( wCmd, wrappedLen, NULL);
len = ReaderReceive(resp, resp_par);
if( len == 0x00 ){
if (MF_DBGLEVEL >= 4) {
Dbprintf("fukked");
}
return FALSE; //DATA LINK ERROR
}
// if we received an I- or R(ACK)-Block with a block number equal to the
// current block number, toggle the current block number
else if (len >= 4 // PCB+CID+CRC = 4 bytes
&& ((resp[0] & 0xC0) == 0 // I-Block
|| (resp[0] & 0xD0) == 0x80) // R-Block with ACK bit set to 0
&& (resp[0] & 0x01) == pcb_blocknum) // equal block numbers
{
pcb_blocknum ^= 1; //toggle next block
}
memcpy(dataout, resp, len);
return len;
}
// CreateAPDU
size_t CreateAPDU( uint8_t *datain, size_t len, uint8_t *dataout){
size_t cmdlen = MIN(len+4, USB_CMD_DATA_SIZE-1);
uint8_t cmd[cmdlen];
memset(cmd, 0, cmdlen);
cmd[0] = 0x0A; // 0x0A = skicka cid, 0x02 = ingen cid. Särskilda bitar //
cmd[0] |= pcb_blocknum; // OR the block number into the PCB
cmd[1] = 0x00; // CID: 0x00 //TODO: allow multiple selected cards
memcpy(cmd+2, datain, len);
AppendCrc14443a(cmd, len+2);
memcpy(dataout, cmd, cmdlen);
return cmdlen;
}
// crc_update(&desfire_crc32, 0, 1); /* CMD_WRITE */
// crc_update(&desfire_crc32, addr, addr_sz);
// crc_update(&desfire_crc32, byte, 8);
// uint32_t crc = crc_finish(&desfire_crc32);
void OnSuccess(){
pcb_blocknum = 0;
ReaderTransmit(deselect_cmd, 3 , NULL);
FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
LEDsoff();
}
void OnError(){
pcb_blocknum = 0;
ReaderTransmit(deselect_cmd, 3 , NULL);
FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
cmd_send(CMD_ACK,0,0,0,0,0);
LEDsoff();
}

View file

@ -1,15 +0,0 @@
#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

View file

@ -11,16 +11,16 @@
#ifndef __MIFARESNIFF_H
#define __MIFARESNIFF_H
#include "../include/proxmark3.h"
#include "proxmark3.h"
#include "apps.h"
#include "util.h"
#include "string.h"
#include "../common/iso14443crc.h"
#include "iso14443crc.h"
#include "iso14443a.h"
#include "crapto1.h"
#include "mifareutil.h"
#include "../include/common.h"
#include "common.h"
#define SNF_INIT 0
#define SNF_NO_FIELD 1

View file

@ -9,12 +9,12 @@
// Work with mifare cards.
//-----------------------------------------------------------------------------
#include "../include/proxmark3.h"
#include "proxmark3.h"
#include "apps.h"
#include "util.h"
#include "string.h"
#include "../common/iso14443crc.h"
#include "iso14443crc.h"
#include "iso14443a.h"
#include "crapto1.h"
#include "mifareutil.h"
@ -93,34 +93,14 @@ int mifare_sendcmd_short_special(struct Crypto1State *pcs, uint8_t crypted, uint
AppendCrc14443a(dcmd, 6);
ReaderTransmit(dcmd, sizeof(dcmd), NULL);
int len = ReaderReceive(answer, answer_parity);
if(!len) {
if(!len)
{
if (MF_DBGLEVEL >= 1) Dbprintf("Authentication failed. Card timeout.");
return 2;
}
return len;
}
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)
{
uint8_t dcmd[19];
int len;
dcmd[0] = cmd;
memcpy(dcmd+1,data,16);
AppendCrc14443a(dcmd, 17);
ReaderTransmit(dcmd, sizeof(dcmd), timing);
len = ReaderReceive(answer, answer_parity);
if(!len) {
if (MF_DBGLEVEL >= 1) Dbprintf("Authentication failed. Card timeout.");
len = ReaderReceive(answer,answer_parity);
}
if(len==1) {
if (MF_DBGLEVEL >= 1) Dbprintf("NAK - Authentication failed.");
return 1;
}
return len;
}
int mifare_sendcmd_shortex(struct Crypto1State *pcs, uint8_t crypted, uint8_t cmd, uint8_t data, uint8_t *answer, uint8_t *answer_parity, uint32_t *timing)
{
uint8_t dcmd[4], ecmd[4];
@ -298,56 +278,6 @@ int mifare_classic_readblock(struct Crypto1State *pcs, uint32_t uid, uint8_t blo
return 0;
}
int mifare_ultra_auth1(uint32_t uid, uint8_t *blockData){
// variables
uint16_t len;
uint8_t* receivedAnswer = get_bigbufptr_recvrespbuf();
uint8_t* receivedAnswerPar = receivedAnswer + MAX_FRAME_SIZE;
// command MIFARE_CLASSIC_READBLOCK
len = mifare_sendcmd_short(NULL, 1, 0x1A, 0x00, receivedAnswer,receivedAnswerPar ,NULL);
if (len == 1) {
if (MF_DBGLEVEL >= 1) Dbprintf("Cmd Error: %02x", receivedAnswer[0]);
return 1;
}
if (len == 11) {
if (MF_DBGLEVEL >= 1) Dbprintf("Auth1 Resp: %02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x",
receivedAnswer[0],receivedAnswer[1],receivedAnswer[2],receivedAnswer[3],receivedAnswer[4],
receivedAnswer[5],receivedAnswer[6],receivedAnswer[7],receivedAnswer[8],receivedAnswer[9],
receivedAnswer[10]);
memcpy(blockData, receivedAnswer, 11);
return 0;
}
//else something went wrong???
return 1;
}
int mifare_ultra_auth2(uint32_t uid, uint8_t *key, uint8_t *blockData){
// variables
uint16_t len;
uint8_t* receivedAnswer = get_bigbufptr_recvrespbuf();
uint8_t* receivedAnswerPar = receivedAnswer + MAX_FRAME_SIZE;
// command MIFARE_CLASSIC_READBLOCK
len = mifare_sendcmd_short_mfucauth(NULL, 1, 0xAF, key, receivedAnswer, receivedAnswerPar, NULL);
if (len == 1) {
if (MF_DBGLEVEL >= 1) Dbprintf("Cmd Error: %02x", receivedAnswer[0]);
return 1;
}
if (len == 11){
if (MF_DBGLEVEL >= 1) Dbprintf("Auth2 Resp: %02x%02x%02x%02x%02x%02x%02x%02x%02x%02x",
receivedAnswer[0],receivedAnswer[1],receivedAnswer[2],receivedAnswer[3],receivedAnswer[4],
receivedAnswer[5],receivedAnswer[6],receivedAnswer[7],receivedAnswer[8],receivedAnswer[9],
receivedAnswer[10]);
memcpy(blockData, receivedAnswer, 11);
return 0;
}
//something went wrong?
return 1;
}
int mifare_ultra_readblock(uint32_t uid, uint8_t blockNo, uint8_t *blockData)
{
// variables
@ -623,91 +553,3 @@ void emlClearMem(void) {
emlSetMem((uint8_t *)uid, 0, 1);
return;
}
//
//DESFIRE
//
int mifare_sendcmd_special(struct Crypto1State *pcs, uint8_t crypted, uint8_t cmd, uint8_t* data, uint8_t* answer, uint8_t *answer_parity, uint32_t *timing)
{
uint8_t dcmd[5] = {0x00};
dcmd[0] = cmd;
memcpy(dcmd+1,data,2);
AppendCrc14443a(dcmd, 3);
ReaderTransmit(dcmd, sizeof(dcmd), NULL);
int len = ReaderReceive(answer, answer_parity);
if(!len) {
if (MF_DBGLEVEL >= 1) Dbprintf("Authentication failed. Card timeout.");
return 2;
}
return len;
}
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)
{
uint8_t dcmd[20] = {0x00};
dcmd[0] = cmd;
memcpy(dcmd+1,data,17);
AppendCrc14443a(dcmd, 18);
ReaderTransmit(dcmd, sizeof(dcmd), NULL);
int len = ReaderReceive(answer, answer_parity);
if(!len){
if (MF_DBGLEVEL >= 1) Dbprintf("Authentication failed. Card timeout.");
return 2;
}
return len;
}
int mifare_desfire_des_auth1(uint32_t uid, uint8_t *blockData){
// variables
int len;
// load key, keynumber
uint8_t data[2]={0x0a, 0x00};
uint8_t* receivedAnswer = get_bigbufptr_recvrespbuf();
uint8_t *receivedAnswerPar = receivedAnswer + MAX_FRAME_SIZE;
// command MIFARE_CLASSIC_READBLOCK
len = mifare_sendcmd_special(NULL, 1, 0x02, data, receivedAnswer,receivedAnswerPar,NULL);
if (len == 1) {
if (MF_DBGLEVEL >= 1) Dbprintf("Cmd Error: %02x", receivedAnswer[0]);
return 1;
}
if (len == 12) {
if (MF_DBGLEVEL >= 1) Dbprintf("Auth1 Resp: %02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x",
receivedAnswer[0],receivedAnswer[1],receivedAnswer[2],receivedAnswer[3],receivedAnswer[4],
receivedAnswer[5],receivedAnswer[6],receivedAnswer[7],receivedAnswer[8],receivedAnswer[9],
receivedAnswer[10],receivedAnswer[11]);
memcpy(blockData, receivedAnswer, 12);
return 0;
}
return 1;
}
int mifare_desfire_des_auth2(uint32_t uid, uint8_t *key, uint8_t *blockData){
// variables
int len;
uint8_t data[17]={0xaf,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
memcpy(data+1,key,16);
uint8_t* receivedAnswer = get_bigbufptr_recvrespbuf();
uint8_t *receivedAnswerPar = receivedAnswer + MAX_FRAME_SIZE;
// command MIFARE_CLASSIC_READBLOCK
len = mifare_sendcmd_special2(NULL, 1, 0x03, data, receivedAnswer, receivedAnswerPar ,NULL);
if ((receivedAnswer[0] == 0x03)&&(receivedAnswer[1] == 0xae)) {
if (MF_DBGLEVEL >= 1) Dbprintf("Auth Error: %02x %02x", receivedAnswer[0], receivedAnswer[1]);
return 1;
}
if (len == 12){
if (MF_DBGLEVEL >= 1) Dbprintf("Auth2 Resp: %02x%02x%02x%02x%02x%02x%02x%02x%02x%02x",
receivedAnswer[0],receivedAnswer[1],receivedAnswer[2],receivedAnswer[3],receivedAnswer[4],
receivedAnswer[5],receivedAnswer[6],receivedAnswer[7],receivedAnswer[8],receivedAnswer[9],
receivedAnswer[10],receivedAnswer[11]);
memcpy(blockData, receivedAnswer, 12);
return 0;
}
return 1;
}

View file

@ -56,15 +56,11 @@ extern int MF_DBGLEVEL;
uint8_t* mifare_get_bigbufptr(void);
int mifare_sendcmd_short(struct Crypto1State *pcs, uint8_t crypted, uint8_t cmd, uint8_t data, uint8_t* answer, uint8_t *answer_parity, uint32_t *timing);
int mifare_sendcmd_short_special(struct Crypto1State *pcs, uint8_t crypted, uint8_t cmd, uint8_t *data, uint8_t* answer, uint8_t *answer_parity, uint32_t *timing);
int mifare_sendcmd_short_mfucauth(struct Crypto1State *pcs, uint8_t crypted, uint8_t cmd, uint8_t *data, uint8_t *answer, uint8_t *answer_parity, uint32_t *timing);
int mifare_sendcmd_shortex(struct Crypto1State *pcs, uint8_t crypted, uint8_t cmd, uint8_t data, uint8_t* answer, uint8_t *answer_parity, uint32_t *timing);
int mifare_classic_auth(struct Crypto1State *pcs, uint32_t uid, uint8_t blockNo, uint8_t keyType, uint64_t ui64Key, uint8_t isNested);
int mifare_classic_authex(struct Crypto1State *pcs, uint32_t uid, uint8_t blockNo, uint8_t keyType, uint64_t ui64Key, uint8_t isNested, uint32_t * ntptr, uint32_t *timing);
int mifare_classic_readblock(struct Crypto1State *pcs, uint32_t uid, uint8_t blockNo, uint8_t *blockData);
int mifare_ultra_auth1(uint32_t cuid, uint8_t *blockData);
int mifare_ultra_auth2(uint32_t cuid, uint8_t *key, uint8_t *blockData);
int mifare_ultra_readblock(uint32_t uid, uint8_t blockNo, uint8_t *blockData);
int mifare_classic_writeblock(struct Crypto1State *pcs, uint32_t uid, uint8_t blockNo, uint8_t *blockData);
int mifare_ultra_writeblock(uint32_t uid, uint8_t blockNo, uint8_t *blockData);
@ -72,12 +68,6 @@ int mifare_ultra_special_writeblock(uint32_t uid, uint8_t blockNo, uint8_t *bloc
int mifare_classic_halt(struct Crypto1State *pcs, uint32_t uid);
int mifare_ultra_halt(uint32_t uid);
// desfire
int mifare_sendcmd_special(struct Crypto1State *pcs, uint8_t crypted, uint8_t cmd, uint8_t* data, uint8_t* answer, uint8_t *answer_parity, uint32_t *timing);
int mifare_sendcmd_special2(struct Crypto1State *pcs, uint8_t crypted, uint8_t cmd, uint8_t* data, uint8_t* answer,uint8_t *answer_parity, uint32_t *timing);
int mifare_desfire_des_auth1(uint32_t uid, uint8_t *blockData);
int mifare_desfire_des_auth2(uint32_t uid, uint8_t *key, uint8_t *blockData);
// crypto functions
void mf_crypto1_decrypt(struct Crypto1State *pcs, uint8_t *receivedCmd, int len);
void mf_crypto1_encrypt(struct Crypto1State *pcs, uint8_t *data, uint16_t len, uint8_t *par);

View file

@ -9,7 +9,7 @@
// with the linker script.
//-----------------------------------------------------------------------------
#include "../include/proxmark3.h"
#include "proxmark3.h"
#include "apps.h"
extern char __data_start__, __data_src_start__, __data_end__, __bss_start__, __bss_end__;

View file

@ -48,11 +48,6 @@ int memcmp(const void *av, const void *bv, int len)
return 0;
}
void memxor(uint8_t * dest, uint8_t * src, size_t len) {
for( ; len > 0; len--,dest++,src++)
*dest ^= *src;
}
int strlen(const char *str)
{
int l = 0;

View file

@ -12,14 +12,10 @@
#ifndef __STRING_H
#define __STRING_H
#include <stdint.h>
#include <util.h>
int strlen(const char *str);
RAMFUNC void *memcpy(void *dest, const void *src, int len);
void *memcpy(void *dest, const void *src, int len);
void *memset(void *dest, int c, int len);
RAMFUNC int memcmp(const void *av, const void *bv, int len);
void memxor(uint8_t * dest, uint8_t * src, size_t len);
int memcmp(const void *av, const void *bv, int len);
char *strncat(char *dest, const char *src, unsigned int n);
char *strcat(char *dest, const char *src);
void strreverse(char s[]);

View file

@ -8,31 +8,11 @@
// Utility functions used in many places, not specific to any piece of code.
//-----------------------------------------------------------------------------
#include "../include/proxmark3.h"
#include "proxmark3.h"
#include "util.h"
#include "string.h"
#include "apps.h"
void print_result(char *name, uint8_t *buf, size_t len) {
uint8_t *p = buf;
if ( len % 16 == 0 ) {
for(; p-buf < len; p += 16)
Dbprintf("[%s:%d/%d] %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x",
name,
p-buf,
len,
p[0], p[1], p[2], p[3], p[4], p[5], p[6], p[7],p[8], p[9], p[10], p[11], p[12], p[13], p[14], p[15]
);
}
else {
for(; p-buf < len; p += 8)
Dbprintf("[%s:%d/%d] %02x %02x %02x %02x %02x %02x %02x %02x", name, p-buf, len, p[0], p[1], p[2], p[3], p[4], p[5], p[6], p[7]);
}
}
size_t nbytes(size_t nbits) {
return (nbits/8)+((nbits%8)>0);
}
@ -65,26 +45,6 @@ uint64_t bytes_to_num(uint8_t* src, size_t len)
return num;
}
// RotateLeft - Ultralight, Desfire
void rol(uint8_t *data, const size_t len){
uint8_t first = data[0];
for (size_t i = 0; i < len-1; i++) {
data[i] = data[i+1];
}
data[len-1] = first;
}
void lsl (uint8_t *data, size_t len) {
for (size_t n = 0; n < len - 1; n++) {
data[n] = (data[n] << 1) | (data[n+1] >> 7);
}
data[len - 1] <<= 1;
}
int32_t le24toh (uint8_t data[3])
{
return (data[2] << 16) | (data[1] << 8) | data[0];
}
void LEDsoff()
{
LED_A_OFF();

View file

@ -13,7 +13,7 @@
#include <stddef.h>
#include <stdint.h>
#include "../include/common.h"
#include <common.h>
#define BYTEx(x, n) (((x) >> (n * 8)) & 0xff )
@ -27,14 +27,10 @@
#define BUTTON_DOUBLE_CLICK -2
#define BUTTON_ERROR -99
void print_result(char *name, uint8_t *buf, size_t len);
size_t nbytes(size_t nbits);
uint32_t SwapBits(uint32_t value, int nrbits);
void num_to_bytes(uint64_t n, size_t len, uint8_t* dest);
uint64_t bytes_to_num(uint8_t* src, size_t len);
void rol(uint8_t *data, const size_t len);
void lsl (uint8_t *data, size_t len);
int32_t le24toh (uint8_t data[3]);
void SpinDelay(int ms);
void SpinDelayUs(int us);

View file

@ -13,14 +13,14 @@ CXX=g++
VPATH = ../common
OBJDIR = obj
LDLIBS = -L/mingw/lib -L/opt/local/lib -L/usr/local/lib ../liblua/liblua.a -lm -lreadline -lpthread -lcrypto -lgdi32
LDLIBS = -L/opt/local/lib -L/usr/local/lib -lreadline -lpthread ../liblua/liblua.a
LDFLAGS = $(COMMON_FLAGS)
CFLAGS = -std=c99 -I. -I../include -I../common -I/mingw/include -I/opt/local/include -I../liblua -Wall $(COMMON_FLAGS) -g -O4 $(ICE_FLAGS)
CFLAGS = -std=c99 -lcrypto -I. -I../include -I../common -I/opt/local/include -I../liblua -Wall $(COMMON_FLAGS) -g -O4
LUAPLATFORM = generic
ifneq (,$(findstring MINGW,$(platform)))
CXXFLAGS = -I$(QTDIR)/include -I$(QTDIR)/include/QtCore -I$(QTDIR)/include/QtGui -I$(QTDIR)/include/QtWidgets -I/mingw/include
QTLDLIBS = -L$(QTDIR)/lib -lQt5Core -lQt5Gui -lQt5Widgets
CXXFLAGS = -I$(QTDIR)/include -I$(QTDIR)/include/QtCore -I$(QTDIR)/include/QtGui
QTLDLIBS = -L$(QTDIR)/lib -lQtCore4 -lQtGui4
MOC = $(QTDIR)/bin/moc
LUAPLATFORM = mingw
else ifeq ($(platform),Darwin)
@ -62,7 +62,6 @@ CMDSRCS = nonce2key/crapto1.c\
loclass/ikeys.c \
loclass/elite_crack.c\
loclass/fileutils.c\
loclass/hash1_brute.c \
mifarehost.c\
crc16.c \
iso14443crc.c \
@ -80,12 +79,8 @@ CMDSRCS = nonce2key/crapto1.c\
cmdhflegic.c \
cmdhficlass.c \
cmdhfmf.c \
cmdhfmfu.c \
cmdhfmfdes.c \
cmdhfdes.c \
cmdhw.c \
cmdlf.c \
cmdlfawid26.c \
cmdlfio.c \
cmdlfhid.c \
cmdlfem4x.c \

View file

@ -29,11 +29,15 @@ int CmdAmp(const char *Cmd)
int i, rising, falling;
int max = INT_MIN, min = INT_MAX;
DetectHighLowInGraph( &max, &min, FALSE);
for (i = 10; i < GraphTraceLen; ++i) {
if (GraphBuffer[i] > max)
max = GraphBuffer[i];
if (GraphBuffer[i] < min)
min = GraphBuffer[i];
}
if (max != min) {
rising = falling= 0;
for (i = 0; i < GraphTraceLen; ++i) {
if (GraphBuffer[i + 1] < GraphBuffer[i]) {
if (rising) {
@ -72,25 +76,31 @@ int Cmdaskdemod(const char *Cmd)
int i;
int c, high = 0, low = 0;
// TODO: complain if we do not give 2 arguments here !
// (AL - this doesn't make sense! we're only using one argument!!!)
sscanf(Cmd, "%i", &c);
/* Detect high and lows and clock */
// (AL - clock???)
for (i = 0; i < GraphTraceLen; ++i)
{
if (GraphBuffer[i] > high)
high = GraphBuffer[i];
else if (GraphBuffer[i] < low)
low = GraphBuffer[i];
}
high=abs(high*.75);
low=abs(low*.75);
if (c != 0 && c != 1) {
PrintAndLog("Invalid argument: %s", Cmd);
return 0;
}
DetectHighLowInGraph( &high, &low, FALSE);
high = abs(high * .75);
low = abs(low * .75);
//prime loop
if (GraphBuffer[0] > 0) {
GraphBuffer[0] = 1-c;
} else {
GraphBuffer[0] = c;
}
for (i = 1; i < GraphTraceLen; ++i) {
/* Transitions are detected at each peak
* Transitions are either:
@ -114,59 +124,52 @@ int Cmdaskdemod(const char *Cmd)
return 0;
}
void printBitStream(uint8_t bits[], uint32_t bitLen){
//by marshmellow
void printBitStream(uint8_t BitStream[], uint32_t bitLen)
{
uint32_t i = 0;
if (bitLen<16) {
PrintAndLog("Too few bits found: %d",bitLen);
return;
}
if (bitLen > 512)
bitLen = 512;
if ( ( bitLen % 16 ) > 0) {
bitLen = ((bitLen / 16) * 16);
PrintAndLog("ICE: equally divided with 16 = %d",bitLen);
}
if (bitLen>512) bitLen=512;
for (i = 0; i <= (bitLen-16); i+=16) {
PrintAndLog("%i%i%i%i%i%i%i%i%i%i%i%i%i%i%i%i",
bits[i],
bits[i+1],
bits[i+2],
bits[i+3],
bits[i+4],
bits[i+5],
bits[i+6],
bits[i+7],
bits[i+8],
bits[i+9],
bits[i+10],
bits[i+11],
bits[i+12],
bits[i+13],
bits[i+14],
bits[i+15]);
BitStream[i],
BitStream[i+1],
BitStream[i+2],
BitStream[i+3],
BitStream[i+4],
BitStream[i+5],
BitStream[i+6],
BitStream[i+7],
BitStream[i+8],
BitStream[i+9],
BitStream[i+10],
BitStream[i+11],
BitStream[i+12],
BitStream[i+13],
BitStream[i+14],
BitStream[i+15]);
}
return;
}
void printEM410x(uint64_t id) {
if ( id <= 0 ) return;
uint64_t id2lo = 0;
uint32_t i,j;
i = j = 0;
for (j = 5; j > 0; j--){
//by marshmellow
void printEM410x(uint64_t id)
{
if (id !=0){
uint64_t iii=1;
uint64_t id2lo=0; //id2hi=0,
uint32_t ii=0;
uint32_t i=0;
for (ii=5; ii>0;ii--){
for (i=0;i<8;i++){
id2lo = ( id2lo << 1LL)|((id & ( 1 << ( i +( ( j-1 ) * 8 )))) >> ( i + (( j-1) *8 )));
id2lo=(id2lo<<1LL)|((id & (iii<<(i+((ii-1)*8))))>>(i+((ii-1)*8)));
}
}
//output em id
PrintAndLog("EM TAG ID : %010llx", id);
PrintAndLog("Unique TAG ID: %010llx", id2lo);
PrintAndLog("Unique TAG ID: %010llx", id2lo); //id2hi,
PrintAndLog("DEZ 8 : %08lld",id & 0xFFFFFF);
PrintAndLog("DEZ 10 : %010lld",id & 0xFFFFFF);
PrintAndLog("DEZ 5.5 : %05lld.%05lld",(id>>16LL) & 0xFFFF,(id & 0xFFFF));
@ -175,19 +178,23 @@ void printEM410x(uint64_t id) {
PrintAndLog("DEZ 15/IK3 : %015lld",id2lo);
PrintAndLog("Other : %05lld_%03lld_%08lld",(id&0xFFFF),((id>>16LL) & 0xFF),(id & 0xFFFFFF));
}
return;
}
//by marshmellow
int CmdEm410xDecode(const char *Cmd)
{
uint64_t id=0;
uint8_t bits[MAX_GRAPH_TRACE_LEN] = {0x00};
uint32_t len = GetFromGraphBuf(bits);
id = Em410xDecode(bits, len);
uint8_t BitStream[MAX_GRAPH_TRACE_LEN]={0};
uint32_t i=0;
i=getFromGraphBuf(BitStream);
id = Em410xDecode(BitStream,i);
printEM410x(id);
if ( id > 0 )
return 1;
if (id>0) return 1;
return 0;
}
//by marshmellow
//takes 2 arguments - clock and invert both as integers
//attempts to demodulate ask while decoding manchester
@ -196,39 +203,40 @@ int Cmdaskmandemod(const char *Cmd)
{
int invert=0;
int clk=0;
uint8_t BitStream[MAX_GRAPH_TRACE_LEN]={0};
sscanf(Cmd, "%i %i", &clk, &invert);
if (invert != 0 && invert != 1) {
PrintAndLog("Invalid argument: %s", Cmd);
return 0;
}
uint32_t BitLen = getFromGraphBuf(BitStream);
// PrintAndLog("DEBUG: Bitlen from grphbuff: %d",BitLen);
int errCnt=0;
errCnt = askmandemod(BitStream, &BitLen,&clk,&invert);
if (errCnt<0){ //if fatal error (or -1)
// PrintAndLog("no data found %d, errors:%d, bitlen:%d, clock:%d",errCnt,invert,BitLen,clk);
return 0;
}
if (BitLen<16) return 0;
PrintAndLog("\nUsing Clock: %d - Invert: %d - Bits Found: %d",clk,invert,BitLen);
uint8_t bits[MAX_GRAPH_TRACE_LEN] = {0x00};
uint32_t len = GetFromGraphBuf(bits);
int errCnt = askmandemod(bits, &len, &clk, &invert);
if (errCnt < 0) return 0;
if (len < 16) return 0;
PrintAndLog("\nUsing Clock: %d - Invert: %d - Bits Found: %d",clk,invert,len);
//output
if (errCnt>0){
PrintAndLog("# Errors during Demoding (shown as 77 in bit stream): %d",errCnt);
}
PrintAndLog("ASK/Manchester decoded bitstream:");
printBitStream(bits, len);
uint64_t tagid = Em410xDecode(bits, len);
if (tagid > 0){
SetGraphBuf(bits, len);
printEM410x(tagid);
// Now output the bitstream to the scrollback by line of 16 bits
printBitStream(BitStream,BitLen);
uint64_t lo =0;
lo = Em410xDecode(BitStream,BitLen);
if (lo>0){
//set GraphBuffer for clone or sim command
setGraphBuf(BitStream,BitLen);
PrintAndLog("EM410x pattern found: ");
printEM410x(lo);
return 1;
}
//if (BitLen>16) return 1;
return 0;
}
@ -240,36 +248,35 @@ int Cmdmandecoderaw(const char *Cmd)
int i =0;
int errCnt=0;
int bitnum=0;
uint8_t bits[MAX_GRAPH_TRACE_LEN] = {0x00};
uint8_t BitStream[MAX_GRAPH_TRACE_LEN]={0};
int high=0,low=0;
for (;i<GraphTraceLen;++i){
if (GraphBuffer[i]>high) high=GraphBuffer[i];
else if(GraphBuffer[i]<low) low=GraphBuffer[i];
bits[i] = GraphBuffer[i];
BitStream[i]=GraphBuffer[i];
}
if (high>1 || low <0 ){
PrintAndLog("Error: please raw demod the wave first then mancheseter raw decode");
return 0;
}
bitnum=i;
errCnt = manrawdecode(bits, &bitnum);
errCnt=manrawdecode(BitStream,&bitnum);
if (errCnt>=20){
PrintAndLog("Too many errors: %d",errCnt);
return 0;
}
PrintAndLog("Manchester Decoded - # errors:%d - data:",errCnt);
printBitStream(bits,bitnum);
printBitStream(BitStream,bitnum);
if (errCnt==0){
//put back in graphbuffer
SetGraphBuf(bits, bitnum);
uint64_t id = Em410xDecode(bits,i);
ClearGraph(0);
for (i=0; i<bitnum;++i){
GraphBuffer[i]=BitStream[i];
}
GraphTraceLen=bitnum;
RepaintGraphWindow();
uint64_t id = 0;
id = Em410xDecode(BitStream,i);
printEM410x(id);
}
return 1;
@ -292,27 +299,25 @@ int CmdBiphaseDecodeRaw(const char *Cmd)
int offset=0;
int high=0, low=0;
sscanf(Cmd, "%i", &offset);
uint8_t bits[MAX_GRAPH_TRACE_LEN]={0};
uint8_t BitStream[MAX_GRAPH_TRACE_LEN]={0};
//get graphbuffer & high and low
for (;i<GraphTraceLen;++i){
if(GraphBuffer[i]>high)high=GraphBuffer[i];
else if(GraphBuffer[i]<low)low=GraphBuffer[i];
bits[i] = GraphBuffer[i];
BitStream[i]=GraphBuffer[i];
}
if (high>1 || low <0){
PrintAndLog("Error: please raw demod the wave first then decode");
return 0;
}
bitnum=i;
errCnt = BiphaseRawDecode(bits, &bitnum, offset);
errCnt=BiphaseRawDecode(BitStream,&bitnum, offset);
if (errCnt>=20){
PrintAndLog("Too many errors attempting to decode: %d",errCnt);
return 0;
}
PrintAndLog("Biphase Decoded using offset: %d - # errors:%d - data:",offset,errCnt);
printBitStream(bits, bitnum);
printBitStream(BitStream,bitnum);
PrintAndLog("\nif bitstream does not look right try offset=1");
return 1;
}
@ -324,39 +329,27 @@ int CmdBiphaseDecodeRaw(const char *Cmd)
//prints binary found and saves in graphbuffer for further commands
int Cmdaskrawdemod(const char *Cmd)
{
int invert=0;
int clk=0;
uint8_t BitStream[MAX_GRAPH_TRACE_LEN]={0};
sscanf(Cmd, "%i %i", &clk, &invert);
if (invert != 0 && invert != 1) {
PrintAndLog("Invalid argument: %s", Cmd);
return 0;
}
if ( clock < 0 ) {
PrintAndLog("Wrong clock argument");
return 0;
}
uint8_t bits[MAX_GRAPH_TRACE_LEN] = {0x00};
int len = GetFromGraphBuf(bits);
int BitLen = getFromGraphBuf(BitStream);
int errCnt=0;
errCnt = askrawdemod(bits, &len, &clk, &invert);
//throw away static - allow 1 and -1 (in case of threshold command first)
if (errCnt == -1) {
errCnt = askrawdemod(BitStream, &BitLen, &clk, &invert);
if (errCnt==-1){ //throw away static - allow 1 and -1 (in case of threshold command first)
PrintAndLog("no data found");
return 0;
}
if (len < 16) return 0;
PrintAndLog("Using Clock: %d - invert: %d - Bits Found: %d",clk,invert,len);
if (BitLen<16) return 0;
PrintAndLog("Using Clock: %d - invert: %d - Bits Found: %d",clk,invert,BitLen);
//PrintAndLog("Data start pos:%d, lastBit:%d, stop pos:%d, numBits:%d",iii,lastBit,i,bitnum);
//move BitStream back to GraphBuffer
SetGraphBuf(bits, len);
setGraphBuf(BitStream, BitLen);
if (errCnt>0){
PrintAndLog("# Errors during Demoding (shown as 77 in bit stream): %d",errCnt);
@ -365,7 +358,8 @@ int Cmdaskrawdemod(const char *Cmd)
PrintAndLog("ASK demoded bitstream:");
// Now output the bitstream to the scrollback by line of 16 bits
printBitStream(bits,len);
printBitStream(BitStream,BitLen);
return 1;
}
@ -404,7 +398,7 @@ int CmdAutoCorr(const char *Cmd)
int CmdBitsamples(const char *Cmd)
{
int cnt = 0;
uint8_t got[10000];
uint8_t got[12288];
GetFromBigBuf(got,sizeof(got),0);
WaitForResponse(CMD_ACK,NULL);
@ -437,10 +431,16 @@ int CmdBitstream(const char *Cmd)
int hithigh, hitlow, first;
/* Detect high and lows and clock */
DetectHighLowInGraph( &high, &low, FALSE);
for (i = 0; i < GraphTraceLen; ++i)
{
if (GraphBuffer[i] > high)
high = GraphBuffer[i];
else if (GraphBuffer[i] < low)
low = GraphBuffer[i];
}
/* Get our clock */
clock = GetClock(Cmd, 0);
clock = GetClock(Cmd, high, 1);
gtl = ClearGraph(0);
bit = 0;
@ -500,7 +500,7 @@ int CmdDec(const char *Cmd)
// uses data from graphbuffer
int CmdDetectClockRate(const char *Cmd)
{
GetClock("",1);
GetClock("",0,0);
return 0;
}
@ -511,43 +511,38 @@ int CmdDetectClockRate(const char *Cmd)
int CmdFSKrawdemod(const char *Cmd)
{
//raw fsk demod no manchester decoding no start bit finding just get binary from wave
//set defaults
int rfLen = 50;
int invert=0;
int fchigh=10;
int fclow=8;
//set options from parameters entered with the command
sscanf(Cmd, "%i %i %i %i", &rfLen, &invert, &fchigh, &fclow);
// A lots of checks if chigh, clow is out-of bounds.
if (strlen(Cmd)>0 && strlen(Cmd)<=2) {
rfLen = 50;
//if invert option only is used
//rfLen=param_get8(Cmd, 0); //if rfLen option only is used
if (rfLen==1){
invert=1;
invert=1; //if invert option only is used
rfLen = 50;
} else if(rfLen==0) rfLen=50;
}
}
PrintAndLog("Args invert: %d - Clock:%d - FC high:%d - FC low: %d",invert,rfLen,fchigh, fclow);
uint8_t bits[MAX_GRAPH_TRACE_LEN] = {0x00};
uint32_t len = GetFromGraphBuf(bits);
int size = fskdemod(bits, len,(uint8_t)rfLen, (uint8_t)invert, (uint8_t)fchigh, (uint8_t)fclow);
PrintAndLog("Args invert: %d - Clock:%d - fchigh:%d - fclow: %d",invert,rfLen,fchigh, fclow);
uint32_t i=0;
uint8_t BitStream[MAX_GRAPH_TRACE_LEN]={0};
uint32_t BitLen = getFromGraphBuf(BitStream);
int size = fskdemod(BitStream,BitLen,(uint8_t)rfLen,(uint8_t)invert,(uint8_t)fchigh,(uint8_t)fclow);
if (size>0){
PrintAndLog("FSK decoded bitstream:");
SetGraphBuf(bits, size);
ClearGraph(0);
for (i=0;i<size;++i){
GraphBuffer[i]=BitStream[i];
}
GraphTraceLen=size;
RepaintGraphWindow();
// Now output the bitstream to the scrollback by line of 16 bits
// only output a max of 8 blocks of 32 bits most tags will have full bit stream inside that sample size
if(size > (8*32)+2)
size = (8*32)+2;
printBitStream(bits,size);
if(size > (8*32)+2) size = (8*32)+2; //only output a max of 8 blocks of 32 bits most tags will have full bit stream inside that sample size
printBitStream(BitStream,size);
} else{
PrintAndLog("no FSK data found");
}
@ -562,51 +557,37 @@ int CmdFSKdemodHID(const char *Cmd)
//raw fsk demod no manchester decoding no start bit finding just get binary from wave
uint32_t hi2=0, hi=0, lo=0;
uint8_t BitStream[MAX_GRAPH_TRACE_LEN] = {0x00};
uint32_t BitLen = GetFromGraphBuf(BitStream);
uint8_t BitStream[MAX_GRAPH_TRACE_LEN]={0};
uint32_t BitLen = getFromGraphBuf(BitStream);
//get binary from fsk wave
size_t size = HIDdemodFSK(BitStream,BitLen,&hi2,&hi,&lo);
if (size<0){
PrintAndLog("Error demoding fsk");
return 0;
}
if (hi2==0 && hi==0 && lo==0) return 0;
//extra large HID tags
if (hi2 != 0){
if (hi2 != 0){ //extra large HID tags
PrintAndLog("TAG ID: %x%08x%08x (%d)",
(unsigned int) hi2,
(unsigned int) hi,
(unsigned int) lo,
(unsigned int) (lo>>1) & 0xFFFF);
SetGraphBuf(BitStream,BitLen);
(unsigned int) hi2, (unsigned int) hi, (unsigned int) lo, (unsigned int) (lo>>1) & 0xFFFF);
setGraphBuf(BitStream,BitLen);
return 1;
} else {
//standard HID tags <38 bits
}
else { //standard HID tags <38 bits
//Dbprintf("TAG ID: %x%08x (%d)",(unsigned int) hi, (unsigned int) lo, (unsigned int) (lo>>1) & 0xFFFF); //old print cmd
uint8_t fmtLen = 0;
uint32_t fc = 0;
uint32_t cardnum = 0;
//if bit 38 is set then < 37 bit format is used
if (((hi>>5) & 1)==1){
if (((hi>>5)&1)==1){//if bit 38 is set then < 37 bit format is used
uint32_t lo2=0;
//get bits 21-37 to check for format len bit
lo2 = (((hi & 15) << 12) | (lo>>20));
lo2=(((hi & 15) << 12) | (lo>>20)); //get bits 21-37 to check for format len bit
uint8_t idx3 = 1;
//find last bit set to 1 (format len bit)
while( lo2 > 1){
while(lo2>1){ //find last bit set to 1 (format len bit)
lo2=lo2>>1;
idx3++;
}
fmtLen =idx3+19;
fc =0;
cardnum=0;
if(fmtLen==26){
cardnum = (lo>>1)&0xFFFF;
fc = (lo>>17)&0xFF;
@ -623,25 +604,20 @@ int CmdFSKdemodHID(const char *Cmd)
cardnum = (lo>>1)&0xFFFFF;
fc = ((hi&1)<<11)|(lo>>21);
}
} else {
//if bit 38 is not set then 37 bit format is used
}
else { //if bit 38 is not set then 37 bit format is used
fmtLen= 37;
fc =0;
cardnum=0;
if(fmtLen==37){
cardnum = (lo>>1)&0x7FFFF;
fc = ((hi&0xF)<<12)|(lo>>20);
}
}
PrintAndLog("TAG ID: %x%08x (%d) - Format Len: %dbit - FC: %d - Card: %d",
(unsigned int) hi,
(unsigned int) lo,
(unsigned int) (lo>>1) & 0xFFFF,
(unsigned int) fmtLen,
(unsigned int) fc,
(unsigned int) cardnum);
SetGraphBuf(BitStream,BitLen);
(unsigned int) hi, (unsigned int) lo, (unsigned int) (lo>>1) & 0xFFFF,
(unsigned int) fmtLen, (unsigned int) fc, (unsigned int) cardnum);
setGraphBuf(BitStream,BitLen);
return 1;
}
return 0;
@ -652,38 +628,26 @@ int CmdFSKdemodHID(const char *Cmd)
//print ioprox ID and some format details
int CmdFSKdemodIO(const char *Cmd)
{
if (GraphTraceLen < 65) {
PrintAndLog("data samples size is too small");
return 0;
}
//raw fsk demod no manchester decoding no start bit finding just get binary from wave
//set defaults
int idx=0;
uint8_t bits[MAX_GRAPH_TRACE_LEN] = {0x00};
uint32_t bitlen = GetFromGraphBuf(bits);
//something in graphbuffer
if (GraphTraceLen < 65) return 0;
uint8_t BitStream[MAX_GRAPH_TRACE_LEN]={0};
uint32_t BitLen = getFromGraphBuf(BitStream);
//get binary from fsk wave
idx = IOdemodFSK(bits, bitlen);
// PrintAndLog("DEBUG: got buff");
idx = IOdemodFSK(BitStream,BitLen);
if (idx<0){
//PrintAndLog("Error demoding fsk");
return 0;
}
// PrintAndLog("DEBUG: Got IOdemodFSK");
if (idx==0){
//PrintAndLog("IO Prox Data not found - FSK Data:");
//if (BitLen > 92) printBitStream(BitStream,92);
return 0;
}
if (idx == -1) {
PrintAndLog("data samples size is too small");
return 0;
}
if (idx == -2) {
PrintAndLog("Data samples has too much noice");
return 0;
}
if (idx == -3){
PrintAndLog("No good demod");
return 0;
}
if (idx+64 > bitlen) return 0;
//Index map
//0 10 20 30 40 50 60
//| | | | | | |
@ -693,26 +657,25 @@ int CmdFSKdemodIO(const char *Cmd)
//
//XSF(version)facility:codeone+codetwo (raw)
//Handle the data
if (idx+64>BitLen) return 0;
PrintAndLog("%d%d%d%d%d%d%d%d %d",BitStream[idx], BitStream[idx+1], BitStream[idx+2], BitStream[idx+3], BitStream[idx+4], BitStream[idx+5], BitStream[idx+6], BitStream[idx+7], BitStream[idx+8]);
PrintAndLog("%d%d%d%d%d%d%d%d %d",BitStream[idx+9], BitStream[idx+10], BitStream[idx+11],BitStream[idx+12],BitStream[idx+13],BitStream[idx+14],BitStream[idx+15],BitStream[idx+16],BitStream[idx+17]);
PrintAndLog("%d%d%d%d%d%d%d%d %d facility",BitStream[idx+18], BitStream[idx+19], BitStream[idx+20],BitStream[idx+21],BitStream[idx+22],BitStream[idx+23],BitStream[idx+24],BitStream[idx+25],BitStream[idx+26]);
PrintAndLog("%d%d%d%d%d%d%d%d %d version",BitStream[idx+27], BitStream[idx+28], BitStream[idx+29],BitStream[idx+30],BitStream[idx+31],BitStream[idx+32],BitStream[idx+33],BitStream[idx+34],BitStream[idx+35]);
PrintAndLog("%d%d%d%d%d%d%d%d %d code1",BitStream[idx+36], BitStream[idx+37], BitStream[idx+38],BitStream[idx+39],BitStream[idx+40],BitStream[idx+41],BitStream[idx+42],BitStream[idx+43],BitStream[idx+44]);
PrintAndLog("%d%d%d%d%d%d%d%d %d code2",BitStream[idx+45], BitStream[idx+46], BitStream[idx+47],BitStream[idx+48],BitStream[idx+49],BitStream[idx+50],BitStream[idx+51],BitStream[idx+52],BitStream[idx+53]);
PrintAndLog("%d%d%d%d%d%d%d%d %d%d checksum",BitStream[idx+54],BitStream[idx+55],BitStream[idx+56],BitStream[idx+57],BitStream[idx+58],BitStream[idx+59],BitStream[idx+60],BitStream[idx+61],BitStream[idx+62],BitStream[idx+63]);
PrintAndLog("%d%d%d%d%d%d%d%d %d", bits[idx] , bits[idx+1], bits[idx+2], bits[idx+3], bits[idx+4], bits[idx+5], bits[idx+6], bits[idx+7], bits[idx+8]);
PrintAndLog("%d%d%d%d%d%d%d%d %d", bits[idx+9] , bits[idx+10], bits[idx+11], bits[idx+12], bits[idx+13], bits[idx+14], bits[idx+15], bits[idx+16], bits[idx+17]);
PrintAndLog("%d%d%d%d%d%d%d%d %d facility", bits[idx+18], bits[idx+19], bits[idx+20], bits[idx+21], bits[idx+22], bits[idx+23], bits[idx+24], bits[idx+25], bits[idx+26]);
PrintAndLog("%d%d%d%d%d%d%d%d %d version", bits[idx+27], bits[idx+28], bits[idx+29], bits[idx+30], bits[idx+31], bits[idx+32], bits[idx+33], bits[idx+34], bits[idx+35]);
PrintAndLog("%d%d%d%d%d%d%d%d %d code1", bits[idx+36], bits[idx+37], bits[idx+38], bits[idx+39], bits[idx+40], bits[idx+41], bits[idx+42], bits[idx+43], bits[idx+44]);
PrintAndLog("%d%d%d%d%d%d%d%d %d code2", bits[idx+45], bits[idx+46], bits[idx+47], bits[idx+48], bits[idx+49], bits[idx+50], bits[idx+51], bits[idx+52], bits[idx+53]);
PrintAndLog("%d%d%d%d%d%d%d%d %d%d checksum", bits[idx+54], bits[idx+55], bits[idx+56], bits[idx+57], bits[idx+58], bits[idx+59], bits[idx+60], bits[idx+61], bits[idx+62], bits[idx+63]);
uint32_t code = bytebits_to_byte(bits+idx,32);
uint32_t code2 = bytebits_to_byte(bits+idx+32,32);
uint8_t version = bytebits_to_byte(bits+idx+27,8); //14,4
uint8_t facilitycode = bytebits_to_byte(bits+idx+18,8) ;
uint16_t number = (bytebits_to_byte(bits+idx+36,8)<<8)|(bytebits_to_byte(bits+idx+45,8)); //36,9
uint32_t code = bytebits_to_byte(BitStream+idx,32);
uint32_t code2 = bytebits_to_byte(BitStream+idx+32,32);
uint8_t version = bytebits_to_byte(BitStream+idx+27,8); //14,4
uint8_t facilitycode = bytebits_to_byte(BitStream+idx+18,8) ;
uint16_t number = (bytebits_to_byte(BitStream+idx+36,8)<<8)|(bytebits_to_byte(BitStream+idx+45,8)); //36,9
PrintAndLog("XSF(%02d)%02x:%05d (%08x%08x)",version,facilitycode,number,code,code2);
SetGraphBuf(bits, bitlen);
setGraphBuf(BitStream,BitLen);
return 1;
}
int CmdFSKdemod(const char *Cmd) //old CmdFSKdemod needs updating
{
static const int LowTone[] = {
@ -733,7 +696,7 @@ int CmdFSKdemod(const char *Cmd) //old CmdFSKdemod needs updating
int lowLen = sizeof (LowTone) / sizeof (int);
int highLen = sizeof (HighTone) / sizeof (int);
int convLen = (highLen > lowLen) ? highLen : lowLen;
int convLen = (highLen > lowLen) ? highLen : lowLen; //if highlen > lowLen then highlen else lowlen
uint32_t hi = 0, lo = 0;
int i, j;
@ -928,67 +891,29 @@ int CmdSamples(const char *Cmd)
int CmdTuneSamples(const char *Cmd)
{
int timeout = 0;
printf("\nMeasuring antenna characteristics, please wait...");
int cnt = 0;
int n = 255;
uint8_t got[255];
UsbCommand c = {CMD_MEASURE_ANTENNA_TUNING};
SendCommand(&c);
UsbCommand resp;
while(!WaitForResponseTimeout(CMD_MEASURED_ANTENNA_TUNING,&resp,1000)) {
timeout++;
printf(".");
if (timeout > 7) {
PrintAndLog("\nNo response from Proxmark. Aborting...");
return 1;
}
}
int peakv, peakf;
int vLf125, vLf134, vHf;
vLf125 = resp.arg[0] & 0xffff;
vLf134 = resp.arg[0] >> 16;
vHf = resp.arg[1] & 0xffff;;
peakf = resp.arg[2] & 0xffff;
peakv = resp.arg[2] >> 16;
PrintAndLog("");
PrintAndLog("# LF antenna: %5.2f V @ 125.00 kHz", vLf125/1000.0);
PrintAndLog("# LF antenna: %5.2f V @ 134.00 kHz", vLf134/1000.0);
PrintAndLog("# LF optimal: %5.2f V @%9.2f kHz", peakv/1000.0, 12000.0/(peakf+1));
PrintAndLog("# HF antenna: %5.2f V @ 13.56 MHz", vHf/1000.0);
if (peakv<2000)
PrintAndLog("# Your LF antenna is unusable.");
else if (peakv<10000)
PrintAndLog("# Your LF antenna is marginal.");
if (vHf<2000)
PrintAndLog("# Your HF antenna is unusable.");
else if (vHf<5000)
PrintAndLog("# Your HF antenna is marginal.");
for (int i = 0; i < 256; i++) {
GraphBuffer[i] = resp.d.asBytes[i] - 128;
PrintAndLog("Reading %d samples\n", n);
GetFromBigBuf(got,n,7256); // armsrc/apps.h: #define FREE_BUFFER_OFFSET 7256
WaitForResponse(CMD_ACK,NULL);
for (int j = 0; j < n; j++) {
GraphBuffer[cnt++] = ((int)got[j]) - 128;
}
PrintAndLog("Done! Divisor 89 is 134khz, 95 is 125khz.\n");
PrintAndLog("\n");
GraphTraceLen = 256;
ShowGraphWindow();
GraphTraceLen = n;
RepaintGraphWindow();
return 0;
}
int CmdLoad(const char *Cmd)
{
char filename[FILE_PATH_SIZE] = {0x00};
int len = 0;
len = strlen(Cmd);
if (len > FILE_PATH_SIZE) len = FILE_PATH_SIZE;
memcpy(filename, Cmd, len);
FILE *f = fopen(filename, "r");
FILE *f = fopen(Cmd, "r");
if (!f) {
PrintAndLog("couldn't open '%s'", filename);
PrintAndLog("couldn't open '%s'", Cmd);
return 0;
}
@ -1070,13 +995,20 @@ int CmdManchesterDemod(const char *Cmd)
/* But it does not work if compiling on WIndows: therefore we just allocate a */
/* large array */
uint8_t BitStream[MAX_GRAPH_TRACE_LEN] = {0x00};
uint8_t BitStream[MAX_GRAPH_TRACE_LEN] = {0};
/* Detect high and lows */
DetectHighLowInGraph( &high, &low, TRUE);
for (i = 0; i < GraphTraceLen; i++)
{
if (GraphBuffer[i] > high)
high = GraphBuffer[i];
else if (GraphBuffer[i] < low)
low = GraphBuffer[i];
}
/* Get our clock */
clock = GetClock(Cmd, 0);
clock = GetClock(Cmd, high, 1);
int tolerance = clock/4;
/* Detect first transition */
@ -1181,9 +1113,7 @@ int CmdManchesterDemod(const char *Cmd)
// At this stage, we now have a bitstream of "01" ("1") or "10" ("0"), parse it into final decoded bitstream
// Actually, we overwrite BitStream with the new decoded bitstream, we just need to be careful
// to stop output at the final bitidx2 value, not bitidx
//http://www.proxmark.org/forum/viewtopic.php?id=403
for (i = 1; i < bitidx; i += 2) {
for (i = 0; i < bitidx; i += 2) {
if ((BitStream[i] == 0) && (BitStream[i+1] == 1)) {
BitStream[bit2idx++] = 1 ^ invert;
} else if ((BitStream[i] == 1) && (BitStream[i+1] == 0)) {
@ -1226,17 +1156,18 @@ int CmdManchesterDemod(const char *Cmd)
BitStream[i+14],
BitStream[i+15]);
}
return bit2idx;
return 0;
}
/* Modulate our data into manchester */
int CmdManchesterMod(const char *Cmd)
{
int i, j;
int clock;
int bit, lastbit, wave;
int clock = GetClock(Cmd, 0);
int half = (int)(clock/2);
/* Get our clock */
clock = GetClock(Cmd, 0, 1);
wave = 0;
lastbit = 1;
@ -1244,9 +1175,9 @@ int CmdManchesterMod(const char *Cmd)
{
bit = GraphBuffer[i * clock] ^ 1;
for (j = 0; j < half; ++j)
for (j = 0; j < (int)(clock/2); j++)
GraphBuffer[(i * clock) + j] = bit ^ lastbit ^ wave;
for (j = half; j < clock; ++j)
for (j = (int)(clock/2); j < clock; j++)
GraphBuffer[(i * clock) + j] = bit ^ lastbit ^ wave ^ 1;
/* Keep track of how we start our wave and if we changed or not this time */
@ -1288,17 +1219,9 @@ int CmdPlot(const char *Cmd)
int CmdSave(const char *Cmd)
{
char filename[FILE_PATH_SIZE] = {0x00};
int len = 0;
len = strlen(Cmd);
if (len > FILE_PATH_SIZE) len = FILE_PATH_SIZE;
memcpy(filename, Cmd, len);
FILE *f = fopen(filename, "w");
FILE *f = fopen(Cmd, "w");
if(!f) {
PrintAndLog("couldn't open '%s'", filename);
PrintAndLog("couldn't open '%s'", Cmd);
return 0;
}
int i;
@ -1413,8 +1336,6 @@ static command_t CommandTable[] =
{"buffclear", CmdBuffClear, 1, "Clear sample buffer and graph window"},
{"dec", CmdDec, 1, "Decimate samples"},
{"detectaskclock",CmdDetectClockRate, 1, "Detect ASK clock rate"},
{"dirthreshold", CmdDirectionalThreshold, 1, "<thres up> <thres down> -- Max rising higher up-thres/ Min falling lower down-thres, keep rest as prev."},
{"em4xdecode", CmdEm410xDecode, 1, "decode em4x from graph buffer"},
{"fskdemod", CmdFSKdemod, 1, "Demodulate graph window as a HID FSK"},
{"fskhiddemod", CmdFSKdemodHID, 1, "Demodulate graph window as a HID FSK using raw"},
{"fskiodemod", CmdFSKdemodIO, 1, "Demodulate graph window as an IO Prox FSK using raw"},
@ -1432,11 +1353,12 @@ static command_t CommandTable[] =
{"norm", CmdNorm, 1, "Normalize max/min to +/-500"},
{"plot", CmdPlot, 1, "Show graph window (hit 'h' in window for keystroke help)"},
{"samples", CmdSamples, 0, "[512 - 40000] -- Get raw samples for graph window"},
{"tune", CmdTuneSamples, 0, "Get hw tune samples for graph window"},
{"save", CmdSave, 1, "<filename> -- Save trace (from graph window)"},
{"scale", CmdScale, 1, "<int> -- Set cursor display scale"},
{"threshold", CmdThreshold, 1, "<threshold> -- Maximize/minimize every value in the graph window depending on threshold"},
{"tune", CmdTuneSamples, 0, "Get hw tune samples for graph window"},
{"zerocrossings", CmdZerocrossings, 1, "Count time between zero-crossings"},
{"dirthreshold", CmdDirectionalThreshold, 1, "<thres up> <thres down> -- Max rising higher up-thres/ Min falling lower down-thres, keep rest as prev."},
{NULL, NULL, 0, NULL}
};

View file

@ -43,10 +43,11 @@ int CmdManchesterMod(const char *Cmd);
int CmdNorm(const char *Cmd);
int CmdPlot(const char *Cmd);
int CmdSamples(const char *Cmd);
int CmdTuneSamples(const char *Cmd);
int CmdSave(const char *Cmd);
int CmdScale(const char *Cmd);
int CmdThreshold(const char *Cmd);
int CmdDirectionalThreshold(const char *Cmd);
int CmdZerocrossings(const char *Cmd);
int CmdTuneSamples(const char *Cmd);
#endif

View file

@ -22,9 +22,6 @@
#include "cmdhflegic.h"
#include "cmdhficlass.h"
#include "cmdhfmf.h"
#include "cmdhfmfu.h"
#include "cmdhfmfdes.h"
#include "cmdhfdes.h"
static int CmdHelp(const char *Cmd);
@ -318,9 +315,6 @@ static command_t CommandTable[] =
{"legic", CmdHFLegic, 0, "{ LEGIC RFIDs... }"},
{"iclass", CmdHFiClass, 1, "{ ICLASS RFIDs... }"},
{"mf", CmdHFMF, 1, "{ MIFARE RFIDs... }"},
{"mfu", CmdHFMFUltra, 1, "{ MIFARE Ultralight RFIDs... }"},
{"mfdes", CmdHFMFDes, 1, "{ MIFARE Desfire RFIDs... }"},
{"des", CmdHFDES, 0, "{ MIFARE DESfire}"},
{"tune", CmdHFTune, 0, "Continuously measure HF antenna tuning"},
{"list", CmdHFList, 1, "List protocol data in trace buffer"},
{NULL, NULL, 0, NULL}

View file

@ -14,150 +14,22 @@
#include <string.h>
#include <unistd.h>
#include "util.h"
#include "../common/iso14443crc.h"
#include "iso14443crc.h"
#include "data.h"
#include "proxmark3.h"
#include "ui.h"
#include "cmdparser.h"
#include "cmdhf14a.h"
#include "../include/common.h"
#include "common.h"
#include "cmdmain.h"
#include "../include/mifare.h"
#include "mifare.h"
static int CmdHelp(const char *Cmd);
static void waitCmd(uint8_t iLen);
int CmdHF14AList(const char *Cmd)
{
bool ShowWaitCycles = false;
char param = param_getchar(Cmd, 0);
if (param == 'h' || (param != 0 && param != 'f')) {
PrintAndLog("List data in trace buffer.");
PrintAndLog("Usage: hf 14a list [f]");
PrintAndLog("f - show frame delay times as well");
PrintAndLog("sample: hf 14a list f");
return 0;
}
ShowWaitCycles = (param == 'f');
// for the time being. Need better Bigbuf handling.
#define TRACE_SIZE 3000
uint8_t trace[TRACE_SIZE];
GetFromBigBuf(trace, TRACE_SIZE, 0);
WaitForResponse(CMD_ACK,NULL);
PrintAndLog("Recorded Activity");
PrintAndLog("");
PrintAndLog("Start = Start of Start Bit, End = End of last modulation. Src = Source of Transfer");
PrintAndLog("All times are in carrier periods (1/13.56Mhz)");
PrintAndLog("");
PrintAndLog(" Start | End | Src | Data (! denotes parity error) | CRC ");
PrintAndLog("-----------|-----------|-----|-----------------------------------------------------------------------");
uint16_t tracepos = 0;
uint16_t duration;
uint16_t data_len;
uint16_t parity_len;
bool isResponse;
uint32_t timestamp;
uint32_t first_timestamp;
uint32_t EndOfTransmissionTimestamp;
for (;;) {
if(tracepos >= TRACE_SIZE) break;
timestamp = *((uint32_t *)(trace + tracepos));
// Break and stick with current result if buffer was not completely full
if (timestamp == 0x44444444) break;
if(tracepos == 0) {
first_timestamp = timestamp;
}
tracepos += 4;
duration = *((uint16_t *)(trace + tracepos));
tracepos += 2;
data_len = *((uint16_t *)(trace + tracepos));
tracepos += 2;
isResponse = false;
if (data_len & 0x8000) {
data_len &= 0x7fff;
isResponse = true;
}
parity_len = (data_len-1)/8 + 1;
if (tracepos + data_len + parity_len >= TRACE_SIZE) break;
uint8_t *frame = trace + tracepos;
tracepos += data_len;
uint8_t *parityBytes = trace + tracepos;
tracepos += parity_len;
char line[16][110];
for (int j = 0; j < data_len; j++) {
int oddparity = 0x01;
int k;
for (k=0;k<8;k++) {
oddparity ^= (((frame[j] & 0xFF) >> k) & 0x01);
}
uint8_t parityBits = parityBytes[j>>3];
if (isResponse && (oddparity != ((parityBits >> (7-(j&0x0007))) & 0x01))) {
sprintf(line[j/16]+((j%16)*4), "%02x! ", frame[j]);
} else {
sprintf(line[j/16]+((j%16)*4), "%02x ", frame[j]);
}
}
char crc[5] = {0x00};
if (data_len > 2) {
uint8_t b1, b2;
ComputeCrc14443(CRC_14443_A, frame, data_len-2, &b1, &b2);
if (b1 != frame[data_len-2] || b2 != frame[data_len-1]) {
sprintf(crc, (isResponse & (data_len < 6)) ? "" : "!crc");
}
}
EndOfTransmissionTimestamp = timestamp + duration;
int num_lines = (data_len - 1)/16 + 1;
for (int j = 0; j < num_lines; j++) {
if (j == 0) {
PrintAndLog(" %9d | %9d | %s | %-64s| %s",
(timestamp - first_timestamp),
(EndOfTransmissionTimestamp - first_timestamp),
(isResponse ? "Tag" : "Rdr"),
line[j],
(j == num_lines-1)?crc:""
);
} else {
PrintAndLog(" | | | %-64s| %s",
line[j],
(j == num_lines-1)?crc:"");
}
}
bool next_isResponse = *((uint16_t *)(trace + tracepos + 6)) & 0x8000;
if (ShowWaitCycles && !isResponse && next_isResponse) {
uint32_t next_timestamp = *((uint32_t *)(trace + tracepos));
if (next_timestamp != 0x44444444) {
PrintAndLog(" %9d | %9d | %s | fdt (Frame Delay Time): %d",
(EndOfTransmissionTimestamp - first_timestamp),
(next_timestamp - first_timestamp),
" ",
(next_timestamp - EndOfTransmissionTimestamp));
}
}
}
PrintAndLog("Deprecated command, use 'hf list 14a' instead");
return 0;
}
@ -226,6 +98,13 @@ int CmdHF14AReader(const char *Cmd)
card.ats_len = resp.arg[0]; // note: ats_len includes CRC Bytes
}
// disconnect
c.arg[0] = 0;
c.arg[1] = 0;
c.arg[2] = 0;
SendCommand(&c);
if(card.ats_len >= 3) { // a valid ATS consists of at least the length byte (TL) and 2 CRC bytes
bool ta1 = 0, tb1 = 0, tc1 = 0;
int pos;
@ -364,24 +243,6 @@ int CmdHF14AReader(const char *Cmd)
PrintAndLog("proprietary non iso14443-4 card found, RATS not supported");
}
// try to see if card responses to "chinese magic backdoor" commands.
c.cmd = CMD_MIFARE_CIDENT;
c.arg[0] = 0;
c.arg[1] = 0;
c.arg[2] = 0;
SendCommand(&c);
WaitForResponse(CMD_ACK,&resp);
uint8_t isOK = resp.arg[0] & 0xff;
PrintAndLog(" Answers to chinese magic backdoor commands: %s", (isOK ? "YES" : "NO") );
// disconnect
c.cmd = CMD_READER_ISO_14443a;
c.arg[0] = 0;
c.arg[1] = 0;
c.arg[2] = 0;
SendCommand(&c);
return select_status;
}
@ -536,22 +397,19 @@ int CmdHF14ACmdRaw(const char *cmd) {
uint8_t active=0;
uint8_t active_select=0;
uint16_t numbits=0;
uint16_t timeout=0;
uint8_t bTimeout=0;
char buf[5]="";
int i=0;
uint8_t data[USB_CMD_DATA_SIZE];
uint8_t data[100];
unsigned int datalen=0, 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] [-f] [-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(" -a active signal field ON without select");
PrintAndLog(" -s active signal field ON with select");
PrintAndLog(" -b number of bits to send. Useful for send partial byte");
PrintAndLog(" -t timeout");
return 0;
}
@ -584,14 +442,6 @@ int CmdHF14ACmdRaw(const char *cmd) {
while(cmd[i]!=' ' && cmd[i]!='\0') { i++; }
i-=2;
break;
case 't':
bTimeout=1;
sscanf(cmd+i+2,"%d",&temp);
timeout = temp & 0xFFFF;
i+=3;
while(cmd[i]!=' ' && cmd[i]!='\0') { i++; }
i+=2;
break;
default:
PrintAndLog("Invalid option");
return 0;
@ -609,19 +459,15 @@ int CmdHF14ACmdRaw(const char *cmd) {
if (strlen(buf)>=2) {
sscanf(buf,"%x",&temp);
data[datalen]=(uint8_t)(temp & 0xff);
datalen++;
*buf=0;
if (++datalen>sizeof(data)){
if (crc)
PrintAndLog("Buffer is full, we can't add CRC to your data");
break;
}
}
continue;
}
PrintAndLog("Invalid char on input");
return 0;
}
if(crc && datalen>0 && datalen<sizeof(data)-2)
if(crc && datalen>0)
{
uint8_t first, second;
ComputeCrc14443(CRC_14443_A, data, datalen, &first, &second);
@ -635,22 +481,13 @@ int CmdHF14ACmdRaw(const char *cmd) {
if(active)
c.arg[0] |= ISO14A_NO_SELECT;
}
if(bTimeout){
#define MAX_TIMEOUT 624*105 // max timeout is 624 ms
c.arg[0] |= ISO14A_SET_TIMEOUT;
c.arg[2] = timeout * 105; // each bit is about 9.4 us
if(c.arg[2]>MAX_TIMEOUT) {
c.arg[2] = MAX_TIMEOUT;
PrintAndLog("Set timeout to 624 ms. The max we can wait for response");
}
}
if(power)
c.arg[0] |= ISO14A_NO_DISCONNECT;
if(datalen>0)
c.arg[0] |= ISO14A_RAW;
// Max buffer is USB_CMD_DATA_SIZE
c.arg[1] = (datalen & 0xFFFF) | (numbits << 16);
c.arg[1] = datalen;
c.arg[2] = numbits;
memcpy(c.d.asBytes,data,datalen);
SendCommand(&c);
@ -670,7 +507,7 @@ static void waitCmd(uint8_t iSelect)
UsbCommand resp;
char *hexout;
if (WaitForResponseTimeout(CMD_ACK,&resp,10000)) {
if (WaitForResponseTimeout(CMD_ACK,&resp,1000)) {
recv = resp.d.asBytes;
uint8_t iLen = iSelect ? resp.arg[1] : resp.arg[0];
PrintAndLog("received %i octets",iLen);

View file

@ -13,15 +13,17 @@
#include <stdbool.h>
#include <string.h>
#include <stdint.h>
#include "../common/iso14443crc.h"
#include "iso14443crc.h"
#include "proxmark3.h"
#include "data.h"
#include "graph.h"
#include "util.h"
#include "ui.h"
#include "cmdparser.h"
#include "cmdhf14b.h"
#include "cmdmain.h"
static int CmdHelp(const char *Cmd);
int CmdHF14BDemod(const char *Cmd)
@ -144,7 +146,7 @@ demodError:
int CmdHF14BList(const char *Cmd)
{
uint8_t got[TRACE_BUFFER_SIZE];
uint8_t got[960];
GetFromBigBuf(got,sizeof(got),0);
WaitForResponse(CMD_ACK,NULL);
@ -156,8 +158,9 @@ int CmdHF14BList(const char *Cmd)
int prev = -1;
for(;;) {
if(i >= TRACE_BUFFER_SIZE) { break; }
if(i >= 900) {
break;
}
bool isResponse;
int timestamp = *((uint32_t *)(got+i));
@ -174,7 +177,7 @@ int CmdHF14BList(const char *Cmd)
if(len > 100) {
break;
}
if(i + len >= TRACE_BUFFER_SIZE) {
if(i + len >= 900) {
break;
}
@ -356,7 +359,7 @@ int CmdHF14BCmdRaw (const char *cmd) {
SendCommand(&c);
if (reply) {
if (WaitForResponseTimeout(CMD_ACK,&resp,10000)) {
if (WaitForResponseTimeout(CMD_ACK,&resp,1000)) {
recv = resp.d.asBytes;
PrintAndLog("received %i octets",resp.arg[0]);
if(!resp.arg[0])

View file

@ -31,9 +31,10 @@
#include "data.h"
#include "graph.h"
#include "ui.h"
#include "util.h"
#include "cmdparser.h"
#include "cmdhf15.h"
#include "../common/iso15693tools.h"
#include "iso15693tools.h"
#include "cmdmain.h"
#define FrameSOF Iso15693FrameSOF
@ -44,7 +45,6 @@
#define Crc(data,datalen) Iso15693Crc(data,datalen)
#define AddCrc(data,datalen) Iso15693AddCrc(data,datalen)
#define sprintUID(target,uid) Iso15693sprintUID(target,uid)
#define TRACE_BUFF_SIZE 12000
// structure and database for uid -> tagtype lookups
typedef struct {
@ -255,17 +255,6 @@ int CmdHF15Read(const char *Cmd)
{
UsbCommand c = {CMD_ACQUIRE_RAW_ADC_SAMPLES_ISO_15693};
SendCommand(&c);
uint8_t data[TRACE_BUFF_SIZE] = {0x00};
GetFromBigBuf(data,TRACE_BUFF_SIZE,3560); //3560 -- should be offset..
WaitForResponseTimeout(CMD_ACK,NULL, 1500);
for (int j = 0; j < TRACE_BUFF_SIZE; j++) {
GraphBuffer[j] = ((int)data[j]) ;
}
GraphTraceLen = TRACE_BUFF_SIZE;
RepaintGraphWindow();
return 0;
}
@ -274,17 +263,6 @@ int CmdHF15Record(const char *Cmd)
{
UsbCommand c = {CMD_RECORD_RAW_ADC_SAMPLES_ISO_15693};
SendCommand(&c);
uint8_t data[TRACE_BUFF_SIZE] = {0x00};
GetFromBigBuf(data,TRACE_BUFF_SIZE,3560); //3560 -- should be offset..
WaitForResponseTimeout(CMD_ACK,NULL, 1500);
for (int j = 0; j < TRACE_BUFF_SIZE; j++) {
GraphBuffer[j] = ((int)data[j]) ;
}
GraphTraceLen = TRACE_BUFF_SIZE;
RepaintGraphWindow();
return 0;
}

View file

@ -1,69 +0,0 @@
//-----------------------------------------------------------------------------
// 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;
}

View file

@ -1,27 +0,0 @@
//-----------------------------------------------------------------------------
// 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

View file

@ -13,7 +13,7 @@
#include "proxmark3.h"
#include "ui.h"
#include "cmdparser.h"
#include "../include/common.h"
#include "common.h"
#include "cmdmain.h"
#include "sleep.h"
#include "cmdhfepa.h"

View file

@ -20,7 +20,7 @@
#include "ui.h"
#include "cmdparser.h"
#include "cmdhficlass.h"
#include "../include/common.h"
#include "common.h"
#include "util.h"
#include "cmdmain.h"
#include "loclass/des.h"
@ -41,42 +41,6 @@ int xorbits_8(uint8_t val)
return res & 1;
}
#define ICLASS_CMD_ACTALL 0x0A
#define ICLASS_CMD_IDENTIFY 0x0C
#define ICLASS_CMD_READ 0x0C
#define ICLASS_CMD_SELECT 0x81
#define ICLASS_CMD_PAGESEL 0x84
#define ICLASS_CMD_READCHECK 0x88
#define ICLASS_CMD_CHECK 0x05
#define ICLASS_CMD_SOF 0x0F
#define ICLASS_CMD_HALT 0x00
void explain(char *exp, size_t size, uint8_t* cmd, uint8_t cmdsize)
{
if(cmdsize > 1 && cmd[0] == ICLASS_CMD_READ)
{
snprintf(exp,size,"READ(%d)",cmd[1]);
return;
}
switch(cmd[0])
{
case ICLASS_CMD_ACTALL: snprintf(exp,size,"ACTALL"); break;
case ICLASS_CMD_IDENTIFY: snprintf(exp,size,"IDENTIFY"); break;
case ICLASS_CMD_SELECT: snprintf(exp,size,"SELECT"); break;
case ICLASS_CMD_PAGESEL: snprintf(exp,size,"PAGESEL"); break;
case ICLASS_CMD_READCHECK: snprintf(exp,size,"READCHECK"); break;
case ICLASS_CMD_CHECK: snprintf(exp,size,"CHECK"); break;
case ICLASS_CMD_SOF: snprintf(exp,size,"SOF"); break;
case ICLASS_CMD_HALT: snprintf(exp,size,"HALT"); break;
default: snprintf(exp,size,"?"); break;
}
return;
}
int CmdHFiClassList(const char *Cmd)
{
PrintAndLog("Deprecated command, use 'hf list iclass' instead");
@ -469,7 +433,51 @@ int CmdHFiClass_iso14443A_write(const char *Cmd)
}
return 0;
}
int CmdHFiClass_loclass(const char *Cmd)
{
char opt = param_getchar(Cmd, 0);
if (strlen(Cmd)<1 || opt == 'h') {
PrintAndLog("Usage: hf iclass loclass [options]");
PrintAndLog("Options:");
PrintAndLog("h Show this help");
PrintAndLog("t Perform self-test");
PrintAndLog("f <filename> Bruteforce iclass dumpfile");
PrintAndLog(" An iclass dumpfile is assumed to consist of an arbitrary number of");
PrintAndLog(" malicious CSNs, and their protocol responses");
PrintAndLog(" The the binary format of the file is expected to be as follows: ");
PrintAndLog(" <8 byte CSN><8 byte CC><4 byte NR><4 byte MAC>");
PrintAndLog(" <8 byte CSN><8 byte CC><4 byte NR><4 byte MAC>");
PrintAndLog(" <8 byte CSN><8 byte CC><4 byte NR><4 byte MAC>");
PrintAndLog(" ... totalling N*24 bytes");
return 0;
}
char fileName[255] = {0};
if(opt == 'f')
{
if(param_getstr(Cmd, 1, fileName) > 0)
{
return bruteforceFileNoKeys(fileName);
}else
{
PrintAndLog("You must specify a filename");
}
}
else if(opt == 't')
{
int errors = testCipherUtils();
errors += testMAC();
errors += doKeyTests(0);
errors += testElite();
if(errors)
{
prnlog("OBS! There were errors!!!");
}
return errors;
}
return 0;
}
static command_t CommandTable[] =
{
@ -481,6 +489,7 @@ static command_t CommandTable[] =
{"replay",CmdHFiClassReader_Replay, 0, "Read an iClass tag via Reply Attack"},
{"dump", CmdHFiClassReader_Dump, 0, "Authenticate and Dump iClass tag"},
{"write", CmdHFiClass_iso14443A_write, 0, "Authenticate and Write iClass block"},
{"loclass", CmdHFiClass_loclass, 1, "Use loclass to perform bruteforce of reader attack dump"},
{NULL, NULL, 0, NULL}
};

View file

@ -218,24 +218,7 @@ int CmdLegicRFRead(const char *Cmd)
int CmdLegicLoad(const char *Cmd)
{
char filename[FILE_PATH_SIZE] = {0x00};
int len = 0;
if (param_getchar(Cmd, 0) == 'h' || param_getchar(Cmd, 0)== 0x00) {
PrintAndLog("It loads datasamples from the file `filename`");
PrintAndLog("Usage: hf legic load <file name>");
PrintAndLog(" sample: hf legic load filename");
return 0;
}
len = strlen(Cmd);
if (len > FILE_PATH_SIZE) {
PrintAndLog("Filepath too long (was %s bytes), max allowed is %s ", len, FILE_PATH_SIZE);
return 0;
}
memcpy(filename, Cmd, len);
FILE *f = fopen(filename, "r");
FILE *f = fopen(Cmd, "r");
if(!f) {
PrintAndLog("couldn't open '%s'", Cmd);
return -1;
@ -268,7 +251,7 @@ int CmdLegicSave(const char *Cmd)
int requested = 1024;
int offset = 0;
int delivered = 0;
char filename[FILE_PATH_SIZE];
char filename[1024];
uint8_t got[1024];
sscanf(Cmd, " %s %i %i", filename, &requested, &offset);

View file

@ -7,7 +7,7 @@
//-----------------------------------------------------------------------------
// High frequency MIFARE commands
//-----------------------------------------------------------------------------
#include "../include/mifare.h"
#include "cmdhfmf.h"
static int CmdHelp(const char *Cmd);
@ -66,7 +66,8 @@ start:
if (isOK != 1) return 1;
// execute original function from util nonce2key
if (nonce2key(uid, nt, nr, par_list, ks_list, &r_key)) {
if (nonce2key(uid, nt, nr, par_list, ks_list, &r_key))
{
isOK = 2;
PrintAndLog("Key not found (lfsr_common_prefix list is null). Nt=%08x", nt);
} else {
@ -140,6 +141,117 @@ int CmdHF14AMfWrBl(const char *Cmd)
return 0;
}
int CmdHF14AMfUWrBl(const char *Cmd)
{
uint8_t blockNo = 0;
bool chinese_card=0;
uint8_t bldata[16] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
UsbCommand resp;
if (strlen(Cmd)<3) {
PrintAndLog("Usage: hf mf uwrbl <block number> <block data (8 hex symbols)> <w>");
PrintAndLog(" sample: hf mf uwrbl 0 01020304");
return 0;
}
blockNo = param_get8(Cmd, 0);
if (param_gethex(Cmd, 1, bldata, 8)) {
PrintAndLog("Block data must include 8 HEX symbols");
return 1;
}
if (strchr(Cmd,'w') != 0) {
chinese_card=1;
}
switch(blockNo){
case 0:
if (!chinese_card){
PrintAndLog("Access Denied");
}else{
PrintAndLog("--specialblock no:%d", 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");
}
}
break;
case 1:
if (!chinese_card){
PrintAndLog("Access Denied");
}else{
PrintAndLog("--specialblock no:%d", 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");
}
}
break;
case 2:
if (!chinese_card){
PrintAndLog("Access Denied");
}else{
PrintAndLog("--specialblock no:%d", blockNo);
PrintAndLog("--data: %s", sprint_hex(bldata, 4));
UsbCommand c = {CMD_MIFAREU_WRITEBL, {blockNo}};
memcpy(c.d.asBytes, bldata, 4);
SendCommand(&c);
if (WaitForResponseTimeout(CMD_ACK,&resp,1500)) {
uint8_t isOK = resp.arg[0] & 0xff;
PrintAndLog("isOk:%02x", isOK);
} else {
PrintAndLog("Command execute timeout");
}
}
break;
case 3:
PrintAndLog("--specialblock no:%d", 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");
}
break;
default:
PrintAndLog("--block no:%d", 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");
}
break;
}
return 0;
}
int CmdHF14AMfRdBl(const char *Cmd)
{
uint8_t blockNo = 0;
@ -188,6 +300,87 @@ int CmdHF14AMfRdBl(const char *Cmd)
return 0;
}
int CmdHF14AMfURdBl(const char *Cmd)
{
uint8_t blockNo = 0;
if (strlen(Cmd)<1) {
PrintAndLog("Usage: hf mf urdbl <block number>");
PrintAndLog(" sample: hf mf urdbl 0");
return 0;
}
blockNo = param_get8(Cmd, 0);
PrintAndLog("--block no:%d", blockNo);
UsbCommand c = {CMD_MIFAREU_READBL, {blockNo}};
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, 4));
else
PrintAndLog("isOk:%02x", isOK);
} else {
PrintAndLog("Command execute timeout");
}
return 0;
}
int CmdHF14AMfURdCard(const char *Cmd)
{
int i;
uint8_t sectorNo = 0;
uint8_t *lockbytes_t=NULL;
uint8_t lockbytes[2]={0,0};
bool bit[16]={0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
uint8_t isOK = 0;
uint8_t * data = NULL;
PrintAndLog("Attempting to Read Ultralight... ");
UsbCommand c = {CMD_MIFAREU_READCARD, {sectorNo}};
SendCommand(&c);
UsbCommand resp;
if (WaitForResponseTimeout(CMD_ACK,&resp,1500)) {
isOK = resp.arg[0] & 0xff;
data = resp.d.asBytes;
PrintAndLog("isOk:%02x", isOK);
if (isOK)
{ // bit 0 and 1
PrintAndLog("Block %3d:%s ", 0,sprint_hex(data + 0 * 4, 4));
PrintAndLog("Block %3d:%s ", 1,sprint_hex(data + 1 * 4, 4));
// bit 2
//process lock bytes
lockbytes_t=data+(2*4);
lockbytes[0]=lockbytes_t[2];
lockbytes[1]=lockbytes_t[3];
for(int j=0; j<16; j++){
bit[j]=lockbytes[j/8] & ( 1 <<(7-j%8));
}
//remaining
for (i = 3; i < 16; i++) {
int bitnum = (23-i) % 16;
PrintAndLog("Block %3d:%s [%d]", i,sprint_hex(data + i * 4, 4),bit[bitnum]);
}
}
} else {
PrintAndLog("Command execute timeout");
}
return 0;
}
int CmdHF14AMfRdSc(const char *Cmd)
{
int i;
@ -278,14 +471,7 @@ int CmdHF14AMfDump(const char *Cmd)
UsbCommand resp;
int size = GetCardSize();
char cmdp = param_getchar(Cmd, 0);
if ( size > -1)
cmdp = (char)(48+size);
PrintAndLog("Got %d",cmdp);
switch (cmdp) {
case '0' : numSectors = 5; break;
case '1' :
@ -326,8 +512,8 @@ int CmdHF14AMfDump(const char *Cmd)
return 2;
}
}
fclose(fin);
// Read access rights to sectors
PrintAndLog("|-----------------------------------------|");
PrintAndLog("|------ Reading sector access bits...-----|");
@ -358,6 +544,8 @@ int CmdHF14AMfDump(const char *Cmd)
}
}
// Read blocks and print to file
PrintAndLog("|-----------------------------------------|");
PrintAndLog("|----- Dumping all blocks to file... -----|");
PrintAndLog("|-----------------------------------------|");
@ -441,8 +629,8 @@ int CmdHF14AMfRestore(const char *Cmd)
{
uint8_t sectorNo,blockNo;
uint8_t keyType = 0;
uint8_t key[6] = {0xFF};
uint8_t bldata[16] = {0x00};
uint8_t key[6] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF};
uint8_t bldata[16] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
uint8_t keyA[40][6];
uint8_t keyB[40][6];
uint8_t numSectors;
@ -460,7 +648,7 @@ int CmdHF14AMfRestore(const char *Cmd)
default: numSectors = 16;
}
if (cmdp == 'h' || cmdp == 'H') {
if (strlen(Cmd) > 1 || cmdp == 'h' || cmdp == 'H') {
PrintAndLog("Usage: hf mf restore [card memory]");
PrintAndLog(" [card memory]: 0 = 320 bytes (Mifare Mini), 1 = 1K (default), 2 = 2K, 4 = 4K");
PrintAndLog("");
@ -469,14 +657,21 @@ int CmdHF14AMfRestore(const char *Cmd)
return 0;
}
if ((fdump = fopen("dumpdata.bin","rb")) == NULL) {
PrintAndLog("Could not find file dumpdata.bin");
return 1;
}
if ((fkeys = fopen("dumpkeys.bin","rb")) == NULL) {
PrintAndLog("Could not find file dumpkeys.bin");
fclose(fdump);
return 1;
}
for (sectorNo = 0; sectorNo < numSectors; sectorNo++) {
if (fread(keyA[sectorNo], 1, 6, fkeys) == 0) {
PrintAndLog("File reading error (dumpkeys.bin).");
fclose(fdump);
fclose(fkeys);
return 2;
}
}
@ -484,16 +679,13 @@ int CmdHF14AMfRestore(const char *Cmd)
for (sectorNo = 0; sectorNo < numSectors; sectorNo++) {
if (fread(keyB[sectorNo], 1, 6, fkeys) == 0) {
PrintAndLog("File reading error (dumpkeys.bin).");
fclose(fdump);
fclose(fkeys);
return 2;
}
}
fclose(fkeys);
if ((fdump = fopen("dumpdata.bin","rb")) == NULL) {
PrintAndLog("Could not find file dumpdata.bin");
return 1;
}
PrintAndLog("Restoring dumpdata.bin to card");
for (sectorNo = 0; sectorNo < numSectors; sectorNo++) {
@ -551,7 +743,7 @@ int CmdHF14AMfNested(const char *Cmd)
uint8_t trgKeyType = 0;
uint8_t SectorsCnt = 0;
uint8_t key[6] = {0, 0, 0, 0, 0, 0};
uint8_t keyBlock[13*6];
uint8_t keyBlock[6*6];
uint64_t key64 = 0;
bool transferToEml = false;
@ -581,15 +773,11 @@ int CmdHF14AMfNested(const char *Cmd)
cmdp = param_getchar(Cmd, 0);
blockNo = param_get8(Cmd, 1);
ctmp = param_getchar(Cmd, 2);
if (ctmp != 'a' && ctmp != 'A' && ctmp != 'b' && ctmp != 'B') {
PrintAndLog("Key type must be A or B");
return 1;
}
if (ctmp != 'A' && ctmp != 'a')
keyType = 1;
if (ctmp != 'A' && ctmp != 'a') keyType = 1;
if (param_gethex(Cmd, 3, key, 12)) {
PrintAndLog("Key must include 12 HEX symbols");
return 1;
@ -603,10 +791,8 @@ int CmdHF14AMfNested(const char *Cmd)
PrintAndLog("Target key type must be A or B");
return 1;
}
if (ctmp != 'A' && ctmp != 'a')
trgKeyType = 1;
if (ctmp != 'A' && ctmp != 'a') trgKeyType = 1;
} else {
switch (cmdp) {
case '0': SectorsCnt = 05; break;
case '1': SectorsCnt = 16; break;
@ -668,14 +854,6 @@ int CmdHF14AMfNested(const char *Cmd)
num_to_bytes(0xa0a1a2a3a4a5, 6, (uint8_t*)(keyBlock + 3 * 6));
num_to_bytes(0xb0b1b2b3b4b5, 6, (uint8_t*)(keyBlock + 4 * 6));
num_to_bytes(0xaabbccddeeff, 6, (uint8_t*)(keyBlock + 5 * 6));
num_to_bytes(0x4d3a99c351dd, 6, (uint8_t*)(keyBlock + 6 * 6));
num_to_bytes(0x1a982c7e459a, 6, (uint8_t*)(keyBlock + 7 * 6));
num_to_bytes(0xd3f7d3f7d3f7, 6, (uint8_t*)(keyBlock + 8 * 6));
num_to_bytes(0x714c5c886e97, 6, (uint8_t*)(keyBlock + 9 * 6));
num_to_bytes(0x587ee5f9350f, 6, (uint8_t*)(keyBlock + 10 * 6));
num_to_bytes(0xa0478cc39091, 6, (uint8_t*)(keyBlock + 11 * 6));
num_to_bytes(0x533cb6c723f6, 6, (uint8_t*)(keyBlock + 12 * 6));
num_to_bytes(0x8fd0a4f256e9, 6, (uint8_t*)(keyBlock + 13 * 6));
PrintAndLog("Testing known keys. Sector count=%d", SectorsCnt);
for (i = 0; i < SectorsCnt; i++) {
@ -691,26 +869,21 @@ int CmdHF14AMfNested(const char *Cmd)
}
}
// nested sectors
iterations = 0;
PrintAndLog("nested...");
bool calibrate = true;
for (i = 0; i < NESTED_SECTOR_RETRY; i++) {
for (uint8_t sectorNo = 0; sectorNo < SectorsCnt; sectorNo++) {
if (ukbhit()) {
printf("\naborted via keyboard!\n");
free(e_sector);
return 2;
}
for (trgKeyType = 0; trgKeyType < 2; trgKeyType++) {
if (e_sector[sectorNo].foundKey[trgKeyType]) continue;
PrintAndLog("-----------------------------------------------");
if(mfnested(blockNo, keyType, key, FirstBlockOfSector(sectorNo), trgKeyType, keyBlock, calibrate)) {
PrintAndLog("Nested error.\n");
free(e_sector);
return 2; }
return 2;
}
else {
calibrate = false;
}
@ -789,19 +962,17 @@ int CmdHF14AMfNested(const char *Cmd)
int CmdHF14AMfChk(const char *Cmd)
{
if (strlen(Cmd)<3) {
PrintAndLog("Usage: hf mf chk <block number>|<*card memory> <key type (A/B/?)> [t|d] [<key (12 hex symbols)>] [<dic (*.dic)>]");
PrintAndLog("Usage: hf mf chk <block number>|<*card memory> <key type (A/B/?)> [t] [<key (12 hex symbols)>] [<dic (*.dic)>]");
PrintAndLog(" * - all sectors");
PrintAndLog("card memory - 0 - MINI(320 bytes), 1 - 1K, 2 - 2K, 4 - 4K, <other> - 1K");
PrintAndLog("d - write keys to binary file\n");
PrintAndLog("t - write keys to emulator memory");
PrintAndLog(" sample: hf mf chk 0 A 1234567890ab keys.dic");
PrintAndLog(" hf mf chk *1 ? t");
PrintAndLog(" hf mf chk *1 ? d");
return 0;
}
FILE * f;
char filename[FILE_PATH_SIZE]={0};
char filename[256]={0};
char buf[13];
uint8_t *keyBlock = NULL, *p;
uint8_t stKeyBlock = 20;
@ -893,7 +1064,7 @@ int CmdHF14AMfChk(const char *Cmd)
keycnt++;
} else {
// May be a dic file
if ( param_getstr(Cmd, 2 + i,filename) >= FILE_PATH_SIZE ) {
if ( param_getstr(Cmd, 2 + i,filename) > 255 ) {
PrintAndLog("File name too long");
free(keyBlock);
return 2;
@ -1174,44 +1345,26 @@ int CmdHF14AMfESet(const char *Cmd)
int CmdHF14AMfELoad(const char *Cmd)
{
FILE * f;
char filename[FILE_PATH_SIZE];
char filename[20];
char *fnameptr = filename;
char buf[64];
uint8_t buf8[64];
int i, len, blockNum, numBlocks;
int nameParamNo = 1;
int i, len, blockNum;
memset(filename, 0, sizeof(filename));
memset(buf, 0, sizeof(buf));
char ctmp = param_getchar(Cmd, 0);
if ( ctmp == 'h' || ctmp == 0x00) {
if (param_getchar(Cmd, 0) == 'h' || param_getchar(Cmd, 0)== 0x00) {
PrintAndLog("It loads emul dump from the file `filename.eml`");
PrintAndLog("Usage: hf mf eload [card memory] <file name w/o `.eml`>");
PrintAndLog(" [card memory]: 0 = 320 bytes (Mifare Mini), 1 = 1K (default), 2 = 2K, 4 = 4K");
PrintAndLog("");
PrintAndLog("Usage: hf mf eload <file name w/o `.eml`>");
PrintAndLog(" sample: hf mf eload filename");
PrintAndLog(" hf mf eload 4 filename");
return 0;
}
switch (ctmp) {
case '0' : numBlocks = 5*4; break;
case '1' :
case '\0': numBlocks = 16*4; break;
case '2' : numBlocks = 32*4; break;
case '4' : numBlocks = 256; break;
default: {
numBlocks = 16*4;
nameParamNo = 0;
}
}
len = param_getstr(Cmd,nameParamNo,filename);
if (len > FILE_PATH_SIZE) len = FILE_PATH_SIZE;
len = strlen(Cmd);
if (len > 14) len = 14;
memcpy(filename, Cmd, len);
fnameptr += len;
sprintf(fnameptr, ".eml");
@ -1226,16 +1379,14 @@ int CmdHF14AMfELoad(const char *Cmd)
blockNum = 0;
while(!feof(f)){
memset(buf, 0, sizeof(buf));
if (fgets(buf, sizeof(buf), f) == NULL) {
if (blockNum >= numBlocks) break;
if((blockNum == 16*4) || (blockNum == 32*4 + 8*16)) { // supports both old (1K) and new (4K) .eml files)
break;
}
PrintAndLog("File reading error.");
fclose(f);
return 2;
}
if (strlen(buf) < 32){
if(strlen(buf) && feof(f))
break;
@ -1243,7 +1394,6 @@ int CmdHF14AMfELoad(const char *Cmd)
fclose(f);
return 2;
}
for (i = 0; i < 32; i += 2) {
sscanf(&buf[i], "%02x", (unsigned int *)&buf8[i / 2]);
}
@ -1255,12 +1405,12 @@ int CmdHF14AMfELoad(const char *Cmd)
}
blockNum++;
if (blockNum >= numBlocks) break;
if (blockNum >= 32*4 + 8*16) break;
}
fclose(f);
if ((blockNum != numBlocks)) {
PrintAndLog("File content error. Got %d must be %d blocks.",blockNum, numBlocks);
if ((blockNum != 16*4) && (blockNum != 32*4 + 8*16)) {
PrintAndLog("File content error. There must be 64 or 256 blocks.");
return 4;
}
PrintAndLog("Loaded %d blocks from file: %s", blockNum, filename);
@ -1271,65 +1421,45 @@ int CmdHF14AMfELoad(const char *Cmd)
int CmdHF14AMfESave(const char *Cmd)
{
FILE * f;
char filename[FILE_PATH_SIZE];
char filename[20];
char * fnameptr = filename;
uint8_t buf[64];
int i, j, len, numBlocks;
int nameParamNo = 1;
int i, j, len;
memset(filename, 0, sizeof(filename));
memset(buf, 0, sizeof(buf));
char ctmp = param_getchar(Cmd, 0);
if ( ctmp == 'h') {
if (param_getchar(Cmd, 0) == 'h') {
PrintAndLog("It saves emul dump into the file `filename.eml` or `cardID.eml`");
PrintAndLog(" Usage: hf mf esave [card memory] [file name w/o `.eml`]");
PrintAndLog(" [card memory]: 0 = 320 bytes (Mifare Mini), 1 = 1K (default), 2 = 2K, 4 = 4K");
PrintAndLog("");
PrintAndLog("Usage: hf mf esave [file name w/o `.eml`]");
PrintAndLog(" sample: hf mf esave ");
PrintAndLog(" hf mf esave 4");
PrintAndLog(" hf mf esave 4 filename");
PrintAndLog(" hf mf esave filename");
return 0;
}
switch (ctmp) {
case '0' : numBlocks = 5*4; break;
case '1' :
case '\0': numBlocks = 16*4; break;
case '2' : numBlocks = 32*4; break;
case '4' : numBlocks = 256; break;
default: {
numBlocks = 16*4;
nameParamNo = 0;
}
}
len = strlen(Cmd);
if (len > 14) len = 14;
len = param_getstr(Cmd,nameParamNo,filename);
if (len > FILE_PATH_SIZE) len = FILE_PATH_SIZE;
// user supplied filename?
if (len < 1) {
// get filename (UID from memory)
// get filename
if (mfEmlGetMem(buf, 0, 1)) {
PrintAndLog("Can\'t get UID from block: %d", 0);
sprintf(filename, "dump.eml");
PrintAndLog("Cant get block: %d", 0);
return 1;
}
for (j = 0; j < 7; j++, fnameptr += 2)
sprintf(fnameptr, "%02X", buf[j]);
sprintf(fnameptr, "%02x", buf[j]);
} else {
memcpy(filename, Cmd, len);
fnameptr += len;
}
// add file extension
sprintf(fnameptr, ".eml");
// open file
f = fopen(filename, "w+");
// put hex
for (i = 0; i < numBlocks; i++) {
for (i = 0; i < 32*4 + 8*16; i++) {
if (mfEmlGetMem(buf, i, 1)) {
PrintAndLog("Cant get block: %d", i);
break;
@ -1340,7 +1470,7 @@ int CmdHF14AMfESave(const char *Cmd)
}
fclose(f);
PrintAndLog("Saved %d blocks to file: %s", numBlocks, filename);
PrintAndLog("Saved to file: %s", filename);
return 0;
}
@ -1389,34 +1519,13 @@ int CmdHF14AMfECFill(const char *Cmd)
int CmdHF14AMfEKeyPrn(const char *Cmd)
{
int i;
uint8_t numSectors;
uint8_t data[16];
uint64_t keyA, keyB;
if (param_getchar(Cmd, 0) == 'h') {
PrintAndLog("It prints the keys loaded in the emulator memory");
PrintAndLog("Usage: hf mf ekeyprn [card memory]");
PrintAndLog(" [card memory]: 0 = 320 bytes (Mifare Mini), 1 = 1K (default), 2 = 2K, 4 = 4K");
PrintAndLog("");
PrintAndLog(" sample: hf mf ekeyprn 1");
return 0;
}
char cmdp = param_getchar(Cmd, 0);
switch (cmdp) {
case '0' : numSectors = 5; break;
case '1' :
case '\0': numSectors = 16; break;
case '2' : numSectors = 32; break;
case '4' : numSectors = 40; break;
default: numSectors = 16;
}
PrintAndLog("|---|----------------|----------------|");
PrintAndLog("|sec|key A |key B |");
PrintAndLog("|---|----------------|----------------|");
for (i = 0; i < numSectors; i++) {
for (i = 0; i < 40; i++) {
if (mfEmlGetMem(data, FirstBlockOfSector(i) + NumBlocksPerSector(i) - 1, 1)) {
PrintAndLog("error get block %d", FirstBlockOfSector(i) + NumBlocksPerSector(i) - 1);
break;
@ -1506,7 +1615,7 @@ int CmdHF14AMfCSetBlk(const char *Cmd)
int CmdHF14AMfCLoad(const char *Cmd)
{
FILE * f;
char filename[FILE_PATH_SIZE];
char filename[20];
char * fnameptr = filename;
char buf[64];
uint8_t buf8[64];
@ -1547,7 +1656,7 @@ int CmdHF14AMfCLoad(const char *Cmd)
return 0;
} else {
len = strlen(Cmd);
if (len > FILE_PATH_SIZE) len = FILE_PATH_SIZE;
if (len > 14) len = 14;
memcpy(filename, Cmd, len);
fnameptr += len;
@ -1592,7 +1701,7 @@ int CmdHF14AMfCLoad(const char *Cmd)
}
fclose(f);
if (blockNum != 16 * 4 && blockNum != 32 * 4 + 8 * 16){
if (blockNum != 16 * 4){
PrintAndLog("File content error. There must be 64 blocks");
return 4;
}
@ -1670,7 +1779,7 @@ int CmdHF14AMfCGetSc(const char *Cmd) {
int CmdHF14AMfCSave(const char *Cmd) {
FILE * f;
char filename[FILE_PATH_SIZE];
char filename[20];
char * fnameptr = filename;
uint8_t fillFromEmulator = 0;
uint8_t buf[64];
@ -1712,7 +1821,7 @@ int CmdHF14AMfCSave(const char *Cmd) {
return 0;
} else {
len = strlen(Cmd);
if (len > FILE_PATH_SIZE) len = FILE_PATH_SIZE;
if (len > 14) len = 14;
if (len < 1) {
// get filename
@ -1886,106 +1995,14 @@ int CmdHF14AMfSniff(const char *Cmd){
return 0;
}
// Tries to identify cardsize.
// Returns <num> where num is:
// -1 unidentified
// 0 - MINI (320bytes)
// 1 - 1K
// 2 - 2K
// 4 - 4K
int GetCardSize()
{
UsbCommand c = {CMD_READER_ISO_14443a, {ISO14A_CONNECT, 0, 0}};
SendCommand(&c);
UsbCommand resp;
WaitForResponse(CMD_ACK,&resp);
if(resp.arg[0] == 0) {
PrintAndLog("iso14443a card select failed");
return -1;
}
iso14a_card_select_t *card = (iso14a_card_select_t *)resp.d.asBytes;
PrintAndLog("Trying to detect card size.");
uint16_t atqa = 0;
uint8_t sak = 0;
atqa = (card->atqa[1] & 0xff) << 8;
atqa += card->atqa[0] & 0xff;
sak = card->sak;
// https://code.google.com/p/libnfc/source/browse/libnfc/target-subr.c
PrintAndLog("found ATAQ: %04X SAK: %02X", atqa, sak);
// NXP MIFARE Mini 0.3k
if ( ( (atqa & 0xff0f) == 0x0004) && (sak == 0x09) ) return 0;
// MIFARE Classic 1K
if ( ((atqa & 0xff0f) == 0x0004) && (sak == 0x08) ) return 1;
// MIFARE Classik 4K
if ( ((atqa & 0xff0f) == 0x0002) && (sak == 0x18) ) return 4;
// SmartMX with MIFARE 1K emulation
if ( ((atqa & 0xf0ff) == 0x0004) ) return 1;
// SmartMX with MIFARE 4K emulation
if ( ((atqa & 0xf0ff) == 0x0002) ) return 4;
// Infineon MIFARE CLASSIC 1K
if ( ((atqa & 0xffff) == 0x0004) && (sak == 0x88) ) return 1;
// MFC 4K emulated by Nokia 6212 Classic
if ( ((atqa & 0xffff) == 0x0002) && (sak == 0x38) ) return 4;
// MFC 4K emulated by Nokia 6131 NFC
if ( ((atqa & 0xffff) == 0x0008) && (sak == 0x38) ) return 4;
PrintAndLog("BEFOOO 1K %02X", (atqa & 0xff0f));
// MIFARE Plus (4 Byte UID or 4 Byte RID)
// MIFARE Plus (7 Byte UID)
if (
((atqa & 0xffff) == 0x0002) |
((atqa & 0xffff) == 0x0004) |
((atqa & 0xffff) == 0x0042) |
((atqa & 0xffff) == 0x0044)
)
{
switch(sak){
case 0x08:
case 0x10: {
//case 0x20:
PrintAndLog("2");
return 2;
break;
}
case 0x11:
case 0x18:{
//case 0x20:
PrintAndLog("4");
return 4;
break;
}
}
}
return -1;
}
static command_t CommandTable[] =
{
{"help", CmdHelp, 1, "This help"},
{"dbg", CmdHF14AMfDbg, 0, "Set default debug mode"},
{"rdbl", CmdHF14AMfRdBl, 0, "Read MIFARE classic block"},
//{"urdbl", CmdHF14AMfURdBl, 0, "Read MIFARE Ultralight block"},
//{"urdcard", CmdHF14AMfURdCard, 0,"Read MIFARE Ultralight Card"},
//{"uwrbl", CmdHF14AMfUWrBl, 0,"Write MIFARE Ultralight block"},
{"urdbl", CmdHF14AMfURdBl, 0, "Read MIFARE Ultralight block"},
{"urdcard", CmdHF14AMfURdCard, 0,"Read MIFARE Ultralight Card"},
{"uwrbl", CmdHF14AMfUWrBl, 0,"Write MIFARE Ultralight block"},
{"rdsc", CmdHF14AMfRdSc, 0, "Read MIFARE classic sector"},
{"dump", CmdHF14AMfDump, 0, "Dump MIFARE classic tag to binary file"},
{"restore", CmdHF14AMfRestore, 0, "Restore MIFARE classic binary file to BLANK tag"},

View file

@ -16,11 +16,11 @@
#include <string.h>
#include <ctype.h>
#include "proxmark3.h"
#include "../common/iso14443crc.h"
#include "iso14443crc.h"
#include "data.h"
#include "ui.h"
#include "cmdparser.h"
#include "../include/common.h"
#include "common.h"
#include "util.h"
#include "mifarehost.h"
@ -53,5 +53,5 @@ int CmdHF14AMfCGetBlk(const char* cmd);
int CmdHF14AMfCGetSc(const char* cmd);
int CmdHF14AMfCLoad(const char* cmd);
int CmdHF14AMfCSave(const char* cmd);
int GetCardSize();
#endif

View file

@ -1,685 +0,0 @@
//-----------------------------------------------------------------------------
// Copyright (C) 2014 Iceman
//
// This code is licensed to you under the terms of the GNU GPL, version 2 or,
// at your option, any later version. See the LICENSE.txt file for the text of
// the license.
//-----------------------------------------------------------------------------
// High frequency MIFARE Desfire commands
//-----------------------------------------------------------------------------
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <openssl/des.h>
#include "cmdmain.h"
#include "proxmark3.h"
#include "../include/common.h"
#include "../include/mifare.h"
#include "../common/iso14443crc.h"
#include "data.h"
#include "ui.h"
#include "cmdparser.h"
#include "util.h"
#include "cmdhfmfdes.h"
uint8_t CMDPOS = 0;
uint8_t LENPOS = 1;
uint8_t key_zero_data[16] = { 0x00 };
uint8_t key_ones_data[16] = { 0x01 };
uint8_t key_defa_data[16] = { 0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f };
uint8_t key_picc_data[16] = { 0x40,0x41,0x42,0x43,0x44,0x45,0x46,0x47,0x48,0x49,0x4a,0x4b,0x4c,0x4d,0x4e,0x4f };
static int CmdHelp(const char *Cmd);
static void xor(unsigned char * dst, unsigned char * src, size_t len);
static int32_t le24toh (uint8_t data[3]);
int CmdHF14ADesWb(const char *Cmd)
{
/* uint8_t blockNo = 0;
uint8_t keyType = 0;
uint8_t key[6] = {0, 0, 0, 0, 0, 0};
uint8_t bldata[16] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
char cmdp = 0x00;
if (strlen(Cmd)<3) {
PrintAndLog("Usage: hf mf wrbl <block number> <key A/B> <key (12 hex symbols)> <block data (32 hex symbols)>");
PrintAndLog(" sample: hf mf wrbl 0 A FFFFFFFFFFFF 000102030405060708090A0B0C0D0E0F");
return 0;
}
blockNo = param_get8(Cmd, 0);
cmdp = param_getchar(Cmd, 1);
if (cmdp == 0x00) {
PrintAndLog("Key type must be A or B");
return 1;
}
if (cmdp != 'A' && cmdp != 'a') keyType = 1;
if (param_gethex(Cmd, 2, key, 12)) {
PrintAndLog("Key must include 12 HEX symbols");
return 1;
}
if (param_gethex(Cmd, 3, bldata, 32)) {
PrintAndLog("Block data must include 32 HEX symbols");
return 1;
}
PrintAndLog("--block no:%02x key type:%02x key:%s", blockNo, keyType, sprint_hex(key, 6));
PrintAndLog("--data: %s", sprint_hex(bldata, 16));
UsbCommand c = {CMD_MIFARE_WRITEBL, {blockNo, keyType, 0}};
memcpy(c.d.asBytes, key, 6);
memcpy(c.d.asBytes + 10, bldata, 16);
SendCommand(&c);
UsbCommand resp;
if (WaitForResponseTimeout(CMD_ACK,&resp,1500)) {
uint8_t isOK = resp.arg[0] & 0xff;
PrintAndLog("isOk:%02x", isOK);
} else {
PrintAndLog("Command execute timeout");
}
*/
return 0;
}
int CmdHF14ADesRb(const char *Cmd)
{
// uint8_t blockNo = 0;
// uint8_t keyType = 0;
// uint8_t key[6] = {0, 0, 0, 0, 0, 0};
// char cmdp = 0x00;
// if (strlen(Cmd)<3) {
// PrintAndLog("Usage: hf mf rdbl <block number> <key A/B> <key (12 hex symbols)>");
// PrintAndLog(" sample: hf mf rdbl 0 A FFFFFFFFFFFF ");
// return 0;
// }
// blockNo = param_get8(Cmd, 0);
// cmdp = param_getchar(Cmd, 1);
// if (cmdp == 0x00) {
// PrintAndLog("Key type must be A or B");
// return 1;
// }
// if (cmdp != 'A' && cmdp != 'a') keyType = 1;
// if (param_gethex(Cmd, 2, key, 12)) {
// PrintAndLog("Key must include 12 HEX symbols");
// return 1;
// }
// PrintAndLog("--block no:%02x key type:%02x key:%s ", blockNo, keyType, sprint_hex(key, 6));
// UsbCommand c = {CMD_MIFARE_READBL, {blockNo, keyType, 0}};
// memcpy(c.d.asBytes, key, 6);
// SendCommand(&c);
// UsbCommand resp;
// if (WaitForResponseTimeout(CMD_ACK,&resp,1500)) {
// uint8_t isOK = resp.arg[0] & 0xff;
// uint8_t * data = resp.d.asBytes;
// if (isOK)
// PrintAndLog("isOk:%02x data:%s", isOK, sprint_hex(data, 16));
// else
// PrintAndLog("isOk:%02x", isOK);
// } else {
// PrintAndLog("Command execute timeout");
// }
return 0;
}
int CmdHF14ADesInfo(const char *Cmd){
UsbCommand c = {CMD_MIFARE_DESFIRE_INFO};
SendCommand(&c);
UsbCommand resp;
if ( !WaitForResponseTimeout(CMD_ACK,&resp,1500) ) {
PrintAndLog("Command execute timeout");
return 0;
}
uint8_t isOK = resp.arg[0] & 0xff;
if ( !isOK ){
PrintAndLog("Command unsuccessful");
return 0;
}
PrintAndLog("");
PrintAndLog("-- Desfire Information --------------------------------------");
PrintAndLog("-------------------------------------------------------------");
PrintAndLog(" UID : %s",sprint_hex(resp.d.asBytes, 7));
PrintAndLog(" Batch number : %s",sprint_hex(resp.d.asBytes+28,5));
PrintAndLog(" Production date : week %02x, 20%02x",resp.d.asBytes[33], resp.d.asBytes[34]);
PrintAndLog(" -----------------------------------------------------------");
PrintAndLog(" Hardware Information");
PrintAndLog(" Vendor Id : %s", GetVendorStr(resp.d.asBytes[7]));
PrintAndLog(" Type : 0x%02X",resp.d.asBytes[8]);
PrintAndLog(" Subtype : 0x%02X",resp.d.asBytes[9]);
PrintAndLog(" Version : %d.%d",resp.d.asBytes[10], resp.d.asBytes[11]);
PrintAndLog(" Storage size : %s",GetCardSizeStr(resp.d.asBytes[12]));
PrintAndLog(" Protocol : %s",GetProtocolStr(resp.d.asBytes[13]));
PrintAndLog(" -----------------------------------------------------------");
PrintAndLog(" Software Information");
PrintAndLog(" Vendor Id : %s",GetVendorStr(resp.d.asBytes[14]));
PrintAndLog(" Type : 0x%02X",resp.d.asBytes[15]);
PrintAndLog(" Subtype : 0x%02X",resp.d.asBytes[16]);
PrintAndLog(" Version : %d.%d",resp.d.asBytes[17], resp.d.asBytes[18]);
PrintAndLog(" storage size : %s", GetCardSizeStr(resp.d.asBytes[19]));
PrintAndLog(" Protocol : %s", GetProtocolStr(resp.d.asBytes[20]));
PrintAndLog("-------------------------------------------------------------");
// Master Key settings
GetKeySettings(NULL);
// Free memory on card
c.cmd = CMD_MIFARE_DESFIRE;
c.arg[0] = (INIT | DISCONNECT);
c.arg[1] = 0x01;
c.d.asBytes[0] = GET_FREE_MEMORY;
SendCommand(&c);
if ( !WaitForResponseTimeout(CMD_ACK,&resp,1500)) {
return 0;
}
uint8_t tmp[3];
memcpy(tmp, resp.d.asBytes+3,3);
PrintAndLog(" Available free memory on card : %d bytes", le24toh( tmp ));
PrintAndLog("-------------------------------------------------------------");
/*
Card Master key (CMK) 0x00 AID = 00 00 00 (card level)
Application Master Key (AMK) 0x00 AID != 00 00 00
Application keys (APK) 0x01-0x0D
Application free 0x0E
Application never 0x0F
ACCESS RIGHTS:
keys 0,1,2,3 C
keys 4,5,6,7 RW
keys 8,9,10,11 W
keys 12,13,14,15 R
*/
return 1;
}
char * GetVendorStr( uint8_t id){
static char buf[30];
char *retStr = buf;
if ( id == 0x04 )
sprintf(retStr, "0x%02X (NXP)",id);
else
sprintf(retStr,"0x%02X (Unknown)",id);
return buf;
}
/*
The 7 MSBits (= n) code the storage size itself based on 2^n,
the LSBit is set to '0' if the size is exactly 2^n
and set to '1' if the storage size is between 2^n and 2^(n+1).
For this version of DESFire the 7 MSBits are set to 0x0C (2^12 = 4096) and the LSBit is '0'.
*/
char * GetCardSizeStr( uint8_t fsize ){
static char buf[30];
char *retStr = buf;
uint16_t usize = 1 << ((fsize >>1) + 1);
uint16_t lsize = 1 << (fsize >>1);
// is LSB set?
if ( fsize & (1 << 0 ) )
sprintf(retStr, "0x%02X (%d - %d bytes)",fsize, usize, lsize);
else
sprintf(retStr, "0x%02X (%d bytes)", fsize, lsize);
return buf;
}
char * GetProtocolStr(uint8_t id){
static char buf[30];
char *retStr = buf;
if ( id == 0x05)
sprintf(retStr,"0x%02X (ISO 14443-3, 14443-4)", id);
else
sprintf(retStr,"0x%02X", id);
return buf;
}
void GetKeySettings( uint8_t *aid){
char messStr[512] = {0x00};
char *str = messStr;
uint8_t isOK = 0;
uint32_t options = NONE;
UsbCommand c;
UsbCommand resp;
//memset(messStr, 0x00, 512);
c.cmd = CMD_MIFARE_DESFIRE;
if ( aid == NULL ){
PrintAndLog(" CMK - PICC, Card Master Key settings ");
PrintAndLog("");
c.arg[CMDPOS] = (INIT | DISCONNECT);
c.arg[LENPOS] = 0x01;
c.d.asBytes[0] = GET_KEY_SETTINGS; // 0x45
SendCommand(&c);
if ( !WaitForResponseTimeout(CMD_ACK,&resp,1000) ) {return;}
isOK = resp.arg[0] & 0xff;
if ( !isOK ){
PrintAndLog(" Can't select master application");
return;
}
str = (resp.d.asBytes[3] & (1 << 3 )) ? "YES":"NO";
PrintAndLog(" [0x08] Configuration changeable : %s", str);
str = (resp.d.asBytes[3] & (1 << 2 )) ? "NO":"YES";
PrintAndLog(" [0x04] CMK required for create/delete : %s",str);
str = (resp.d.asBytes[3] & (1 << 1 )) ? "NO":"YES";
PrintAndLog(" [0x02] Directory list access with CMK : %s",str);
str = (resp.d.asBytes[3] & (1 << 0 )) ? "YES" : "NO";
PrintAndLog(" [0x01] CMK is changeable : %s", str);
c.arg[LENPOS] = 0x02; //LEN
c.d.asBytes[0] = GET_KEY_VERSION; //0x64
c.d.asBytes[1] = 0x00;
SendCommand(&c);
if ( !WaitForResponseTimeout(CMD_ACK,&resp,1000) ) {
return;
}
isOK = resp.arg[0] & 0xff;
if ( !isOK ){
PrintAndLog(" Can't read key-version");
return;
}
PrintAndLog("");
PrintAndLog(" Max number of keys : %d", resp.d.asBytes[4]);
PrintAndLog(" Master key Version : %d (0x%02x)", resp.d.asBytes[3], resp.d.asBytes[3]);
PrintAndLog(" ----------------------------------------------------------");
c.arg[LENPOS] = 0x02; //LEN
c.d.asBytes[0] = AUTHENTICATE; //0x0A
c.d.asBytes[1] = 0x00; // KEY 0
SendCommand(&c);
if ( !WaitForResponseTimeout(CMD_ACK,&resp,1000) ) {return;}
isOK = resp.d.asBytes[2] & 0xff;
PrintAndLog(" [0x0A] Authenticate : %s", ( isOK==0xAE ) ? "NO":"YES");
c.d.asBytes[0] = AUTHENTICATE_ISO; //0x1A
SendCommand(&c);
if ( !WaitForResponseTimeout(CMD_ACK,&resp,1000) ) {return;}
isOK = resp.d.asBytes[2] & 0xff;
PrintAndLog(" [0x1A] Authenticate ISO : %s", ( isOK==0xAE ) ? "NO":"YES");
c.d.asBytes[0] = AUTHENTICATE_AES; //0xAA
SendCommand(&c);
if ( !WaitForResponseTimeout(CMD_ACK,&resp,1000) ) {return;}
isOK = resp.d.asBytes[2] & 0xff;
PrintAndLog(" [0xAA] Authenticate AES : %s", ( isOK==0xAE ) ? "NO":"YES");
PrintAndLog("");
PrintAndLog(" ----------------------------------------------------------");
} else {
PrintAndLog(" AMK - Application Master Key settings");
// SELECT AID
c.arg[0] = (INIT | CLEARTRACE);
c.arg[LENPOS] = 0x04;
c.d.asBytes[0] = SELECT_APPLICATION; // 0x5a
memcpy(c.d.asBytes+1, aid, 3);
SendCommand(&c);
if (!WaitForResponseTimeout(CMD_ACK,&resp,1500) ) {
PrintAndLog(" Timed-out");
return;
}
isOK = resp.arg[0] & 0xff;
if ( !isOK ){
PrintAndLog(" Can't select AID: %s",sprint_hex(aid,3));
return;
}
// KEY SETTINGS
options = NONE;
c.arg[0] = options;
c.arg[LENPOS] = 0x01;
c.d.asBytes[0] = GET_KEY_SETTINGS; // 0x45
SendCommand(&c);
if ( !WaitForResponseTimeout(CMD_ACK,&resp,1500) ) {
return;
}
isOK = resp.arg[0] & 0xff;
if ( !isOK ){
PrintAndLog(" Can't read Application Master key settings");
} else {
// Access rights.
uint8_t rights = (resp.d.asBytes[3] >> 4 && 0xff);
switch (rights){
case 0x00:
str = "AMK authentication is necessary to change any key (default)";
break;
case 0x0e:
str = "Authentication with the key to be changed (same KeyNo) is necessary to change a key";
break;
case 0x0f:
str = "All keys (except AMK,see Bit0) within this application are frozen";
break;
default:
str = "Authentication with the specified key is necessary to change any ley. A change key and a PICC master key (CMK) can only be changed after authentication with the master key. For keys other then the master or change key, an authentication with the same key is needed.";
break;
}
PrintAndLog("Changekey Access rights");
PrintAndLog("-- %s",str);
PrintAndLog("");
// same as CMK
str = (resp.d.asBytes[3] & (1 << 3 )) ? "YES":"NO";
PrintAndLog(" 0x08 Configuration changeable : %s", str);
str = (resp.d.asBytes[3] & (1 << 2 )) ? "NO":"YES";
PrintAndLog(" 0x04 AMK required for create/delete : %s",str);
str = (resp.d.asBytes[3] & (1 << 1 )) ? "NO":"YES";
PrintAndLog(" 0x02 Directory list access with AMK : %s",str);
str = (resp.d.asBytes[3] & (1 << 0 )) ? "YES" : "NO";
PrintAndLog(" 0x01 AMK is changeable : %s", str);
}
// KEY VERSION - AMK
c.arg[0] = NONE;
c.arg[LENPOS] = 0x02;
c.d.asBytes[0] = GET_KEY_VERSION; //0x64
c.d.asBytes[1] = 0x00;
SendCommand(&c);
if ( !WaitForResponseTimeout(CMD_ACK,&resp,1500) ) {
PrintAndLog(" Timed-out");
return;
}
int numOfKeys;
isOK = resp.arg[0] & 0xff;
if ( !isOK ){
PrintAndLog(" Can't read Application Master key version. Trying all keys");
numOfKeys = MAX_NUM_KEYS;
}
else{
numOfKeys = resp.d.asBytes[4];
PrintAndLog("");
PrintAndLog(" Max number of keys : %d", numOfKeys );
PrintAndLog(" Application Master key Version : %d (0x%02x)", resp.d.asBytes[3], resp.d.asBytes[3]);
PrintAndLog("-------------------------------------------------------------");
}
// LOOP over numOfKeys that we got before.
// From 0x01 to numOfKeys. We already got 0x00. (AMK)
for(int i=0x01; i<=0x0f; ++i){
}
}
}
int CmdHF14ADesEnumApplications(const char *Cmd){
uint8_t isOK = 0x00;
uint8_t aid[3];
uint32_t options = (INIT | DISCONNECT);
UsbCommand c = {CMD_MIFARE_DESFIRE, {options , 0x01 }};
c.d.asBytes[0] = GET_APPLICATION_IDS; //0x6a
SendCommand(&c);
UsbCommand resp;
if ( !WaitForResponseTimeout(CMD_ACK,&resp,1500) ) {
return 0;
}
isOK = resp.arg[0] & 0xff;
if ( !isOK ){
PrintAndLog("Command unsuccessful");
return 0;
}
PrintAndLog("");
PrintAndLog("-- Desfire Enumerate Applications ---------------------------");
PrintAndLog("-------------------------------------------------------------");
UsbCommand respAid;
UsbCommand respFiles;
uint8_t num = 0;
int max = resp.arg[1] -3 -2;
for(int i=3; i<=max; i+=3){
PrintAndLog(" Aid %d : %02X %02X %02X ",num ,resp.d.asBytes[i],resp.d.asBytes[i+1],resp.d.asBytes[i+2]);
num++;
aid[0] = resp.d.asBytes[i];
aid[1] = resp.d.asBytes[i+1];
aid[2] = resp.d.asBytes[i+2];
GetKeySettings(aid);
// Select Application
c.arg[CMDPOS] = INIT;
c.arg[LENPOS] = 0x04;
c.d.asBytes[0] = SELECT_APPLICATION; // 0x5a
c.d.asBytes[1] = resp.d.asBytes[i];
c.d.asBytes[2] = resp.d.asBytes[i+1];
c.d.asBytes[3] = resp.d.asBytes[i+2];
SendCommand(&c);
if (!WaitForResponseTimeout(CMD_ACK,&respAid,1500) ) {
PrintAndLog(" Timed-out");
continue;
}
isOK = respAid.d.asBytes[2] & 0xff;
if ( isOK != 0x00 ){
PrintAndLog(" Can't select AID: %s",sprint_hex(resp.d.asBytes+i,3));
continue;
}
// Get File IDs
c.arg[CMDPOS] = NONE;
c.arg[LENPOS] = 0x01;
c.d.asBytes[0] = GET_FILE_IDS; // 0x6f
SendCommand(&c);
if ( !WaitForResponseTimeout(CMD_ACK,&respFiles,1500) ) {
PrintAndLog(" Timed-out");
continue;
} else {
isOK = respFiles.d.asBytes[2] & 0xff;
if ( !isOK ){
PrintAndLog(" Can't get file ids ");
} else {
int respfileLen = resp.arg[1]-3-2;
for (int j=0; j< respfileLen; ++j){
PrintAndLog(" Fileid %d :", resp.d.asBytes[j+3]);
}
}
}
// Get ISO File IDs
c.arg[CMDPOS] = DISCONNECT;
c.arg[LENPOS] = 0x01;
c.d.asBytes[0] = GET_ISOFILE_IDS; // 0x61
SendCommand(&c);
if ( !WaitForResponseTimeout(CMD_ACK,&respFiles,1500) ) {
PrintAndLog(" Timed-out");
continue;
} else {
isOK = respFiles.d.asBytes[2] & 0xff;
if ( !isOK ){
PrintAndLog(" Can't get ISO file ids ");
} else {
int respfileLen = resp.arg[1]-3-2;
for (int j=0; j< respfileLen; ++j){
PrintAndLog(" ISO Fileid %d :", resp.d.asBytes[j+3]);
}
}
}
}
PrintAndLog("-------------------------------------------------------------");
return 1;
}
// MIAFRE DesFire Authentication
//
#define BUFSIZE 256
int CmdHF14ADesAuth(const char *Cmd){
// NR DESC KEYLENGHT
// ------------------------
// 1 = DES 8
// 2 = 3DES 16
// 3 = 3K 3DES 24
// 4 = AES 16
uint8_t keylength = 8;
unsigned char key[24];
if (strlen(Cmd)<3) {
PrintAndLog("Usage: hf mfdes auth <1|2|3> <1|2|3|4> <keyno> <key> ");
PrintAndLog(" Auth modes");
PrintAndLog(" 1 = normal, 2 = iso, 3 = aes");
PrintAndLog(" Crypto");
PrintAndLog(" 1 = DES 2 = 3DES 3 = 3K3DES 4 = AES");
PrintAndLog("");
PrintAndLog(" sample: hf mfdes auth 1 1 0 11223344");
PrintAndLog(" sample: hf mfdes auth 3 4 0 404142434445464748494a4b4c4d4e4f");
return 0;
}
uint8_t cmdAuthMode = param_get8(Cmd,0);
uint8_t cmdAuthAlgo = param_get8(Cmd,1);
uint8_t cmdKeyNo = param_get8(Cmd,2);
switch (cmdAuthMode)
{
case 1:
if ( cmdAuthAlgo != 1 && cmdAuthAlgo != 2) {
PrintAndLog("Crypto algo not valid for the auth mode");
return 1;
}
break;
case 2:
if ( cmdAuthAlgo != 1 && cmdAuthAlgo != 2 && cmdAuthAlgo != 3) {
PrintAndLog("Crypto algo not valid for the auth mode");
return 1;
}
break;
case 3:
if ( cmdAuthAlgo != 4) {
PrintAndLog("Crypto algo not valid for the auth mode");
return 1;
}
break;
default:
PrintAndLog("Wrong Auth mode");
return 1;
break;
}
switch (cmdAuthAlgo){
case 2:
keylength = 16;
PrintAndLog("3DES selected");
break;
case 3:
keylength = 24;
PrintAndLog("3 key 3DES selected");
break;
case 4:
keylength = 16;
PrintAndLog("AES selected");
break;
default:
cmdAuthAlgo = 1;
keylength = 8;
PrintAndLog("DES selected");
break;
}
// key
if (param_gethex(Cmd, 3, key, keylength*2)) {
PrintAndLog("Key must include %d HEX symbols", keylength);
return 1;
}
// algo, nyckellängd,
UsbCommand c = {CMD_MIFARE_DESFIRE_AUTH1, { cmdAuthMode, cmdAuthAlgo, cmdKeyNo }};
c.d.asBytes[0] = keylength;
memcpy(c.d.asBytes+1, key, keylength);
SendCommand(&c);
UsbCommand resp;
if (!WaitForResponseTimeout(CMD_ACK,&resp,3000)) {
PrintAndLog("Client command execute timeout");
return 0;
}
uint8_t isOK = resp.arg[0] & 0xff;
if ( isOK) {
uint8_t * data= resp.d.asBytes;
PrintAndLog(" Key :%s",sprint_hex(key, keylength));
PrintAndLog(" SESSION :%s",sprint_hex(data, keylength));
PrintAndLog("-------------------------------------------------------------");
//PrintAndLog(" Expected :B5 21 9E E8 1A A7 49 9D 21 96 68 7E 13 97 38 56");
} else{
PrintAndLog("Client command failed.");
}
PrintAndLog("-------------------------------------------------------------");
return 1;
}
static void xor(unsigned char * dst, unsigned char * src, size_t len) {
for( ; len > 0; len--,dst++,src++)
*dst ^= *src;
}
static int32_t le24toh (uint8_t data[3]) {
return (data[2] << 16) | (data[1] << 8) | data[0];
}
static command_t CommandTable[] =
{
{"help", CmdHelp, 1, "This help"},
{"auth", CmdHF14ADesAuth, 0, "Tries a MIFARE DesFire Authentication"},
{"rb", CmdHF14ADesRb, 0, "Read MIFARE DesFire block"},
{"wb", CmdHF14ADesWb, 0, "write MIFARE DesFire block"},
{"info", CmdHF14ADesInfo, 0, "Get MIFARE DesFire information"},
{"enum", CmdHF14ADesEnumApplications,0, "Tries enumerate all applications"},
{NULL, NULL, 0, NULL}
};
int CmdHFMFDes(const char *Cmd)
{
// flush
WaitForResponseTimeout(CMD_ACK,NULL,100);
CmdsParse(CommandTable, Cmd);
return 0;
}
int CmdHelp(const char *Cmd)
{
CmdsHelp(CommandTable);
return 0;
}

View file

@ -1,75 +0,0 @@
//-----------------------------------------------------------------------------
// Copyright (C) 2014 Iceman
//
// This code is licensed to you under the terms of the GNU GPL, version 2 or,
// at your option, any later version. See the LICENSE.txt file for the text of
// the license.
//-----------------------------------------------------------------------------
// High frequency MIFARE Desfire commands
//-----------------------------------------------------------------------------
int CmdHFMFDes(const char *Cmd);
int CmdHF14ADesAuth(const char* cmd);
int CmdHF14ADesRb(const char* cmd);
int CmdHF14ADesWb(const char* cmd);
int CmdHF14ADesInfo(const char *Cmd);
int CmdHF14ADesEnumApplications(const char *Cmd);
char * GetCardSizeStr( uint8_t fsize );
char * GetVendorStr( uint8_t id);
char * GetProtocolStr(uint8_t id);
void GetKeySettings( uint8_t * aid);
// Command options for Desfire behavior.
enum {
NONE = 0x00,
INIT = 0x01,
DISCONNECT = 0x02,
CLEARTRACE = 0x04,
BAR = 0x08,
} CmdOptions ;
#define CREATE_APPLICATION 0xca
#define DELETE_APPLICATION 0xda
#define GET_APPLICATION_IDS 0x6a
#define SELECT_APPLICATION 0x5a
#define FORMAT_PICC 0xfc
#define GET_VERSION 0x60
#define READ_DATA 0xbd
#define WRITE_DATA 0x3d
#define GET_VALUE 0x6c
#define CREDIT 0x0c
#define DEBIT 0xdc
#define LIMITED_CREDIT 0x1c
#define WRITE_RECORD 0x3b
#define READ_RECORDS 0xbb
#define CLEAR_RECORD_FILE 0xeb
#define COMMIT_TRANSACTION 0xc7
#define ABORT_TRANSACTION 0xa7
#define GET_FREE_MEMORY 0x6e
#define GET_FILE_IDS 0x6f
#define GET_ISOFILE_IDS 0x61
#define GET_FILE_SETTINGS 0xf5
#define CHANGE_FILE_SETTINGS 0x5f
#define CREATE_STD_DATA_FILE 0xcd
#define CREATE_BACKUP_DATA_FILE 0xcb
#define CREATE_VALUE_FILE 0xcc
#define CREATE_LINEAR_RECORD_FILE 0xc1
#define CREATE_CYCLIC_RECORD_FILE 0xc0
#define DELETE_FILE 0xdf
#define AUTHENTICATE 0x0a // AUTHENTICATE_NATIVE
#define AUTHENTICATE_ISO 0x1a // AUTHENTICATE_STANDARD
#define AUTHENTICATE_AES 0xaa
#define CHANGE_KEY_SETTINGS 0x54
#define GET_KEY_SETTINGS 0x45
#define CHANGE_KEY 0xc4
#define GET_KEY_VERSION 0x64
#define AUTHENTICATION_FRAME 0xAF
#define MAX_NUM_KEYS 0x0F
#define MAX_APPLICATION_COUNT 28
#define MAX_FILE_COUNT 32
#define MAX_FRAME_SIZE 60
#define NOT_YET_AUTHENTICATED 255
#define FRAME_PAYLOAD_SIZE (MAX_FRAME_SIZE - 5)

View file

@ -1,250 +0,0 @@
//-----------------------------------------------------------------------------
// 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;
}

View file

@ -1,5 +0,0 @@
static int CmdHelp(const char *Cmd);
int CmdHF14AMfDESAuth(const char *Cmd);
int CmdHFMFDesfire(const char *Cmd);
int CmdHelp(const char *Cmd);

File diff suppressed because it is too large Load diff

View file

@ -1,16 +0,0 @@
#include "cmdhfmf.h"
//standard ultralight
int CmdHF14AMfUWrBl(const char *Cmd);
int CmdHF14AMfURdBl(const char *Cmd);
int CmdHF14AMfURdCard(const char *Cmd);
int CmdHF14AMfUDump(const char *Cmd);
//Crypto Cards
int CmdHF14AMfUCRdBl(const char *Cmd);
int CmdHF14AMfUCRdCard(const char *Cmd);
int CmdHF14AMfUCDump(const char *Cmd);
int CmdHF14AMfucAuth(const char *Cmd);
void rol (uint8_t *data, const size_t len);
//general stuff
int CmdHFMFUltra(const char *Cmd);

View file

@ -13,11 +13,12 @@
#include <string.h>
#include <limits.h>
#include "ui.h"
//#include "proxusb.h"
#include "proxmark3.h"
#include "cmdparser.h"
#include "cmddata.h"
#include "cmdhw.h"
#include "cmdmain.h"
#include "cmddata.h"
/* low-level hardware control */
@ -417,7 +418,7 @@ static command_t CommandTable[] =
{"setlfdivisor", CmdSetDivisor, 0, "<19 - 255> -- Drive LF antenna at 12Mhz/(divisor+1)"},
{"setmux", CmdSetMux, 0, "<loraw|hiraw|lopkd|hipkd> -- Set the ADC mux to a specific value"},
{"tune", CmdTune, 0, "Measure antenna tuning"},
{"version", CmdVersion, 0, "Show version information about the connected Proxmark"},
{"version", CmdVersion, 0, "Show version inforation about the connected Proxmark"},
{NULL, NULL, 0, NULL}
};

View file

@ -20,7 +20,6 @@
#include "cmdmain.h"
#include "cmddata.h"
#include "cmdlf.h"
#include "cmdlfawid26.h"
#include "cmdlfhid.h"
#include "cmdlfti.h"
#include "cmdlfem4x.h"
@ -71,7 +70,7 @@ int CmdFlexdemod(const char *Cmd)
}
}
if (start == GraphTraceLen - LONG_WAIT) {
//PrintAndLog("nothing to wait for");
PrintAndLog("nothing to wait for");
return 0;
}
@ -201,7 +200,7 @@ int CmdIndalaDemod(const char *Cmd)
}
if (start == rawbit - uidlen + 1) {
//PrintAndLog("nothing to wait for");
PrintAndLog("nothing to wait for");
return 0;
}
@ -373,9 +372,6 @@ int CmdLFRead(const char *Cmd)
}
SendCommand(&c);
WaitForResponse(CMD_ACK,NULL);
CmdSamples("");
ShowGraphWindow();
return 0;
}
@ -384,8 +380,10 @@ static void ChkBitstream(const char *str)
int i;
/* convert to bitstream if necessary */
for (i = 0; i < (int)(GraphTraceLen / 2); i++){
if (GraphBuffer[i] > 1 || GraphBuffer[i] < 0) {
for (i = 0; i < (int)(GraphTraceLen / 2); i++)
{
if (GraphBuffer[i] > 1 || GraphBuffer[i] < 0)
{
CmdBitstream(str);
break;
}
@ -394,7 +392,7 @@ static void ChkBitstream(const char *str)
int CmdLFSim(const char *Cmd)
{
int i,j;
int i;
static int gap;
sscanf(Cmd, "%i", &gap);
@ -402,20 +400,18 @@ int CmdLFSim(const char *Cmd)
/* convert to bitstream if necessary */
ChkBitstream(Cmd);
printf("Sending [%d bytes]", GraphTraceLen);
for (i = 0; i < GraphTraceLen; i += USB_CMD_DATA_SIZE) {
PrintAndLog("Sending data, please wait...");
for (i = 0; i < GraphTraceLen; i += 48) {
UsbCommand c={CMD_DOWNLOADED_SIM_SAMPLES_125K, {i, 0, 0}};
for (j = 0; j < USB_CMD_DATA_SIZE; j++) {
int j;
for (j = 0; j < 48; j++) {
c.d.asBytes[j] = GraphBuffer[i+j];
}
SendCommand(&c);
WaitForResponse(CMD_ACK,NULL);
printf(".");
}
printf("\n");
PrintAndLog("Starting to simulate");
PrintAndLog("Starting simulator...");
UsbCommand c = {CMD_SIMULATE_TAG_125K, {GraphTraceLen, gap, 0}};
SendCommand(&c);
return 0;
@ -475,15 +471,6 @@ int CmdLFSnoop(const char *Cmd)
SendCommand(&c);
WaitForResponse(CMD_ACK,NULL);
#define BUFF_SIZE 8000
uint8_t data[BUFF_SIZE] = {0x00};
GetFromBigBuf(data,BUFF_SIZE,0);
WaitForResponseTimeout(CMD_ACK,NULL, 1500);
SetGraphBuf(data, BUFF_SIZE);
return 0;
}
@ -567,50 +554,24 @@ int CmdVchDemod(const char *Cmd)
int CmdLFfind(const char *Cmd)
{
int ans=0;
char cmdp = param_getchar(Cmd, 0);
if (strlen(Cmd) > 1 || cmdp == 'h' || cmdp == 'H') {
PrintAndLog("Usage: lf search <0|1>");
PrintAndLog(" <use data from Graphbuffer>, if not set, try reading data from tag.");
PrintAndLog("");
PrintAndLog(" sample: lf search");
PrintAndLog(" : lf search 1");
return 0;
}
if (!offline || (cmdp != '1') ){
if (!offline){
ans=CmdLFRead("");
} else if (GraphTraceLen < 1000) {
PrintAndLog("Data in Graphbuffer was too small.");
return 0;
ans=CmdSamples("20000");
}
if (GraphTraceLen<1000) return 0;
PrintAndLog("Checking for known tags:");
ans=Cmdaskmandemod("");
PrintAndLog("ASK_MAN: %s", (ans) ? "YES":"NO" );
if (ans>0) return 1;
ans=CmdFSKdemodHID("");
PrintAndLog("HID: %s", (ans) ? "YES":"NO" );
if (ans>0) return 1;
ans=CmdFSKdemodIO("");
PrintAndLog("IO prox: %s", (ans) ? "YES":"NO" );
if (ans>0) return 1;
//add psk and indala
ans=CmdIndalaDemod("");
PrintAndLog("Indala (64): %s", (ans) ? "YES":"NO" );
if (ans>0) return 1;
ans=CmdIndalaDemod("224");
PrintAndLog("Indala (224): %s", (ans) ? "YES":"NO" );
// ans = CmdVchDemod("");
// PrintAndLog("VeriChip: %s", (ans) ? "YES":"NO" );
// ans = CmdFlexdemod("");
// PrintAndLog("FlexPass: %s", (ans) ? "YES":"NO" );
if (!ans)
if (ans>0) return 1;
PrintAndLog("No Known Tags Found!\n");
return 0;
}
@ -618,29 +579,23 @@ 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... }"},
{"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 (UID in HEX)(option 'l' for 224 UID"},
{"vchdemod", CmdVchDemod, 1, "['clone'] -- Demodulate samples for VeriChip"},
{"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, "['h' or <divisor>] -- Read 125/134 kHz LF ID-only tag (option 'h' for 134, alternatively: f=12MHz/(divisor+1))"},
{"search", CmdLFfind, 1, "Read and Search for valid known tag (in offline mode it you can load first then search)"},
{"sim", CmdLFSim, 0, "[GAP] -- Simulate LF tag from buffer with optional GAP (in microseconds)"},
{"simbidir", CmdLFSimBidir, 0, "Simulate LF tag (with bidirectional data transmission between reader and tag)"},
{"simman", CmdLFSimManchester, 0, "<Clock> <Bitstream> [GAP] Simulate arbitrary Manchester LF tag"},
{"snoop", CmdLFSnoop, 0, "['l'|'h'|<divisor>] [trigger threshold]-- Snoop LF (l:125khz, h:134khz)"},
{"awid26", CmdLFAWID26, 1, "{ AWID26 tags }"},
{"em4x", CmdLFEM4X, 1, "{ EM4X tags }"},
{"hid", CmdLFHID, 1, "{ HID tags }"},
{"hitag", CmdLFHitag, 1, "{ Hitag tags and transponders }"},
{"io", CmdLFIO, 1, "{ ioProx tags }"},
{"pcf7931", CmdLFPCF7931, 1, "{ PCF7931 tags }"},
{"ti", CmdLFTI, 1, "{ TI tags }"},
{"t55xx", CmdLFT55XX, 1, "{ T55xx tags }"},
{"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}
};

View file

@ -1,208 +0,0 @@
//-----------------------------------------------------------------------------
//
// 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;
}

View file

@ -1,18 +0,0 @@
//-----------------------------------------------------------------------------
//
// 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

View file

@ -13,18 +13,12 @@
#include <inttypes.h>
#include "proxmark3.h"
#include "ui.h"
#include "util.h"
#include "graph.h"
#include "cmdmain.h"
#include "cmdparser.h"
#include "cmddata.h"
#include "cmdlf.h"
#include "cmdlfem4x.h"
#include "util.h"
#include "data.h"
#define LF_TRACE_BUFF_SIZE 12000
#define LF_BITSSTREAM_LEN 1000
char *global_em410xId;
static int CmdHelp(const char *Cmd);
@ -56,19 +50,23 @@ int CmdEM410xRead(const char *Cmd)
uint8_t BitStream[MAX_GRAPH_TRACE_LEN];
high = low = 0;
// get clock
clock = GetClock(Cmd, 0);
/* Detect high and lows and clock */
for (i = 0; i < GraphTraceLen; i++)
{
if (GraphBuffer[i] > high)
high = GraphBuffer[i];
else if (GraphBuffer[i] < low)
low = GraphBuffer[i];
}
// Detect high and lows and clock
DetectHighLowInGraph( &high, &low, TRUE);
/* get clock */
clock = GetClock(Cmd, high, 0);
PrintAndLog("NUMNUM");
// parity for our 4 columns
/* parity for our 4 columns */
parity[0] = parity[1] = parity[2] = parity[3] = 0;
header = rows = 0;
// manchester demodulate
/* manchester demodulate */
bit = bit2idx = 0;
for (i = 0; i < (int)(GraphTraceLen / clock); i++)
{
@ -79,9 +77,9 @@ int CmdEM410xRead(const char *Cmd)
/* Find out if we hit both high and low peaks */
for (j = 0; j < clock; j++)
{
if (GraphBuffer[(i * clock) + j] >= high)
if (GraphBuffer[(i * clock) + j] == high)
hithigh = 1;
else if (GraphBuffer[(i * clock) + j] <= low)
else if (GraphBuffer[(i * clock) + j] == low)
hitlow = 1;
/* it doesn't count if it's the first part of our read
@ -104,7 +102,7 @@ int CmdEM410xRead(const char *Cmd)
retest:
/* We go till 5 before the graph ends because we'll get that far below */
for (i = 0; i < bit2idx - 5; i++)
for (i = 1; i < bit2idx - 5; i++)
{
/* Step 2: We have our header but need our tag ID */
if (header == 9 && rows < 10)
@ -151,8 +149,6 @@ retest:
PrintAndLog("EM410x Tag ID: %s", id);
PrintAndLog("Unique Tag ID: %s", id2);
global_em410xId = id;
/* Stop any loops */
return 1;
}
@ -181,10 +177,8 @@ retest:
}
/* if we've already retested after flipping bits, return */
if (retested++){
PrintAndLog("Failed to decode");
if (retested++)
return 0;
}
/* if this didn't work, try flipping bits */
for (i = 0; i < bit2idx; i++)
@ -285,8 +279,7 @@ int CmdEM410xWatch(const char *Cmd)
{
char cmdp = param_getchar(Cmd, 0);
int read_h = (cmdp == 'h');
do
{
do {
if (ukbhit()) {
printf("\naborted via keyboard!\n");
break;
@ -294,21 +287,12 @@ int CmdEM410xWatch(const char *Cmd)
CmdLFRead(read_h ? "h" : "");
CmdSamples("6000");
} while (
!CmdEM410xRead("")
);
return 0;
}
int CmdEM410xWatchnSpoof(const char *Cmd)
{
CmdEM410xWatch(Cmd);
PrintAndLog("# Replaying : %s",global_em410xId);
CmdEM410xSim(global_em410xId);
return 0;
}
/* Read the transmitted data of an EM4x50 tag
* Format:
*
@ -523,12 +507,12 @@ int CmdEM410xWrite(const char *Cmd)
int CmdReadWord(const char *Cmd)
{
int Word = -1; //default to invalid word
int Word = 16; //default to invalid word
UsbCommand c;
sscanf(Cmd, "%d", &Word);
if ( (Word > 15) | (Word < 0) ) {
if (Word > 15) {
PrintAndLog("Word must be between 0 and 15");
return 1;
}
@ -541,34 +525,18 @@ int CmdReadWord(const char *Cmd)
c.arg[1] = Word;
c.arg[2] = 0;
SendCommand(&c);
WaitForResponse(CMD_ACK, NULL);
uint8_t data[LF_TRACE_BUFF_SIZE] = {0x00};
GetFromBigBuf(data,LF_TRACE_BUFF_SIZE,0); //3560 -- should be offset..
WaitForResponseTimeout(CMD_ACK,NULL, 1500);
for (int j = 0; j < LF_TRACE_BUFF_SIZE; j++) {
GraphBuffer[j] = ((int)data[j]);
}
GraphTraceLen = LF_TRACE_BUFF_SIZE;
uint8_t bits[LF_BITSSTREAM_LEN] = {0x00};
uint8_t * bitstream = bits;
manchester_decode(GraphBuffer, LF_TRACE_BUFF_SIZE, bitstream,LF_BITSSTREAM_LEN);
RepaintGraphWindow();
return 0;
}
int CmdReadWordPWD(const char *Cmd)
{
int Word = -1; //default to invalid word
int Word = 16; //default to invalid word
int Password = 0xFFFFFFFF; //default to blank password
UsbCommand c;
sscanf(Cmd, "%d %x", &Word, &Password);
if ( (Word > 15) | (Word < 0) ) {
if (Word > 15) {
PrintAndLog("Word must be between 0 and 15");
return 1;
}
@ -581,22 +549,6 @@ int CmdReadWordPWD(const char *Cmd)
c.arg[1] = Word;
c.arg[2] = Password;
SendCommand(&c);
WaitForResponse(CMD_ACK, NULL);
uint8_t data[LF_TRACE_BUFF_SIZE] = {0x00};
GetFromBigBuf(data,LF_TRACE_BUFF_SIZE,0); //3560 -- should be offset..
WaitForResponseTimeout(CMD_ACK,NULL, 1500);
for (int j = 0; j < LF_TRACE_BUFF_SIZE; j++) {
GraphBuffer[j] = ((int)data[j]);
}
GraphTraceLen = LF_TRACE_BUFF_SIZE;
uint8_t bits[LF_BITSSTREAM_LEN] = {0x00};
uint8_t * bitstream = bits;
manchester_decode(GraphBuffer, LF_TRACE_BUFF_SIZE, bitstream, LF_BITSSTREAM_LEN);
RepaintGraphWindow();
return 0;
}
@ -613,7 +565,7 @@ int CmdWriteWord(const char *Cmd)
return 1;
}
PrintAndLog("Writing word %d with data %08X", Word, Data);
PrintAndLog("Writting word %d with data %08X", Word, Data);
c.cmd = CMD_EM4X_WRITE_WORD;
c.d.asBytes[0] = 0x0; //Normal mode
@ -626,7 +578,7 @@ int CmdWriteWord(const char *Cmd)
int CmdWriteWordPWD(const char *Cmd)
{
int Word = 16; //default to invalid word
int Word = 8; //default to invalid word
int Data = 0xFFFFFFFF; //default to blank data
int Password = 0xFFFFFFFF; //default to blank password
UsbCommand c;
@ -638,7 +590,7 @@ int CmdWriteWordPWD(const char *Cmd)
return 1;
}
PrintAndLog("Writing word %d with data %08X and password %08X", Word, Data, Password);
PrintAndLog("Writting word %d with data %08X and password %08X", Word, Data, Password);
c.cmd = CMD_EM4X_WRITE_WORD;
c.d.asBytes[0] = 0x1; //Password mode
@ -649,283 +601,24 @@ int CmdWriteWordPWD(const char *Cmd)
return 0;
}
static command_t CommandTable[] =
{
{"help", CmdHelp, 1, "This help"},
{"410xdemod", CmdEMdemodASK, 0, "[clock rate] -- Extract ID from EM410x tag"},
{"410xread", CmdEM410xRead, 1, "[clock rate] -- Extract ID from EM410x tag"},
{"410xsim", CmdEM410xSim, 0, "<UID> -- Simulate EM410x tag"},
{"replay", MWRem4xReplay, 0, "Watches for tag and simulates manchester encoded em4x tag"},
{"410xwatch", CmdEM410xWatch, 0, "['h'] -- Watches for EM410x 125/134 kHz tags (option 'h' for 134)"},
{"410xspoof", CmdEM410xWatchnSpoof, 0, "['h'] --- Watches for EM410x 125/134 kHz tags, and replays them. (option 'h' for 134)" },
{"410xwrite", CmdEM410xWrite, 1, "<UID> <'0' T5555> <'1' T55x7> [clock rate] -- Write EM410x UID to T5555(Q5) or T55x7 tag, optionally setting clock rate"},
{"4x50read", CmdEM4x50Read, 1, "Extract data from EM4x50 tag"},
{"rd", CmdReadWord, 1, "<Word 1-15> -- Read EM4xxx word data"},
{"rdpwd", CmdReadWordPWD, 1, "<Word 1-15> <Password> -- Read EM4xxx word data in password mode "},
{"wr", CmdWriteWord, 1, "<Data> <Word 1-15> -- Write EM4xxx word data"},
{"wrpwd", CmdWriteWordPWD, 1, "<Data> <Word 1-15> <Password> -- Write EM4xxx word data in password mode"},
{"em410xdemod", CmdEMdemodASK, 0, "[clock rate] -- Extract ID from EM410x tag"},
{"em410xread", CmdEM410xRead, 1, "[clock rate] -- Extract ID from EM410x tag"},
{"em410xsim", CmdEM410xSim, 0, "<UID> -- Simulate EM410x tag"},
{"em410xwatch", CmdEM410xWatch, 0, "['h'] -- Watches for EM410x 125/134 kHz tags (option 'h' for 134)"},
{"em410xwrite", CmdEM410xWrite, 1, "<UID> <'0' T5555> <'1' T55x7> [clock rate] -- Write EM410x UID to T5555(Q5) or T55x7 tag, optionally setting clock rate"},
{"em4x50read", CmdEM4x50Read, 1, "Extract data from EM4x50 tag"},
{"readword", CmdReadWord, 1, "<Word> -- Read EM4xxx word data"},
{"readwordPWD", CmdReadWordPWD, 1, "<Word> <Password> -- Read EM4xxx word data in password mode"},
{"writeword", CmdWriteWord, 1, "<Data> <Word> -- Write EM4xxx word data"},
{"writewordPWD", CmdWriteWordPWD, 1, "<Data> <Word> <Password> -- Write EM4xxx word data in password mode"},
{NULL, NULL, 0, NULL}
};
//Confirms the parity of a bitstream as well as obtaining the data (TagID) from within the appropriate memory space.
//Arguments:
// Pointer to a string containing the desired bitsream
// Pointer to a string that will receive the decoded tag ID
// Length of the bitsream pointed at in the first argument, char* _strBitStream
//Retuns:
//1 Parity confirmed
//0 Parity not confirmed
int ConfirmEm410xTagParity( char* _strBitStream, char* pID, int LengthOfBitstream )
{
int i = 0;
int rows = 0;
int Parity[4] = {0x00};
char ID[11] = {0x00};
int k = 0;
int BitStream[70] = {0x00};
int counter = 0;
//prepare variables
for ( i = 0; i <= LengthOfBitstream; i++)
{
if (_strBitStream[i] == '1')
{
k =1;
memcpy(&BitStream[i], &k,4);
}
else if (_strBitStream[i] == '0')
{
k = 0;
memcpy(&BitStream[i], &k,4);
}
}
while ( counter < 2 )
{
//set/reset variables and counters
memset(ID,0x00,sizeof(ID));
memset(Parity,0x00,sizeof(Parity));
rows = 0;
for ( i = 9; i <= LengthOfBitstream; i++)
{
if ( rows < 10 )
{
if ((BitStream[i] ^ BitStream[i+1] ^ BitStream[i+2] ^ BitStream[i+3]) == BitStream[i+4])
{
sprintf(ID+rows, "%x", (8 * BitStream[i]) + (4 * BitStream[i+1]) + (2 * BitStream[i+2]) + (1 * BitStream[i+3]));
rows++;
/* Keep parity info and move four bits ahead*/
Parity[0] ^= BitStream[i];
Parity[1] ^= BitStream[i+1];
Parity[2] ^= BitStream[i+2];
Parity[3] ^= BitStream[i+3];
i += 4;
}
}
if ( rows == 10 )
{
if ( BitStream[i] == Parity[0] && BitStream[i+1] == Parity[1] &&
BitStream[i+2] == Parity[2] && BitStream[i+3] == Parity[3] &&
BitStream[i+4] == 0)
{
memcpy(pID,ID,strlen(ID));
return 1;
}
}
}
printf("[PARITY ->]Failed. Flipping Bits, and rechecking parity for bitstream:\n[PARITY ->]");
for (k = 0; k < LengthOfBitstream; k++)
{
BitStream[k] ^= 1;
printf("%i", BitStream[k]);
}
puts(" ");
counter++;
}
return 0;
}
//Reads and demodulates an em410x RFID tag. It further allows slight modification to the decoded bitstream
//Once a suitable bitstream has been identified, and if needed, modified, it is replayed. Allowing emulation of the
//"stolen" rfid tag.
//No meaningful returns or arguments.
int MWRem4xReplay(const char* Cmd)
{
// //header traces
// static char ArrayTraceZero[] = { '0','0','0','0','0','0','0','0','0' };
// static char ArrayTraceOne[] = { '1','1','1','1','1','1','1','1','1' };
// //local string variables
// char strClockRate[10] = {0x00};
// char strAnswer[4] = {0x00};
// char strTempBufferMini[2] = {0x00};
// //our outbound bit-stream
// char strSimulateBitStream[65] = {0x00};
// //integers
// int iClockRate = 0;
// int needle = 0;
// int j = 0;
// int iFirstHeaderOffset = 0x00000000;
// int numManchesterDemodBits=0;
// //boolean values
// bool bInverted = false;
// //pointers to strings. memory will be allocated.
// char* pstrInvertBitStream = 0x00000000;
// char* pTempBuffer = 0x00000000;
// char* pID = 0x00000000;
// char* strBitStreamBuffer = 0x00000000;
// puts("###################################");
// puts("#### Em4x Replay ##");
// puts("#### R.A.M. June 2013 ##");
// puts("###################################");
// //initialize
// CmdLFRead("");
// //Collect ourselves 10,000 samples
// CmdSamples("10000");
// puts("[->]preforming ASK demodulation\n");
// //demodulate ask
// Cmdaskdemod("0");
// iClockRate = DetectClock(0);
// sprintf(strClockRate, "%i\n",iClockRate);
// printf("[->]Detected ClockRate: %s\n", strClockRate);
// //If detected clock rate is something completely unreasonable, dont go ahead
// if ( iClockRate < 0xFFFE )
// {
// pTempBuffer = (char*)malloc(MAX_GRAPH_TRACE_LEN);
// if (pTempBuffer == 0x00000000)
// return 0;
// memset(pTempBuffer,0x00,MAX_GRAPH_TRACE_LEN);
// //Preform manchester de-modulation and display in a single line.
// numManchesterDemodBits = CmdManchesterDemod( strClockRate );
// //note: numManchesterDemodBits is set above in CmdManchesterDemod()
// if ( numManchesterDemodBits == 0 )
// return 0;
// strBitStreamBuffer = malloc(numManchesterDemodBits+1);
// if ( strBitStreamBuffer == 0x00000000 )
// return 0;
// memset(strBitStreamBuffer, 0x00, (numManchesterDemodBits+1));
// //fill strBitStreamBuffer with demodulated, string formatted bits.
// for ( j = 0; j <= numManchesterDemodBits; j++ )
// {
// sprintf(strTempBufferMini, "%i",BitStream[j]);
// strcat(strBitStreamBuffer,strTempBufferMini);
// }
// printf("[->]Demodulated Bitstream: \n%s\n", strBitStreamBuffer);
// //Reset counter and select most probable bit stream
// j = 0;
// while ( j < numManchesterDemodBits )
// {
// memset(strSimulateBitStream,0x00,64);
// //search for header of nine (9) 0's : 000000000 or nine (9) 1's : 1111 1111 1
// if ( ( strncmp(strBitStreamBuffer+j, ArrayTraceZero, sizeof(ArrayTraceZero)) == 0 ) ||
// ( strncmp(strBitStreamBuffer+j, ArrayTraceOne, sizeof(ArrayTraceOne)) == 0 ) )
// {
// iFirstHeaderOffset = j;
// memcpy(strSimulateBitStream, strBitStreamBuffer+j,64);
// printf("[->]Offset of Header");
// if ( strncmp(strBitStreamBuffer+iFirstHeaderOffset, "0", 1) == 0 )
// printf("'%s'", ArrayTraceZero );
// else
// printf("'%s'", ArrayTraceOne );
// printf(": %i\nHighlighted string : %s\n",iFirstHeaderOffset,strSimulateBitStream);
// //allow us to escape loop or choose another frame
// puts("[<-]Are we happy with this sample? [Y]es/[N]o");
// gets(strAnswer);
// if ( ( strncmp(strAnswer,"y",1) == 0 ) || ( strncmp(strAnswer,"Y",1) == 0 ) )
// {
// j = numManchesterDemodBits+1;
// break;
// }
// }
// j++;
// }
// }
// else return 0;
// //Do we want the buffer inverted?
// memset(strAnswer, 0x00, sizeof(strAnswer));
// printf("[<-]Do you wish to invert the highlighted bitstream? [Y]es/[N]o\n");
// gets(strAnswer);
// if ( ( strncmp("y", strAnswer,1) == 0 ) || ( strncmp("Y", strAnswer, 1 ) == 0 ) )
// {
// //allocate heap memory
// pstrInvertBitStream = (char*)malloc(numManchesterDemodBits);
// if ( pstrInvertBitStream != 0x00000000 )
// {
// memset(pstrInvertBitStream,0x00,numManchesterDemodBits);
// bInverted = true;
// //Invert Bitstream
// for ( needle = 0; needle <= numManchesterDemodBits; needle++ )
// {
// if (strSimulateBitStream[needle] == '0')
// strcat(pstrInvertBitStream,"1");
// else if (strSimulateBitStream[needle] == '1')
// strcat(pstrInvertBitStream,"0");
// }
// printf("[->]Inverted bitstream: %s\n", pstrInvertBitStream);
// }
// }
// //Confirm parity of selected string
// pID = (char*)malloc(11);
// if (pID != 0x00000000)
// {
// memset(pID, 0x00, 11);
// if (ConfirmEm410xTagParity(strSimulateBitStream,pID, 64) == 1)
// {
// printf("[->]Parity confirmed for selected bitstream!\n");
// printf("[->]Tag ID was detected as: [hex]:%s\n",pID );
// }
// else
// printf("[->]Parity check failed for the selected bitstream!\n");
// }
// //Spoof
// memset(strAnswer, 0x00, sizeof(strAnswer));
// printf("[<-]Do you wish to continue with the EM4x simulation? [Y]es/[N]o\n");
// gets(strAnswer);
// if ( ( strncmp(strAnswer,"y",1) == 0 ) || ( strncmp(strAnswer,"Y",1) == 0 ) )
// {
// strcat(pTempBuffer, strClockRate);
// strcat(pTempBuffer, " ");
// if (bInverted == true)
// strcat(pTempBuffer,pstrInvertBitStream);
// if (bInverted == false)
// strcat(pTempBuffer,strSimulateBitStream);
// //inform the user
// puts("[->]Starting simulation now: \n");
// //Simulate tag with prepared buffer.
// CmdLFSimManchester(pTempBuffer);
// }
// else if ( ( strcmp("n", strAnswer) == 0 ) || ( strcmp("N", strAnswer ) == 0 ) )
// printf("[->]Exiting procedure now...\n");
// else
// printf("[->]Erroneous selection\nExiting procedure now....\n");
// //Clean up -- Exit function
// //clear memory, then release pointer.
// if ( pstrInvertBitStream != 0x00000000 )
// {
// memset(pstrInvertBitStream,0x00,numManchesterDemodBits);
// free(pstrInvertBitStream);
// }
// if ( pTempBuffer != 0x00000000 )
// {
// memset(pTempBuffer,0x00,MAX_GRAPH_TRACE_LEN);
// free(pTempBuffer);
// }
// if ( pID != 0x00000000 )
// {
// memset(pID,0x00,11);
// free(pID);
// }
// if ( strBitStreamBuffer != 0x00000000 )
// {
// memset(strBitStreamBuffer,0x00,numManchesterDemodBits);
// free(strBitStreamBuffer);
// }
return 0;
}
int CmdLFEM4X(const char *Cmd)
{
CmdsParse(CommandTable, Cmd);

View file

@ -22,6 +22,5 @@ int CmdReadWord(const char *Cmd);
int CmdReadWordPWD(const char *Cmd);
int CmdWriteWord(const char *Cmd);
int CmdWriteWordPWD(const char *Cmd);
int MWRem4xReplay(const char* Cmd);
#endif

View file

@ -15,9 +15,9 @@
#include "proxmark3.h"
#include "ui.h"
#include "cmdparser.h"
#include "../include/common.h"
#include "common.h"
#include "util.h"
#include "../include/hitag2.h"
#include "hitag2.h"
#include "sleep.h"
#include "cmdmain.h"
@ -29,7 +29,7 @@ size_t nbytes(size_t nbits) {
int CmdLFHitagList(const char *Cmd)
{
uint8_t got[TRACE_BUFFER_SIZE];
uint8_t got[3000];
GetFromBigBuf(got,sizeof(got),0);
WaitForResponse(CMD_ACK,NULL);
@ -39,25 +39,11 @@ int CmdLFHitagList(const char *Cmd)
int i = 0;
int prev = -1;
int len = strlen(Cmd);
char filename[FILE_PATH_SIZE] = { 0x00 };
FILE* pf = NULL;
if (len > FILE_PATH_SIZE)
len = FILE_PATH_SIZE;
memcpy(filename, Cmd, len);
if (strlen(filename) > 0) {
if ((pf = fopen(filename,"wb")) == NULL) {
PrintAndLog("Error: Could not open file [%s]",filename);
return 1;
}
}
for (;;) {
if(i >= TRACE_BUFFER_SIZE) { break; }
if(i >= 1900) {
break;
}
bool isResponse;
int timestamp = *((uint32_t *)(got+i));
@ -82,7 +68,9 @@ int CmdLFHitagList(const char *Cmd)
if (len > 100) {
break;
}
if (i + len >= TRACE_BUFFER_SIZE) { break;}
if (i + len >= 1900) {
break;
}
uint8_t *frame = (got+i+9);
@ -115,22 +103,18 @@ int CmdLFHitagList(const char *Cmd)
line);
if (pf) {
fprintf(pf," +%7d: %3d: %s %s\n",
(prev < 0 ? 0 : (timestamp - prev)),
bits,
(isResponse ? "TAG" : " "),
line);
}
// if (pf) {
// fprintf(pf," +%7d: %3d: %s %s\n",
// (prev < 0 ? 0 : (timestamp - prev)),
// bits,
// (isResponse ? "TAG" : " "),
// line);
// }
prev = timestamp;
i += (len + 9);
}
if (pf) {
fclose(pf);
PrintAndLog("Recorded activity succesfully written to file: %s", filename);
}
return 0;
}
@ -142,14 +126,12 @@ int CmdLFHitagSnoop(const char *Cmd) {
}
int CmdLFHitagSim(const char *Cmd) {
UsbCommand c = {CMD_SIMULATE_HITAG};
char filename[FILE_PATH_SIZE] = { 0x00 };
char filename[256] = { 0x00 };
FILE* pf;
bool tag_mem_supplied;
int len = strlen(Cmd);
if (len > FILE_PATH_SIZE) len = FILE_PATH_SIZE;
memcpy(filename, Cmd, len);
param_getstr(Cmd,0,filename);
if (strlen(filename) > 0) {
if ((pf = fopen(filename,"rb+")) == NULL) {
@ -245,9 +227,9 @@ int CmdLFHitagReader(const char *Cmd) {
static command_t CommandTable[] =
{
{"help", CmdHelp, 1, "This help"},
{"list", CmdLFHitagList, 1, "<outfile> List Hitag trace history"},
{"list", CmdLFHitagList, 1, "List Hitag trace history"},
{"reader", CmdLFHitagReader, 1, "Act like a Hitag Reader"},
{"sim", CmdLFHitagSim, 1, "<infile> Simulate Hitag transponder"},
{"sim", CmdLFHitagSim, 1, "Simulate Hitag transponder"},
{"snoop", CmdLFHitagSnoop, 1, "Eavesdrop Hitag communication"},
{NULL, NULL, 0, NULL}
};

View file

@ -13,66 +13,51 @@
#include "proxmark3.h"
#include "ui.h"
#include "graph.h"
#include "cmdmain.h"
#include "cmdparser.h"
#include "cmddata.h"
#include "cmdlf.h"
#include "cmdlft55xx.h"
#include "util.h"
#include "data.h"
#define LF_TRACE_BUFF_SIZE 20000 // 32 x 32 x 10 (32 bit times numofblock (7), times clock skip..)
#define LF_BITSSTREAM_LEN 1000 // more then 1000 bits shouldn't happend.. 8block * 4 bytes * 8bits =
static int CmdHelp(const char *Cmd);
int CmdReadBlk(const char *Cmd)
{
int block = -1;
sscanf(Cmd, "%d", &block);
int Block = 8; //default to invalid block
UsbCommand c;
if ((block > 7) | (block < 0)) {
sscanf(Cmd, "%d", &Block);
if (Block > 7) {
PrintAndLog("Block must be between 0 and 7");
return 1;
}
UsbCommand c;
PrintAndLog("Reading block %d", Block);
c.cmd = CMD_T55XX_READ_BLOCK;
c.d.asBytes[0] = 0x00;
c.d.asBytes[0] = 0x0; //Normal mode
c.arg[0] = 0;
c.arg[1] = block;
c.arg[1] = Block;
c.arg[2] = 0;
SendCommand(&c);
WaitForResponse(CMD_ACK, NULL);
uint8_t data[LF_TRACE_BUFF_SIZE] = {0x00};
GetFromBigBuf(data,LF_TRACE_BUFF_SIZE,0); //3560 -- should be offset..
WaitForResponseTimeout(CMD_ACK,NULL, 1500);
for (int j = 0; j < LF_TRACE_BUFF_SIZE; j++) {
GraphBuffer[j] = (int)data[j];
}
GraphTraceLen = LF_TRACE_BUFF_SIZE;
ManchesterDemod(block);
RepaintGraphWindow();
return 0;
}
int CmdReadBlkPWD(const char *Cmd)
{
int Block = -1; //default to invalid block
int Block = 8; //default to invalid block
int Password = 0xFFFFFFFF; //default to blank Block 7
UsbCommand c;
sscanf(Cmd, "%d %x", &Block, &Password);
if ((Block > 7) | (Block < 0)) {
if (Block > 7) {
PrintAndLog("Block must be between 0 and 7");
return 1;
}
PrintAndLog("Reading page 0 block %d pwd %08X", Block, Password);
PrintAndLog("Reading block %d with password %08X", Block, Password);
c.cmd = CMD_T55XX_READ_BLOCK;
c.d.asBytes[0] = 0x1; //Password mode
@ -80,19 +65,6 @@ int CmdReadBlkPWD(const char *Cmd)
c.arg[1] = Block;
c.arg[2] = Password;
SendCommand(&c);
WaitForResponse(CMD_ACK, NULL);
uint8_t data[LF_TRACE_BUFF_SIZE] = {0x00};
GetFromBigBuf(data,LF_TRACE_BUFF_SIZE,0); //3560 -- should be offset..
WaitForResponseTimeout(CMD_ACK,NULL, 1500);
for (int j = 0; j < LF_TRACE_BUFF_SIZE; j++) {
GraphBuffer[j] = ((int)data[j]);
}
GraphTraceLen = LF_TRACE_BUFF_SIZE;
ManchesterDemod(Block);
RepaintGraphWindow();
return 0;
}
@ -147,349 +119,22 @@ int CmdWriteBlkPWD(const char *Cmd)
int CmdReadTrace(const char *Cmd)
{
char cmdp = param_getchar(Cmd, 0);
if (strlen(Cmd) > 1 || cmdp == 'h' || cmdp == 'H') {
PrintAndLog("Usage: lf t55xx trace [use data from Graphbuffer]");
PrintAndLog(" [use data from Graphbuffer], if not set, try reading data from tag.");
PrintAndLog("");
PrintAndLog(" sample: lf t55xx trace");
PrintAndLog(" sample: lf t55xx trace 1");
return 0;
}
PrintAndLog("Reading traceability data");
if ( strlen(Cmd)==0){
UsbCommand c = {CMD_T55XX_READ_TRACE, {0, 0, 0}};
SendCommand(&c);
WaitForResponse(CMD_ACK, NULL);
uint8_t data[LF_TRACE_BUFF_SIZE] = {0x00};
GetFromBigBuf(data,LF_TRACE_BUFF_SIZE,0); //3560 -- should be offset..
WaitForResponseTimeout(CMD_ACK,NULL, 1500);
for (int j = 0; j < LF_TRACE_BUFF_SIZE; j++) {
GraphBuffer[j] = ((int)data[j]);
}
GraphTraceLen = LF_TRACE_BUFF_SIZE;
}
uint8_t bits[LF_BITSSTREAM_LEN] = {0x00};
uint8_t * bitstream = bits;
manchester_decode(GraphBuffer, LF_TRACE_BUFF_SIZE, bitstream, LF_BITSSTREAM_LEN);
RepaintGraphWindow();
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 );
PrintAndLog(" Manufactured");
PrintAndLog(" Year/Quarter : %d/%d",2000+year, quarter );
PrintAndLog(" Lot ID : %d", lotid );
PrintAndLog(" Wafer number : %d", wafer);
PrintAndLog(" Die Number : %d", dw);
PrintAndLog("-------------------------------------------------------------");
PrintAndLog(" Raw Data - Page 1");
PrintAndLog(" Block 0 : 0x%08X %s", bl0, sprint_bin(bitstream+5,32) );
PrintAndLog(" Block 0 : 0x%08X %s", bl1, sprint_bin(bitstream+37,32) );
PrintAndLog("-------------------------------------------------------------");
/*
TRACE - BLOCK O
Bits Definition HEX
1-8 ACL Allocation class (ISO/IEC 15963-1) 0xE0
9-16 MFC Manufacturer ID (ISO/IEC 7816-6) 0x15 Atmel Corporation
17-21 CID 0x1 = Atmel ATA5577M1 0x2 = Atmel ATA5577M2
22-24 ICR IC revision
25-28 YEAR (BCD encoded) 9 (= 2009)
29-30 QUARTER 1,2,3,4
31-32 LOT ID
TRACE - BLOCK 1
1-12 LOT ID
13-17 Wafer number
18-32 DW, die number sequential
*/
return 0;
}
int CmdInfo(const char *Cmd){
/*
Page 0 Block 0 Configuration data.
Normal mode
Extended mode
*/
char cmdp = param_getchar(Cmd, 0);
if (strlen(Cmd) > 1 || cmdp == 'h' || cmdp == 'H') {
PrintAndLog("Usage: lf t55xx info [use data from Graphbuffer]");
PrintAndLog(" [use data from Graphbuffer], if not set, try reading data from tag.");
PrintAndLog("");
PrintAndLog(" sample: lf t55xx info");
PrintAndLog(" sample: lf t55xx info 1");
return 0;
}
if ( strlen(Cmd) == 0 ){
CmdReadBlk("0");
}
uint8_t bits[LF_BITSSTREAM_LEN] = {0x00};
manchester_decode(GraphBuffer, LF_TRACE_BUFF_SIZE, bits, LF_BITSSTREAM_LEN);
uint8_t si = 5;
uint32_t bl0 = PackBits(si, 32, bits);
uint32_t safer = PackBits(si, 4, bits); si += 4;
uint32_t resv = PackBits(si, 7, bits); si += 7;
uint32_t dbr = PackBits(si, 3, bits); si += 3;
uint32_t extend = PackBits(si, 1, bits); si += 1;
uint32_t datamodulation = PackBits(si, 5, bits); si += 5;
uint32_t pskcf = PackBits(si, 2, bits); si += 2;
uint32_t aor = PackBits(si, 1, bits); si += 1;
uint32_t otp = PackBits(si, 1, bits); si += 1;
uint32_t maxblk = PackBits(si, 3, bits); si += 3;
uint32_t pwd = PackBits(si, 1, bits); si += 1;
uint32_t sst = PackBits(si, 1, bits); si += 1;
uint32_t fw = PackBits(si, 1, bits); si += 1;
uint32_t inv = PackBits(si, 1, bits); si += 1;
uint32_t por = PackBits(si, 1, bits); si += 1;
PrintAndLog("");
PrintAndLog("-- T55xx Configuration --------------------------------------");
PrintAndLog("-------------------------------------------------------------");
PrintAndLog(" Safer key : %s", GetSaferStr(safer));
PrintAndLog(" reserved : %d", resv);
PrintAndLog(" Data bit rate : %s", GetBitRateStr(dbr));
PrintAndLog(" eXtended mode : %s", (extend) ? "Yes - Warning":"No");
PrintAndLog(" Modulation : %s", GetModulationStr(datamodulation) );
PrintAndLog(" PSK clock freq : %d", pskcf);
PrintAndLog(" AOR - Answer on Request : %s", (aor) ? "Yes":"No");
PrintAndLog(" OTP - One Time Pad : %s", (otp) ? "Yes - Warning":"No" );
PrintAndLog(" Max block : %d", maxblk);
PrintAndLog(" Password mode : %s", (pwd) ? "Yes":"No");
PrintAndLog(" Sequence Start Terminator : %s", (sst) ? "Yes":"No");
PrintAndLog(" Fast Write : %s", (fw) ? "Yes":"No");
PrintAndLog(" Inverse data : %s", (inv) ? "Yes":"No");
PrintAndLog(" POR-Delay : %s", (por) ? "Yes":"No");
PrintAndLog("-------------------------------------------------------------");
PrintAndLog(" Raw Data - Page 0");
PrintAndLog(" Block 0 : 0x%08X %s", bl0, sprint_bin(bits+5,32) );
PrintAndLog("-------------------------------------------------------------");
return 0;
}
int CmdDump(const char *Cmd){
char cmdp = param_getchar(Cmd, 0);
char s[20];
uint8_t pwd[4] = {0x00};
bool hasPwd = ( strlen(Cmd) > 0);
if ( cmdp == 'h' || cmdp == 'H') {
PrintAndLog("Usage: lf t55xx dump <password>");
PrintAndLog(" sample: lf t55xx dump FFFFFFFF");
return 0;
}
if ( hasPwd ){
if (param_gethex(Cmd, 0, pwd, 8)) {
PrintAndLog("password must include 8 HEX symbols");
return 0;
}
}
for ( int i = 0; i <8; ++i){
memset(s,0,sizeof(s));
if ( hasPwd ) {
sprintf(s,"%d %02x%02x%02x%02x", i, pwd[0],pwd[1],pwd[2],pwd[3]);
CmdReadBlkPWD(s);
} else {
sprintf(s,"%d", i);
CmdReadBlk(s);
}
}
return 0;
}
int CmdIceFsk(const char *Cmd){
if (!HasGraphData()) return 0;
iceFsk3(GraphBuffer, LF_TRACE_BUFF_SIZE);
RepaintGraphWindow();
return 0;
}
int CmdIceManchester(const char *Cmd){
ManchesterDemod( -1);
return 0;
}
int ManchesterDemod(int blockNum){
if (!HasGraphData()) return 0;
uint8_t sizebyte = 32;
// the value 5 was selected during empirical studies of the decoded data. Some signal noise to skip.
uint8_t offset = 5;
uint32_t blockData;
uint8_t bits[LF_BITSSTREAM_LEN] = {0x00};
uint8_t * bitstream = bits;
//manchester_decode(GraphBuffer, LF_TRACE_BUFF_SIZE, bitstream, LF_BITSSTREAM_LEN);
manchester_decode(GraphBuffer, LF_TRACE_BUFF_SIZE, bits, LF_BITSSTREAM_LEN);
//blockData = PackBits(offset, sizebyte, bitstream);
blockData = PackBits(offset, sizebyte, bits);
if ( blockNum < 0)
PrintAndLog(" Decoded : 0x%08X %s", blockData, sprint_bin(bitstream+offset,sizebyte) );
else
PrintAndLog(" Block %d : 0x%08X %s", blockNum, blockData, sprint_bin(bitstream+offset,sizebyte) );
return 0;
}
char * GetBitRateStr(uint32_t id){
static char buf[40];
char *retStr = buf;
switch (id){
case 0:
sprintf(retStr,"%d - RF/8",id);
break;
case 1:
sprintf(retStr,"%d - RF/16",id);
break;
case 2:
sprintf(retStr,"%d - RF/32",id);
break;
case 3:
sprintf(retStr,"%d - RF/40",id);
break;
case 4:
sprintf(retStr,"%d - RF/50",id);
break;
case 5:
sprintf(retStr,"%d - RF/64",id);
break;
case 6:
sprintf(retStr,"%d - RF/100",id);
break;
case 7:
sprintf(retStr,"%d - RF/128",id);
break;
default:
sprintf(retStr,"%d - (Unknown)",id);
break;
}
return buf;
}
char * GetSaferStr(uint32_t id){
static char buf[40];
char *retStr = buf;
sprintf(retStr,"%d",id);
if (id == 6) {
sprintf(retStr,"%d - pasdwd",id);
}
if (id == 9 ){
sprintf(retStr,"%d - testmode ",id);
}
return buf;
}
char * GetModulationStr( uint32_t id){
static char buf[40];
char *retStr = buf;
switch (id){
case 0:
sprintf(retStr,"%d - DIRECT (ASK/NRZ)",id);
break;
case 1:
sprintf(retStr,"%d - PSK 1 phase change when input changes",id);
break;
case 2:
sprintf(retStr,"%d - PSK 2 phase change on bitclk if input high",id);
break;
case 3:
sprintf(retStr,"%d - PSK 3 phase change on rising edge of input",id);
break;
case 4:
sprintf(retStr,"%d - FSK 1 RF/8 RF/5",id);
break;
case 5:
sprintf(retStr,"%d - FSK 2 RF/8 RF/10",id);
break;
case 6:
sprintf(retStr,"%d - FSK 1a RF/5 RF/8",id);
break;
case 7:
sprintf(retStr,"%d - FSK 2a RF/10 RF/8",id);
break;
case 8:
sprintf(retStr,"%d - Manschester",id);
break;
case 16:
sprintf(retStr,"%d - Biphase",id);
break;
case 17:
sprintf(retStr,"%d - Reserved",id);
break;
default:
sprintf(retStr,"0x%02X (Unknown)",id);
break;
}
return buf;
}
uint32_t PackBits(uint8_t start, uint8_t len, uint8_t* bits){
int i = start;
int j = len-1;
if (len > 32) {
return 0;
}
uint32_t tmp = 0;
for (; j >= 0; --j, ++i){
tmp |= bits[i] << j;
}
return tmp;
}
static command_t CommandTable[] =
{
{"help", CmdHelp, 1, "This help"},
{"rd", CmdReadBlk, 0, "<block> -- Read T55xx block data (page 0)"},
{"rdpwd", CmdReadBlkPWD, 0, "<block> <password> -- Read T55xx block data with password mode"},
{"wr", CmdWriteBlk, 0, "<data> <block> -- Write T55xx block data (page 0)"},
{"wrpwd", CmdWriteBlkPWD, 0, "<data> <block> <password> -- Write T55xx block data with password"},
{"trace", CmdReadTrace, 0, "[1] Read T55xx traceability data (page 1/ blk 0-1)"},
{"info", CmdInfo, 0, "[1] Read T55xx configuration data (page 0/ blk 0)"},
{"dump", CmdDump, 0, "[password] Dump T55xx card block 0-7. optional with password"},
{"fsk", CmdIceFsk, 0, "FSK demod"},
{"man", CmdIceManchester, 0, "Manchester demod (with SST)"},
{"readblock", CmdReadBlk, 1, "<Block> -- Read T55xx block data (page 0)"},
{"readblockPWD", CmdReadBlkPWD, 1, "<Block> <Password> -- Read T55xx block data in password mode(page 0)"},
{"writeblock", CmdWriteBlk, 1, "<Data> <Block> -- Write T55xx block data (page 0)"},
{"writeblockPWD", CmdWriteBlkPWD, 1, "<Data> <Block> <Password> -- Write T55xx block data in password mode(page 0)"},
{"readtrace", CmdReadTrace, 1, "Read T55xx traceability data (page 1)"},
{NULL, NULL, 0, NULL}
};

View file

@ -17,12 +17,5 @@ int CmdReadBlkPWD(const char *Cmd);
int CmdWriteBlk(const char *Cmd);
int CmdWriteBLkPWD(const char *Cmd);
int CmdReadTrace(const char *Cmd);
int CmdInfo(const char *Cmd);
int CmdIceFsk(const char *Cmd);
int CmdIceManchester(const char *Cmd);
int ManchesterDemod(int block);
char * GetBitRateStr(uint32_t id);
char * GetSaferStr(uint32_t id);
char * GetModulationStr( uint32_t id);
uint32_t PackBits(uint8_t start, uint8_t len, uint8_t* bitstream);
#endif

View file

@ -16,7 +16,7 @@
#include "cmdparser.h"
#include "proxmark3.h"
#include "data.h"
#include "../include/usb_cmd.h"
#include "usb_cmd.h"
#include "ui.h"
#include "cmdhf.h"
#include "cmddata.h"
@ -133,14 +133,15 @@ bool WaitForResponseTimeout(uint32_t cmd, UsbCommand* response, size_t ms_timeou
UsbCommand resp;
if (response == NULL)
if (response == NULL) {
response = &resp;
}
// Wait until the command is received
for(size_t dm_seconds=0; dm_seconds < ms_timeout/10; dm_seconds++) {
while(getCommand(response)) {
while(getCommand(response))
{
if(response->cmd == cmd){
return true;
}

View file

@ -11,7 +11,7 @@
#ifndef CMDMAIN_H__
#define CMDMAIN_H__
#include "../include/usb_cmd.h"
#include "usb_cmd.h"
#include "cmdparser.h"
void UsbCommandReceived(UsbCommand *UC);
void CommandReceived(char *Cmd);

View file

@ -13,9 +13,6 @@
#include <stdint.h>
//trace buffer size as defined in armsrc/apps.h TRACE_SIZE
#define TRACE_BUFFER_SIZE 4096
#define FILE_PATH_SIZE 1000
#define SAMPLE_BUFFER_SIZE 64
extern uint8_t* sample_buf;

View file

@ -16,7 +16,7 @@
#include "flash.h"
#include "elf.h"
#include "proxendian.h"
#include "../include/usb_cmd.h"
#include "usb_cmd.h"
void SendCommand(UsbCommand* txcmd);
void ReceiveCommand(UsbCommand* rxcmd);

View file

@ -13,7 +13,7 @@
#include "proxmark3.h"
#include "flash.h"
#include "uart.h"
#include "../include/usb_cmd.h"
#include "usb_cmd.h"
#ifdef _WIN32
# define unlink(x)

View file

@ -9,7 +9,6 @@
//-----------------------------------------------------------------------------
#include <stdio.h>
#include <stdbool.h>
#include <string.h>
#include "ui.h"
#include "graph.h"
@ -22,13 +21,11 @@ int GraphTraceLen;
void AppendGraph(int redraw, int clock, int bit)
{
int i;
int half = (int)(clock/2);
int firstbit = bit ^ 1;
for (i = 0; i < half; ++i)
GraphBuffer[GraphTraceLen++] = firstbit;
for (i = 0; i < (int)(clock / 2); ++i)
GraphBuffer[GraphTraceLen++] = bit ^ 1;
for (i = 0; i <= half; ++i)
for (i = (int)(clock / 2); i < clock; ++i)
GraphBuffer[GraphTraceLen++] = bit;
if (redraw)
@ -39,8 +36,6 @@ void AppendGraph(int redraw, int clock, int bit)
int ClearGraph(int redraw)
{
int gtl = GraphTraceLen;
memset(GraphBuffer, 0x00, GraphTraceLen);
GraphTraceLen = 0;
if (redraw)
@ -49,13 +44,106 @@ int ClearGraph(int redraw)
return gtl;
}
void SetGraphBuf(uint8_t *buff, int size)
/*
* Detect clock rate
*/
//decommissioned - has difficulty detecting rf/32
/*
int DetectClockOld(int peak)
{
if ( buff == NULL ) return;
int i;
int clock = 0xFFFF;
int lastpeak = 0;
uint16_t i = 0;
if ( size > MAX_GRAPH_TRACE_LEN )
size = MAX_GRAPH_TRACE_LEN;
// Detect peak if we don't have one
if (!peak)
for (i = 0; i < GraphTraceLen; ++i)
if (GraphBuffer[i] > peak)
peak = GraphBuffer[i];
// peak=(int)(peak*.75);
for (i = 1; i < GraphTraceLen; ++i)
{
// If this is the beginning of a peak
if (GraphBuffer[i - 1] != GraphBuffer[i] && GraphBuffer[i] >= peak)
{
// Find lowest difference between peaks
if (lastpeak && i - lastpeak < clock)
clock = i - lastpeak;
lastpeak = i;
}
}
return clock;
}
*/
/*
NOW IN LFDEMOD.C
// by marshmellow
// not perfect especially with lower clocks or VERY good antennas (heavy wave clipping)
// maybe somehow adjust peak trimming value based on samples to fix?
int DetectASKClock(int peak)
{
int i=0;
int low=0;
int clk[]={16,32,40,50,64,100,128,256};
int loopCnt = 256;
if (GraphTraceLen<loopCnt) loopCnt = GraphTraceLen;
if (!peak){
for (i=0;i<loopCnt;++i){
if(GraphBuffer[i]>peak){
peak = GraphBuffer[i];
}
if(GraphBuffer[i]<low){
low = GraphBuffer[i];
}
}
peak=(int)(peak*.75);
low= (int)(low*.75);
}
int ii;
int clkCnt;
int tol = 0;
int bestErr=1000;
int errCnt[]={0,0,0,0,0,0,0,0};
for(clkCnt=0; clkCnt<6;++clkCnt){
if (clk[clkCnt]==32){
tol=1;
}else{
tol=0;
}
bestErr=1000;
for (ii=0; ii<loopCnt; ++ii){
if ((GraphBuffer[ii]>=peak) || (GraphBuffer[ii]<=low)){
errCnt[clkCnt]=0;
for (i=0; i<((int)(GraphTraceLen/clk[clkCnt])-1); ++i){
if (GraphBuffer[ii+(i*clk[clkCnt])]>=peak || GraphBuffer[ii+(i*clk[clkCnt])]<=low){
}else if(GraphBuffer[ii+(i*clk[clkCnt])-tol]>=peak || GraphBuffer[ii+(i*clk[clkCnt])-tol]<=low){
}else if(GraphBuffer[ii+(i*clk[clkCnt])+tol]>=peak || GraphBuffer[ii+(i*clk[clkCnt])+tol]<=low){
}else{ //error no peak detected
errCnt[clkCnt]++;
}
}
if(errCnt[clkCnt]==0) return clk[clkCnt];
if(errCnt[clkCnt]<bestErr) bestErr=errCnt[clkCnt];
}
}
}
int iii=0;
int best=0;
for (iii=0; iii<6;++iii){
if (errCnt[iii]<errCnt[best]){
best = iii;
}
}
// PrintAndLog("DEBUG: clkCnt: %d, ii: %d, i: %d peak: %d, low: %d, errcnt: %d, errCnt64: %d",clkCnt,ii,i,peak,low,errCnt[best],errCnt[4]);
return clk[best];
}
*/
void setGraphBuf(uint8_t *buff,int size)
{
int i=0;
ClearGraph(0);
for (; i < size; ++i){
GraphBuffer[i]=buff[i];
@ -64,81 +152,38 @@ void SetGraphBuf(uint8_t *buff, int size)
RepaintGraphWindow();
return;
}
// Copies grahpbuff to buff.
// while triming values to the range -127 -- 127.
int GetFromGraphBuf(uint8_t *buff)
int getFromGraphBuf(uint8_t *buff)
{
if ( buff == NULL ) return -1;
uint32_t i = 0;
for (; i < GraphTraceLen; ++i){
// trim upper and lower values.
if (GraphBuffer[i] > 127)
GraphBuffer[i] = 127;
else if (GraphBuffer[i] < -127)
GraphBuffer[i] = -127;
uint32_t i;
for (i=0;i<GraphTraceLen;++i){
if (GraphBuffer[i]>127) GraphBuffer[i]=127; //trim
if (GraphBuffer[i]<-127) GraphBuffer[i]=-127; //trim
buff[i]=(uint8_t)(GraphBuffer[i]+128);
}
return i;
}
/* Get or auto-detect clock rate */
int GetClock(const char *str, int verbose)
int GetClock(const char *str, int peak, int verbose)
{
int clock;
// int clock2;
sscanf(str, "%i", &clock);
if (!strcmp(str, ""))
clock = 0;
/* Auto-detect clock */
if (!clock) {
uint8_t grph[MAX_GRAPH_TRACE_LEN] = {0x00};
int size = GetFromGraphBuf(grph);
if ( size < 0 ) {
PrintAndLog("Failed to copy from graphbuffer");
return -1;
}
if (!clock)
{
uint8_t grph[MAX_GRAPH_TRACE_LEN]={0};
int size = getFromGraphBuf(grph);
clock = DetectASKClock(grph,size,0);
//clock2 = DetectClock2(peak);
/* Only print this message if we're not looping something */
if (verbose)
if (!verbose){
PrintAndLog("Auto-detected clock rate: %d", clock);
//PrintAndLog("clock2: %d",clock2);
}
}
return clock;
}
// A simple test to see if there is any data inside Graphbuffer.
bool HasGraphData(){
if ( GraphTraceLen <= 0) {
PrintAndLog("No data available, try reading something first");
return false;
}
return true;
}
// Detect high and lows in Grapbuffer.
// Only loops the first 256 values.
void DetectHighLowInGraph(int *high, int *low, bool addFuzz) {
uint8_t loopMax = 255;
if ( loopMax > GraphTraceLen)
loopMax = GraphTraceLen;
for (uint8_t i = 0; i < loopMax; ++i) {
if (GraphBuffer[i] > *high)
*high = GraphBuffer[i];
else if (GraphBuffer[i] < *low)
*low = GraphBuffer[i];
}
//12% fuzz in case highs and lows aren't clipped
if (addFuzz) {
*high = (int)(*high * .88);
*low = (int)(*low * .88);
}
}

View file

@ -10,16 +10,17 @@
#ifndef GRAPH_H__
#define GRAPH_H__
#include <stdint.h>
void AppendGraph(int redraw, int clock, int bit);
int ClearGraph(int redraw);
int GetFromGraphBuf(uint8_t *buff);
int GetClock(const char *str, int verbose);
void SetGraphBuf(uint8_t *buff,int size);
bool HasGraphData();
void DetectHighLowInGraph(int *high, int *low, bool addFuzz);
//int DetectClock(int peak);
int getFromGraphBuf(uint8_t *buff);
int GetClock(const char *str, int peak, int verbose);
void setGraphBuf(uint8_t *buff,int size);
#define MAX_GRAPH_TRACE_LEN (1024*128)
extern int GraphBuffer[MAX_GRAPH_TRACE_LEN];
extern int GraphTraceLen;
#endif

View file

@ -1,17 +1,5 @@
/*****************************************************************************
* WARNING
*
* THIS CODE IS CREATED FOR EXPERIMENTATION AND EDUCATIONAL USE ONLY.
*
* USAGE OF THIS CODE IN OTHER WAYS MAY INFRINGE UPON THE INTELLECTUAL
* PROPERTY OF OTHER PARTIES, SUCH AS INSIDE SECURE AND HID GLOBAL,
* AND MAY EXPOSE YOU TO AN INFRINGEMENT ACTION FROM THOSE PARTIES.
*
* THIS CODE SHOULD NEVER BE USED TO INFRINGE PATENTS OR INTELLECTUAL PROPERTY RIGHTS.
*
*****************************************************************************
*
* This file is part of loclass. It is a reconstructon of the cipher engine
* This file is part of iClassCipher. It is a reconstructon of the cipher engine
* used in iClass, and RFID techology.
*
* The implementation is based on the work performed by

View file

@ -1,17 +1,5 @@
/*****************************************************************************
* WARNING
*
* THIS CODE IS CREATED FOR EXPERIMENTATION AND EDUCATIONAL USE ONLY.
*
* USAGE OF THIS CODE IN OTHER WAYS MAY INFRINGE UPON THE INTELLECTUAL
* PROPERTY OF OTHER PARTIES, SUCH AS INSIDE SECURE AND HID GLOBAL,
* AND MAY EXPOSE YOU TO AN INFRINGEMENT ACTION FROM THOSE PARTIES.
*
* THIS CODE SHOULD NEVER BE USED TO INFRINGE PATENTS OR INTELLECTUAL PROPERTY RIGHTS.
*
*****************************************************************************
*
* This file is part of loclass. It is a reconstructon of the cipher engine
* This file is part of iClassCipher. It is a reconstructon of the cipher engine
* used in iClass, and RFID techology.
*
* The implementation is based on the work performed by

View file

@ -1,17 +1,5 @@
/*****************************************************************************
* WARNING
*
* THIS CODE IS CREATED FOR EXPERIMENTATION AND EDUCATIONAL USE ONLY.
*
* USAGE OF THIS CODE IN OTHER WAYS MAY INFRINGE UPON THE INTELLECTUAL
* PROPERTY OF OTHER PARTIES, SUCH AS INSIDE SECURE AND HID GLOBAL,
* AND MAY EXPOSE YOU TO AN INFRINGEMENT ACTION FROM THOSE PARTIES.
*
* THIS CODE SHOULD NEVER BE USED TO INFRINGE PATENTS OR INTELLECTUAL PROPERTY RIGHTS.
*
*****************************************************************************
*
* This file is part of loclass. It is a reconstructon of the cipher engine
* This file is part of iClassCipher. It is a reconstructon of the cipher engine
* used in iClass, and RFID techology.
*
* The implementation is based on the work performed by

View file

@ -1,17 +1,5 @@
/*****************************************************************************
* WARNING
*
* THIS CODE IS CREATED FOR EXPERIMENTATION AND EDUCATIONAL USE ONLY.
*
* USAGE OF THIS CODE IN OTHER WAYS MAY INFRINGE UPON THE INTELLECTUAL
* PROPERTY OF OTHER PARTIES, SUCH AS INSIDE SECURE AND HID GLOBAL,
* AND MAY EXPOSE YOU TO AN INFRINGEMENT ACTION FROM THOSE PARTIES.
*
* THIS CODE SHOULD NEVER BE USED TO INFRINGE PATENTS OR INTELLECTUAL PROPERTY RIGHTS.
*
*****************************************************************************
*
* This file is part of loclass. It is a reconstructon of the cipher engine
* This file is part of iClassCipher. It is a reconstructon of the cipher engine
* used in iClass, and RFID techology.
*
* The implementation is based on the work performed by

View file

@ -1,41 +1,3 @@
/*****************************************************************************
* WARNING
*
* THIS CODE IS CREATED FOR EXPERIMENTATION AND EDUCATIONAL USE ONLY.
*
* USAGE OF THIS CODE IN OTHER WAYS MAY INFRINGE UPON THE INTELLECTUAL
* PROPERTY OF OTHER PARTIES, SUCH AS INSIDE SECURE AND HID GLOBAL,
* AND MAY EXPOSE YOU TO AN INFRINGEMENT ACTION FROM THOSE PARTIES.
*
* THIS CODE SHOULD NEVER BE USED TO INFRINGE PATENTS OR INTELLECTUAL PROPERTY RIGHTS.
*
*****************************************************************************
*
* This file is part of loclass. It is a reconstructon of the cipher engine
* used in iClass, and RFID techology.
*
* The implementation is based on the work performed by
* Flavio D. Garcia, Gerhard de Koning Gans, Roel Verdult and
* Milosch Meriac in the paper "Dismantling IClass".
*
* Copyright (C) 2014 Martin Holst Swende
*
* This is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as published
* by the Free Software Foundation.
*
* This file 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 loclass. If not, see <http://www.gnu.org/licenses/>.
*
*
*
****************************************************************************/
#include <stdint.h>
#include <stdbool.h>
#include <string.h>
@ -552,6 +514,7 @@ int bruteforceDump(uint8_t dump[], size_t dumpsize, uint16_t keytable[])
*/
int bruteforceFile(const char *filename, uint16_t keytable[])
{
FILE *f = fopen(filename, "rb");
if(!f) {
prnlog("Failed to read from file '%s'", filename);
@ -563,7 +526,7 @@ int bruteforceFile(const char *filename, uint16_t keytable[])
fseek(f, 0, SEEK_SET);
uint8_t *dump = malloc(fsize);
size_t bytes_read = fread(dump, fsize, 1, f);
size_t bytes_read = fread(dump, 1, fsize, f);
fclose(f);
if (bytes_read < fsize)
@ -614,9 +577,18 @@ int _testBruteforce()
**** The 64-bit HS Custom Key Value = 5B7C62C491C11B39 ****
**/
uint16_t keytable[128] = {0};
//save some time...
startvalue = 0x7B0000;
//Test a few variants
if(fileExists("iclass_dump.bin"))
{
errors |= bruteforceFile("iclass_dump.bin",keytable);
}else if(fileExists("loclass/iclass_dump.bin")){
errors |= bruteforceFile("loclass/iclass_dump.bin",keytable);
}else if(fileExists("client/loclass/iclass_dump.bin")){
errors |= bruteforceFile("client/loclass/iclass_dump.bin",keytable);
}else{
prnlog("Error: The file iclass_dump.bin was not found!");
}
}
return errors;
}

View file

@ -1,42 +1,3 @@
/*****************************************************************************
* WARNING
*
* THIS CODE IS CREATED FOR EXPERIMENTATION AND EDUCATIONAL USE ONLY.
*
* USAGE OF THIS CODE IN OTHER WAYS MAY INFRINGE UPON THE INTELLECTUAL
* PROPERTY OF OTHER PARTIES, SUCH AS INSIDE SECURE AND HID GLOBAL,
* AND MAY EXPOSE YOU TO AN INFRINGEMENT ACTION FROM THOSE PARTIES.
*
* THIS CODE SHOULD NEVER BE USED TO INFRINGE PATENTS OR INTELLECTUAL PROPERTY RIGHTS.
*
*****************************************************************************
*
* This file is part of loclass. It is a reconstructon of the cipher engine
* used in iClass, and RFID techology.
*
* The implementation is based on the work performed by
* Flavio D. Garcia, Gerhard de Koning Gans, Roel Verdult and
* Milosch Meriac in the paper "Dismantling IClass".
*
* Copyright (C) 2014 Martin Holst Swende
*
* This is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as published
* by the Free Software Foundation.
*
* This file 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 loclass. If not, see <http://www.gnu.org/licenses/>.
*
*
*
****************************************************************************/
#ifndef ELITE_CRACK_H
#define ELITE_CRACK_H
void permutekey(uint8_t key[8], uint8_t dest[8]);

View file

@ -1,41 +1,3 @@
/*****************************************************************************
* WARNING
*
* THIS CODE IS CREATED FOR EXPERIMENTATION AND EDUCATIONAL USE ONLY.
*
* USAGE OF THIS CODE IN OTHER WAYS MAY INFRINGE UPON THE INTELLECTUAL
* PROPERTY OF OTHER PARTIES, SUCH AS INSIDE SECURE AND HID GLOBAL,
* AND MAY EXPOSE YOU TO AN INFRINGEMENT ACTION FROM THOSE PARTIES.
*
* THIS CODE SHOULD NEVER BE USED TO INFRINGE PATENTS OR INTELLECTUAL PROPERTY RIGHTS.
*
*****************************************************************************
*
* This file is part of loclass. It is a reconstructon of the cipher engine
* used in iClass, and RFID techology.
*
* The implementation is based on the work performed by
* Flavio D. Garcia, Gerhard de Koning Gans, Roel Verdult and
* Milosch Meriac in the paper "Dismantling IClass".
*
* Copyright (C) 2014 Martin Holst Swende
*
* This is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as published
* by the Free Software Foundation.
*
* This file 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 loclass. If not, see <http://www.gnu.org/licenses/>.
*
*
*
****************************************************************************/
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
@ -51,11 +13,11 @@
int fileExists(const char *filename) {
#ifdef _WIN32
struct _stat fileStat;
int result = _stat(filename, &fileStat);
struct _stat st;
int result = _stat(filename, &st);
#else
struct stat fileStat;
int result = stat(filename, &fileStat);
struct stat st;
int result = stat(filename, &st);
#endif
return result == 0;
}
@ -76,33 +38,21 @@ int saveFile(const char *preferredName, const char *suffix, const void* data, si
/* We should have a valid filename now, e.g. dumpdata-3.bin */
/*Opening file for writing in binary mode*/
FILE *fh=fopen(fileName,"wb");
if(!fh) {
FILE *fileHandle=fopen(fileName,"wb");
if(!fileHandle) {
PrintAndLog("Failed to write to file '%s'", fileName);
free(fh);
free(fileName);
return 1;
}
fwrite(data, 1, datalen, fh);
fclose(fh);
PrintAndLog("Saved data to '%s'", fileName);
fwrite(data, 1, datalen, fileHandle);
fclose(fileHandle);
PrintAndLog(">Saved data to '%s'", fileName);
free(fileName);
return 0;
}
int loadFile(const char *fileName, void* data, size_t datalen)
{
FILE *filehandle = fopen(fileName, "rb");
if(!filehandle) {
PrintAndLog("Failed to read from file '%s'", fileName);
free(filehandle);
return 1;
}
fread(data,datalen,1,filehandle);
fclose(filehandle);
free(filehandle);
return 0;
}
/**
* Utility function to print to console. This is used consistently within the library instead
* of printf, but it actually only calls printf (and adds a linebreak).
@ -113,11 +63,11 @@ int loadFile(const char *fileName, void* data, size_t datalen)
*/
void prnlog(char *fmt, ...)
{
char buffer[2048] = {0};
va_list args;
va_start(args,fmt);
PrintAndLog(fmt, args);
//vprintf(fmt,args);
vsprintf (buffer,fmt, args);
va_end(args);
//printf("\n");
PrintAndLog(buffer);
}

View file

@ -1,41 +1,3 @@
/*****************************************************************************
* WARNING
*
* THIS CODE IS CREATED FOR EXPERIMENTATION AND EDUCATIONAL USE ONLY.
*
* USAGE OF THIS CODE IN OTHER WAYS MAY INFRINGE UPON THE INTELLECTUAL
* PROPERTY OF OTHER PARTIES, SUCH AS INSIDE SECURE AND HID GLOBAL,
* AND MAY EXPOSE YOU TO AN INFRINGEMENT ACTION FROM THOSE PARTIES.
*
* THIS CODE SHOULD NEVER BE USED TO INFRINGE PATENTS OR INTELLECTUAL PROPERTY RIGHTS.
*
*****************************************************************************
*
* This file is part of loclass. It is a reconstructon of the cipher engine
* used in iClass, and RFID techology.
*
* The implementation is based on the work performed by
* Flavio D. Garcia, Gerhard de Koning Gans, Roel Verdult and
* Milosch Meriac in the paper "Dismantling IClass".
*
* Copyright (C) 2014 Martin Holst Swende
*
* This is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as published
* by the Free Software Foundation.
*
* This file 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 loclass. If not, see <http://www.gnu.org/licenses/>.
*
*
*
****************************************************************************/
#ifndef FILEUTILS_H
#define FILEUTILS_H
/**
@ -49,16 +11,7 @@
* @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 loadFile(const char *fileName, void* data, size_t datalen);
/**
* Utility function to print to console. This is used consistently within the library instead
@ -68,4 +21,5 @@ int loadFile(const char *fileName, void* data, size_t datalen);
* @param fmt
*/
void prnlog(char *fmt, ...);
int fileExists(const char *filename);
#endif // FILEUTILS_H

View file

@ -1,92 +0,0 @@
#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);
}
}
}

View file

@ -1,5 +0,0 @@
#ifndef HASH1_BRUTE_H
#define HASH1_BRUTE_H
void brute_hash1();
#endif // HASH1_BRUTE_H

View file

@ -1,17 +1,5 @@
/*****************************************************************************
* WARNING
*
* THIS CODE IS CREATED FOR EXPERIMENTATION AND EDUCATIONAL USE ONLY.
*
* USAGE OF THIS CODE IN OTHER WAYS MAY INFRINGE UPON THE INTELLECTUAL
* PROPERTY OF OTHER PARTIES, SUCH AS INSIDE SECURE AND HID GLOBAL,
* AND MAY EXPOSE YOU TO AN INFRINGEMENT ACTION FROM THOSE PARTIES.
*
* THIS CODE SHOULD NEVER BE USED TO INFRINGE PATENTS OR INTELLECTUAL PROPERTY RIGHTS.
*
*****************************************************************************
*
* This file is part of loclass. It is a reconstructon of the cipher engine
* This file is part of iClassCipher. It is a reconstructon of the cipher engine
* used in iClass, and RFID techology.
*
* The implementation is based on the work performed by
@ -737,6 +725,7 @@ int doTestsWithKnownInputs()
int readKeyFile(uint8_t key[8])
{
FILE *f;
int retval = 1;
f = fopen("iclass_key.bin", "rb");
@ -749,6 +738,7 @@ int readKeyFile(uint8_t key[8])
fclose(f);
}
return retval;
}

View file

@ -1,41 +1,3 @@
/*****************************************************************************
* WARNING
*
* THIS CODE IS CREATED FOR EXPERIMENTATION AND EDUCATIONAL USE ONLY.
*
* USAGE OF THIS CODE IN OTHER WAYS MAY INFRINGE UPON THE INTELLECTUAL
* PROPERTY OF OTHER PARTIES, SUCH AS INSIDE SECURE AND HID GLOBAL,
* AND MAY EXPOSE YOU TO AN INFRINGEMENT ACTION FROM THOSE PARTIES.
*
* THIS CODE SHOULD NEVER BE USED TO INFRINGE PATENTS OR INTELLECTUAL PROPERTY RIGHTS.
*
*****************************************************************************
*
* This file is part of loclass. It is a reconstructon of the cipher engine
* used in iClass, and RFID techology.
*
* The implementation is based on the work performed by
* Flavio D. Garcia, Gerhard de Koning Gans, Roel Verdult and
* Milosch Meriac in the paper "Dismantling IClass".
*
* Copyright (C) 2014 Martin Holst Swende
*
* This is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as published
* by the Free Software Foundation.
*
* This file 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 loclass. If not, see <http://www.gnu.org/licenses/>.
*
*
*
****************************************************************************/
#ifndef IKEYS_H
#define IKEYS_H

View file

@ -1,17 +1,5 @@
/*****************************************************************************
* WARNING
*
* THIS CODE IS CREATED FOR EXPERIMENTATION AND EDUCATIONAL USE ONLY.
*
* USAGE OF THIS CODE IN OTHER WAYS MAY INFRINGE UPON THE INTELLECTUAL
* PROPERTY OF OTHER PARTIES, SUCH AS INSIDE SECURE AND HID GLOBAL,
* AND MAY EXPOSE YOU TO AN INFRINGEMENT ACTION FROM THOSE PARTIES.
*
* THIS CODE SHOULD NEVER BE USED TO INFRINGE PATENTS OR INTELLECTUAL PROPERTY RIGHTS.
*
*****************************************************************************
*
* This file is part of loclass. It is a reconstructon of the cipher engine
* This file is part of iClassCipher. It is a reconstructon of the cipher engine
* used in iClass, and RFID techology.
*
* The implementation is based on the work performed by
@ -30,13 +18,9 @@
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with loclass. If not, see <http://www.gnu.org/licenses/>.
*
*
*
* along with IClassCipher. If not, see <http://www.gnu.org/licenses/>.
****************************************************************************/
#include <stdio.h>
#include <cipherutils.h>
#include <stdint.h>
@ -80,18 +64,7 @@ int main (int argc, char **argv)
{
prnlog("IClass Cipher version 1.2, Copyright (C) 2014 Martin Holst Swende\n");
prnlog("Comes with ABSOLUTELY NO WARRANTY");
prnlog("Released as GPLv2\n");
prnlog("WARNING");
prnlog("");
prnlog("THIS TOOL IS CREATED FOR EXPERIMENTATION AND EDUCATIONAL USE ONLY. ");
prnlog("");
prnlog("USAGE OF THIS TOOL IN OTHER WAYS MAY INFRINGE UPON THE INTELLECTUAL ");
prnlog("PROPERTY OF OTHER PARTIES, SUCH AS INSIDE SECURE AND HID GLOBAL, ");
prnlog("AND MAY EXPOSE YOU TO AN INFRINGEMENT ACTION FROM THOSE PARTIES. ");
prnlog("");
prnlog("THIS TOOL SHOULD NEVER BE USED TO INFRINGE PATENTS OR INTELLECTUAL PROPERTY RIGHTS. ");
prnlog("This is free software, and you are welcome to use, abuse and repackage, please keep the credits\n");
char *fileName = NULL;
int c;
while ((c = getopt (argc, argv, "thf:")) != -1)

View file

@ -49,7 +49,7 @@ local _commands = {
CMD_EM4X_WRITE_WORD = 0x0219,
CMD_IO_DEMOD_FSK = 0x021A,
CMD_IO_CLONE_TAG = 0x021B,
CMD_EM410X_DEMOD = 0x021c,
CMD_EM410X_DEMOD = 0x021C,
--/* CMD_SET_ADC_MUX: ext1 is 0 for lopkd, 1 for loraw, 2 for hipkd, 3 for hiraw */
--// For the 13.56 MHz tags
@ -64,7 +64,6 @@ local _commands = {
CMD_ISO_15693_COMMAND_DONE = 0x0314,
CMD_ISO_15693_FIND_AFI = 0x0315,
CMD_ISO_15693_DEBUG = 0x0316,
CMD_LF_SNOOP_RAW_ADC_SAMPLES = 0x0317,
--// For Hitag2 transponders
CMD_SNOOP_HITAG = 0x0370,
@ -81,13 +80,10 @@ local _commands = {
CMD_READER_LEGIC_RF = 0x0388,
CMD_WRITER_LEGIC_RF = 0x0389,
CMD_EPA_PACE_COLLECT_NONCE = 0x038A,
--//CMD_EPA_ = 0x038B,
CMD_SNOOP_ICLASS = 0x0392,
CMD_SIMULATE_TAG_ICLASS = 0x0393,
CMD_READER_ICLASS = 0x0394,
CMD_READER_ICLASS_REPLAY = 0x0395,
CMD_ICLASS_ISO14443A_WRITE = 0x0397,
--// For measurements of the antenna tuning
CMD_MEASURE_ANTENNA_TUNING = 0x0400,
@ -104,11 +100,8 @@ local _commands = {
CMD_MIFARE_EML_MEMSET = 0x0602,
CMD_MIFARE_EML_MEMGET = 0x0603,
CMD_MIFARE_EML_CARDLOAD = 0x0604,
--// magic chinese card commands
CMD_MIFARE_CSETBLOCK = 0x0605,
CMD_MIFARE_CGETBLOCK = 0x0606,
CMD_MIFARE_CIDENT = 0x0607,
CMD_MIFARE_EML_CSETBLOCK = 0x0605,
CMD_MIFARE_EML_CGETBLOCK = 0x0606,
CMD_SIMULATE_MIFARE_CARD = 0x0610,
@ -116,33 +109,12 @@ local _commands = {
CMD_MIFARE_NESTED = 0x0612,
CMD_MIFARE_READBL = 0x0620,
CMD_MIFAREU_READBL = 0x0720,
CMD_MIFARE_READSC = 0x0621,
CMD_MIFAREU_READCARD = 0x0721,
CMD_MIFARE_WRITEBL = 0x0622,
CMD_MIFAREU_WRITEBL = 0x0722,
CMD_MIFAREU_WRITEBL_COMPAT = 0x0723,
CMD_MIFARE_CHKKEYS = 0x0623,
CMD_MIFARE_SNIFFER = 0x0630,
--//ultralightC
CMD_MIFAREUC_AUTH1 = 0x0724,
CMD_MIFAREUC_AUTH2 = 0x0725,
CMD_MIFAREUC_READCARD = 0x0726,
--// mifare desfire
CMD_MIFARE_DESFIRE_READBL = 0x0728,
CMD_MIFARE_DESFIRE_WRITEBL = 0x0729,
CMD_MIFARE_DESFIRE_AUTH1 = 0x072a,
CMD_MIFARE_DESFIRE_AUTH2 = 0x072b,
CMD_MIFARE_DES_READER = 0x072c,
CMD_MIFARE_DESFIRE_INFO = 0x072d,
CMD_MIFARE_DESFIRE = 0x072e,
CMD_UNKNOWN = 0xFFFF,
}
@ -213,6 +185,7 @@ function Command:getBytes()
local cmd = self.cmd
local arg1, arg2, arg3 = self.arg1, self.arg2, self.arg3
return bin.pack("LLLLH",cmd, arg1, arg2, arg3,data);
end
return _commands

View file

@ -1,63 +0,0 @@
local _names = {
--[[
--]]
["0400"]="BASH",
["1600"]="BOOMER" ,
["1800"]="CAMO",
["3000"]="CHOPCHOP" ,
["2000"]="CYNDER",
["6400"]="JET-VAC",
["6700"]="FLASHWING",
["7000"]="TREE REX",
["7100"]="LIGHTCORE SHROOMBOOM",
["1C00"]="DARK SPYRO",
["0600"]="DINORANG" ,
["1200"]="DOUBLE TROUBLE" ,
["1500"]="DRILLSERGEANT" ,
["1400"]="DROBOT",
["0900"]="LIGHTCORE ERUPTOR" ,
["0B00"]="FLAMESLINGER" ,
["1F00"]="GHOST ROASTER",
["0E00"]="GILL GRUNT" ,
["1D00"]="HEX",
["0A00"]="IGNITOR",
["0300"]="LIGHTNINGROD",
["0700"]="LIGHTCORE PRISM BREAK",
["1500"]="SLAMBAM",
["0100"]="SONIC BOOM",
["1000"]="SPYRO",
["1A00"]="STEALTH ELF",
["1B00"]="STUMP SMASH",
["0800"]="SUNBURN",
["0500"]="TERRAFIN",
["1300"]="TRIGGER HAPPY",
["1100"]="VOODOOD",
["0200"]="WARNADO",
["0D00"]="WHAM SHELL",
["0000"]="WHIRLWIND",
["1700"]="WRECKING BALL",
["0C00"]="ZAP",
["1900"]="ZOOK",
["0300"]="DRAGON",
["012D"]="ICE",
["012E"]="PIRATE",
["0130"]="PVPUNLOCK",
["012F"]="UNDEAD",
["0200"]="ANVIL" ,
["CB00"]="CROSSED SWORDS",
["CC00"]="HOURGLASS",
["CA00"]="REGENERATION",
["C900"]="SECRET STASH",
["CD00"]="SHIELD",
["CF00"]="SPARX",
["CE00"]="SPEED BOOTS",
["0194"]="LEGENDARY BASH",
["0430"]="LEGENDARY CHOPCHOP",
["01A0"]="LEGENDARY SPYRO",
["01A3"]="LEGENDARY TRIGGER HAPPY",
["0202"]="PET GILL GRUNT",
["020E"]="PET STEALTH ELF",
["01F9"]="PET TERRAFIN",
["0207"]="PET TRIGGER HAPPY",
}
return _names

View file

@ -47,18 +47,6 @@ local function save_HTML(javascript, filename)
end
local function save_TEXT(data,filename)
-- Open the output file
local outfile = io.open(filename, "wb")
if outfile == nil then
return oops(string.format("Could not write to file %s",tostring(filename)))
end
outfile:write(data)
io.close(outfile)
return filename
end
local function save_BIN(data, filename)
-- Open the output file
@ -193,6 +181,4 @@ return {
convert_bin_to_html = convert_bin_to_html,
convert_eml_to_html = convert_eml_to_html,
convert_eml_to_bin = convert_eml_to_bin,
SaveAsBinary = save_BIN,
SaveAsText = save_TEXT,
}

View file

@ -55,7 +55,6 @@ local skel_1 = [[
return "UNKNOWN"
}
add("04,,,Mifare TNP3xxx Activision 1K,0f01,01");
add("04,,,Mifare Mini,0004,09");
add("04,,,Mifare Classic 1k/Mifare Plus(4 byte UID) 2K SL1,0004,08");
add("04,,,Mifare Plus (4 byte UID) 2K SL2,0004,10");

View file

@ -1,384 +0,0 @@
local md5 = {
_VERSION = "md5.lua 0.5.0",
_DESCRIPTION = "MD5 computation in Lua (5.1)",
_URL = "https://github.com/kikito/md5.lua",
_LICENSE = [[
MIT LICENSE
Copyright (c) 2013 Enrique García Cota + Adam Baldwin + hanzao + Equi 4 Software
Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the
"Software"), to deal in the Software without restriction, including
without limitation the rights to use, copy, modify, merge, publish,
distribute, sublicense, and/or sell copies of the Software, and to
permit persons to whom the Software is furnished to do so, subject to
the following conditions:
The above copyright notice and this permission notice shall be included
in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
]]
}
-- bit lib implementions
local floor, abs, max = math.floor, math.abs, math.max
local char, byte, format, rep, sub =
string.char, string.byte, string.format, string.rep, string.sub
local function check_int(n)
-- checking not float
if(n - floor(n) > 0) then
error("trying to use bitwise operation on non-integer!")
end
end
local function tbl2number(tbl)
local n = #tbl
local rslt = 0
local power = 1
for i = 1, n do
rslt = rslt + tbl[i]*power
power = power*2
end
return rslt
end
local function expand(tbl_m, tbl_n)
local big = {}
local small = {}
if(#tbl_m > #tbl_n) then
big = tbl_m
small = tbl_n
else
big = tbl_n
small = tbl_m
end
-- expand small
for i = #small + 1, #big do
small[i] = 0
end
end
local to_bits -- needs to be declared before bit_not
local function bit_not(n)
local tbl = to_bits(n)
local size = max(#tbl, 32)
for i = 1, size do
if(tbl[i] == 1) then
tbl[i] = 0
else
tbl[i] = 1
end
end
return tbl2number(tbl)
end
-- defined as local above
to_bits = function (n)
check_int(n)
if(n < 0) then
-- negative
return to_bits(bit_not(abs(n)) + 1)
end
-- to bits table
local tbl = {}
local cnt = 1
while (n > 0) do
local last = math.fmod(n,2)
if(last == 1) then
tbl[cnt] = 1
else
tbl[cnt] = 0
end
n = (n-last)/2
cnt = cnt + 1
end
return tbl
end
local function bit_or(m, n)
local tbl_m = to_bits(m)
local tbl_n = to_bits(n)
expand(tbl_m, tbl_n)
local tbl = {}
local rslt = max(#tbl_m, #tbl_n)
for i = 1, rslt do
if(tbl_m[i]== 0 and tbl_n[i] == 0) then
tbl[i] = 0
else
tbl[i] = 1
end
end
return tbl2number(tbl)
end
local function bit_and(m, n)
local tbl_m = to_bits(m)
local tbl_n = to_bits(n)
expand(tbl_m, tbl_n)
local tbl = {}
local rslt = max(#tbl_m, #tbl_n)
for i = 1, rslt do
if(tbl_m[i]== 0 or tbl_n[i] == 0) then
tbl[i] = 0
else
tbl[i] = 1
end
end
return tbl2number(tbl)
end
local function bit_xor(m, n)
local tbl_m = to_bits(m)
local tbl_n = to_bits(n)
expand(tbl_m, tbl_n)
local tbl = {}
local rslt = max(#tbl_m, #tbl_n)
for i = 1, rslt do
if(tbl_m[i] ~= tbl_n[i]) then
tbl[i] = 1
else
tbl[i] = 0
end
end
return tbl2number(tbl)
end
local function bit_rshift(n, bits)
check_int(n)
local high_bit = 0
if(n < 0) then
-- negative
n = bit_not(abs(n)) + 1
high_bit = 2147483648 -- 0x80000000
end
for i=1, bits do
n = n/2
n = bit_or(floor(n), high_bit)
end
return floor(n)
end
local function bit_lshift(n, bits)
check_int(n)
if(n < 0) then
-- negative
n = bit_not(abs(n)) + 1
end
for i=1, bits do
n = n*2
end
return bit_and(n, 4294967295) -- 0xFFFFFFFF
end
-- convert little-endian 32-bit int to a 4-char string
local function lei2str(i)
local f=function (s) return char( bit_and( bit_rshift(i, s), 255)) end
return f(0)..f(8)..f(16)..f(24)
end
-- convert raw string to big-endian int
local function str2bei(s)
local v=0
for i=1, #s do
v = v * 256 + byte(s, i)
end
return v
end
-- convert raw string to little-endian int
local function str2lei(s)
local v=0
for i = #s,1,-1 do
v = v*256 + byte(s, i)
end
return v
end
-- cut up a string in little-endian ints of given size
local function cut_le_str(s,...)
local o, r = 1, {}
local args = {...}
for i=1, #args do
table.insert(r, str2lei(sub(s, o, o + args[i] - 1)))
o = o + args[i]
end
return r
end
local swap = function (w) return str2bei(lei2str(w)) end
local function hex2binaryaux(hexval)
return char(tonumber(hexval, 16))
end
local function hex2binary(hex)
local result, _ = hex:gsub('..', hex2binaryaux)
return result
end
-- An MD5 mplementation in Lua, requires bitlib (hacked to use LuaBit from above, ugh)
-- 10/02/2001 jcw@equi4.com
local FF = 0xffffffff
local CONSTS = {
0xd76aa478, 0xe8c7b756, 0x242070db, 0xc1bdceee,
0xf57c0faf, 0x4787c62a, 0xa8304613, 0xfd469501,
0x698098d8, 0x8b44f7af, 0xffff5bb1, 0x895cd7be,
0x6b901122, 0xfd987193, 0xa679438e, 0x49b40821,
0xf61e2562, 0xc040b340, 0x265e5a51, 0xe9b6c7aa,
0xd62f105d, 0x02441453, 0xd8a1e681, 0xe7d3fbc8,
0x21e1cde6, 0xc33707d6, 0xf4d50d87, 0x455a14ed,
0xa9e3e905, 0xfcefa3f8, 0x676f02d9, 0x8d2a4c8a,
0xfffa3942, 0x8771f681, 0x6d9d6122, 0xfde5380c,
0xa4beea44, 0x4bdecfa9, 0xf6bb4b60, 0xbebfbc70,
0x289b7ec6, 0xeaa127fa, 0xd4ef3085, 0x04881d05,
0xd9d4d039, 0xe6db99e5, 0x1fa27cf8, 0xc4ac5665,
0xf4292244, 0x432aff97, 0xab9423a7, 0xfc93a039,
0x655b59c3, 0x8f0ccc92, 0xffeff47d, 0x85845dd1,
0x6fa87e4f, 0xfe2ce6e0, 0xa3014314, 0x4e0811a1,
0xf7537e82, 0xbd3af235, 0x2ad7d2bb, 0xeb86d391,
0x67452301, 0xefcdab89, 0x98badcfe, 0x10325476
}
local f=function (x,y,z) return bit_or(bit_and(x,y),bit_and(-x-1,z)) end
local g=function (x,y,z) return bit_or(bit_and(x,z),bit_and(y,-z-1)) end
local h=function (x,y,z) return bit_xor(x,bit_xor(y,z)) end
local i=function (x,y,z) return bit_xor(y,bit_or(x,-z-1)) end
local z=function (f,a,b,c,d,x,s,ac)
a=bit_and(a+f(b,c,d)+x+ac,FF)
-- be *very* careful that left shift does not cause rounding!
return bit_or(bit_lshift(bit_and(a,bit_rshift(FF,s)),s),bit_rshift(a,32-s))+b
end
local function transform(A,B,C,D,X)
local a,b,c,d=A,B,C,D
local t=CONSTS
a=z(f,a,b,c,d,X[ 0], 7,t[ 1])
d=z(f,d,a,b,c,X[ 1],12,t[ 2])
c=z(f,c,d,a,b,X[ 2],17,t[ 3])
b=z(f,b,c,d,a,X[ 3],22,t[ 4])
a=z(f,a,b,c,d,X[ 4], 7,t[ 5])
d=z(f,d,a,b,c,X[ 5],12,t[ 6])
c=z(f,c,d,a,b,X[ 6],17,t[ 7])
b=z(f,b,c,d,a,X[ 7],22,t[ 8])
a=z(f,a,b,c,d,X[ 8], 7,t[ 9])
d=z(f,d,a,b,c,X[ 9],12,t[10])
c=z(f,c,d,a,b,X[10],17,t[11])
b=z(f,b,c,d,a,X[11],22,t[12])
a=z(f,a,b,c,d,X[12], 7,t[13])
d=z(f,d,a,b,c,X[13],12,t[14])
c=z(f,c,d,a,b,X[14],17,t[15])
b=z(f,b,c,d,a,X[15],22,t[16])
a=z(g,a,b,c,d,X[ 1], 5,t[17])
d=z(g,d,a,b,c,X[ 6], 9,t[18])
c=z(g,c,d,a,b,X[11],14,t[19])
b=z(g,b,c,d,a,X[ 0],20,t[20])
a=z(g,a,b,c,d,X[ 5], 5,t[21])
d=z(g,d,a,b,c,X[10], 9,t[22])
c=z(g,c,d,a,b,X[15],14,t[23])
b=z(g,b,c,d,a,X[ 4],20,t[24])
a=z(g,a,b,c,d,X[ 9], 5,t[25])
d=z(g,d,a,b,c,X[14], 9,t[26])
c=z(g,c,d,a,b,X[ 3],14,t[27])
b=z(g,b,c,d,a,X[ 8],20,t[28])
a=z(g,a,b,c,d,X[13], 5,t[29])
d=z(g,d,a,b,c,X[ 2], 9,t[30])
c=z(g,c,d,a,b,X[ 7],14,t[31])
b=z(g,b,c,d,a,X[12],20,t[32])
a=z(h,a,b,c,d,X[ 5], 4,t[33])
d=z(h,d,a,b,c,X[ 8],11,t[34])
c=z(h,c,d,a,b,X[11],16,t[35])
b=z(h,b,c,d,a,X[14],23,t[36])
a=z(h,a,b,c,d,X[ 1], 4,t[37])
d=z(h,d,a,b,c,X[ 4],11,t[38])
c=z(h,c,d,a,b,X[ 7],16,t[39])
b=z(h,b,c,d,a,X[10],23,t[40])
a=z(h,a,b,c,d,X[13], 4,t[41])
d=z(h,d,a,b,c,X[ 0],11,t[42])
c=z(h,c,d,a,b,X[ 3],16,t[43])
b=z(h,b,c,d,a,X[ 6],23,t[44])
a=z(h,a,b,c,d,X[ 9], 4,t[45])
d=z(h,d,a,b,c,X[12],11,t[46])
c=z(h,c,d,a,b,X[15],16,t[47])
b=z(h,b,c,d,a,X[ 2],23,t[48])
a=z(i,a,b,c,d,X[ 0], 6,t[49])
d=z(i,d,a,b,c,X[ 7],10,t[50])
c=z(i,c,d,a,b,X[14],15,t[51])
b=z(i,b,c,d,a,X[ 5],21,t[52])
a=z(i,a,b,c,d,X[12], 6,t[53])
d=z(i,d,a,b,c,X[ 3],10,t[54])
c=z(i,c,d,a,b,X[10],15,t[55])
b=z(i,b,c,d,a,X[ 1],21,t[56])
a=z(i,a,b,c,d,X[ 8], 6,t[57])
d=z(i,d,a,b,c,X[15],10,t[58])
c=z(i,c,d,a,b,X[ 6],15,t[59])
b=z(i,b,c,d,a,X[13],21,t[60])
a=z(i,a,b,c,d,X[ 4], 6,t[61])
d=z(i,d,a,b,c,X[11],10,t[62])
c=z(i,c,d,a,b,X[ 2],15,t[63])
b=z(i,b,c,d,a,X[ 9],21,t[64])
return A+a,B+b,C+c,D+d
end
----------------------------------------------------------------
function md5.sumhexa(s)
local msgLen = #s
local padLen = 56 - msgLen % 64
if msgLen % 64 > 56 then padLen = padLen + 64 end
if padLen == 0 then padLen = 64 end
s = s .. char(128) .. rep(char(0),padLen-1) .. lei2str(8*msgLen) .. lei2str(0)
assert(#s % 64 == 0)
local t = CONSTS
local a,b,c,d = t[65],t[66],t[67],t[68]
for i=1,#s,64 do
local X = cut_le_str(sub(s,i,i+63),4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4)
assert(#X == 16)
X[0] = table.remove(X,1) -- zero based!
a,b,c,d = transform(a,b,c,d,X)
end
return format("%08x%08x%08x%08x",swap(a),swap(b),swap(c),swap(d))
end
function md5.sum(s)
return hex2binary(md5.sumhexa(s))
end
return md5

View file

@ -141,24 +141,6 @@ local _keys = {
'200000000000',
'a00000000000',
'b00000000000',
--[[
Should be for Mifare TNP3xxx tags A KEY.
--]]
'4b0b20107ccb',
--[[
Kiev metro cards
--]]
'8fe644038790',
'f14ee7cae863',
'632193be1c3c',
'569369c5a0e5',
'9de89e070277',
'eff603e1efe9',
'644672bd4afe',
'b5ff67cba951',
}
---

View file

@ -25,7 +25,6 @@ local ISO14A_COMMAND = {
local ISO14443a_TYPES = {}
ISO14443a_TYPES[0x00] = "NXP MIFARE Ultralight | Ultralight C"
ISO14443a_TYPES[0x01] = "NXP MIFARE TNP3xxx Activision Game Appliance"
ISO14443a_TYPES[0x04] = "NXP MIFARE (various !DESFire !DESFire EV1)"
ISO14443a_TYPES[0x08] = "NXP MIFARE CLASSIC 1k | Plus 2k"
ISO14443a_TYPES[0x09] = "NXP MIFARE Mini 0.3k"

View file

@ -33,86 +33,9 @@ local Utils =
return answer
end,
------------ FILE READING
ReadDumpFile = function (filename)
if filename == nil then
return nil, 'Filename is empty'
end
if #filename == 0 then
return nil, 'Filename length is zero'
end
infile = io.open(filename, "rb")
if infile == nil then
return nil, string.format("Could not read file %s",filename)
end
local t = infile:read("*all")
len = string.len(t)
local _,hex = bin.unpack(("H%d"):format(len),t)
io.close(infile)
return hex
end,
------------ string split function
Split = function( inSplitPattern, outResults )
if not outResults then
outResults = {}
end
local start = 1
local splitStart, splitEnd = string.find( self, inSplitPattern, start )
while splitStart do
table.insert( outResults, string.sub( self, start, splitStart-1 ) )
start = splitEnd + 1
splitStart, splitEnd = string.find( self, inSplitPattern, start )
end
table.insert( outResults, string.sub( self, start ) )
return outResults
end,
------------ CRC-16 ccitt checksums
-- Takes a hex string and calculates a crc16
Crc16 = function(s)
if s == nil then return nil end
if #s == 0 then return nil end
if type(s) == 'string' then
local utils = require('utils')
local asc = utils.ConvertHexToAscii(s)
local hash = core.crc16(asc)
return hash
end
return nil
end,
-- input parameter is a string
-- Swaps the endianess and returns a number,
-- IE: 'cd7a' -> '7acd' -> 0x7acd
SwapEndianness = function(s, len)
if s == nil then return nil end
if #s == 0 then return '' end
if type(s) ~= 'string' then return nil end
local retval = 0
if len == 16 then
local t = s:sub(3,4)..s:sub(1,2)
retval = tonumber(t,16)
elseif len == 24 then
local t = s:sub(5,6)..s:sub(3,4)..s:sub(1,2)
retval = tonumber(t,16)
elseif len == 32 then
local t = s:sub(7,8)..s:sub(5,6)..s:sub(3,4)..s:sub(1,2)
retval = tonumber(t,16)
end
return retval
end,
------------ CONVERSIONS
--
-- Converts DECIMAL to HEX
ConvertDecToHex = function(IN)
ConvertDec2Hex = function(IN)
local B,K,OUT,I,D=16,"0123456789ABCDEF","",0
while IN>0 do
I=I+1
@ -123,100 +46,12 @@ local Utils =
end,
---
-- Convert Byte array to string of hex
ConvertBytesToHex = function(bytes)
if #bytes == 0 then
return ''
end
local s={}
ConvertBytes2String = function(bytes)
s = {}
for i = 1, #(bytes) do
s[i] = string.format("%02X",bytes[i])
end
return table.concat(s)
end,
-- Convert byte array to string with ascii
ConvertBytesToAscii = function(bytes)
if #bytes == 0 then
return ''
end
local s={}
for i = 1, #(bytes) do
s[i] = string.char(bytes[i])
end
return table.concat(s)
end,
ConvertHexToBytes = function(s)
local t={}
if s == nil then return t end
if #s == 0 then return t end
for k in s:gmatch"(%x%x)" do
table.insert(t,tonumber(k,16))
end
return t
end,
ConvertAsciiToBytes = function(s)
local t={}
if s == nil then return t end
if #s == 0 then return t end
for k in s:gmatch"(.)" do
table.insert(t, string.byte(k))
end
return t
end,
ConvertHexToAscii = function(s)
local t={}
if s == nil then return t end
if #s == 0 then return t end
for k in s:gmatch"(%x%x)" do
table.insert(t, string.char(tonumber(k,16)))
end
return table.concat(t)
end,
-- function convertStringToBytes(str)
-- local bytes = {}
-- local strLength = string.len(str)
-- for i=1,strLength do
-- table.insert(bytes, string.byte(str, i))
-- end
-- return bytes
-- end
-- function convertBytesToString(bytes)
-- local bytesLength = table.getn(bytes)
-- local str = ""
-- for i=1,bytesLength do
-- str = str .. string.char(bytes[i])
-- end
-- return str
-- end
-- function convertHexStringToBytes(str)
-- local bytes = {}
-- local strLength = string.len(str)
-- for k=2,strLength,2 do
-- local hexString = "0x" .. string.sub(str, (k - 1), k)
-- table.insert(bytes, hex.to_dec(hexString))
-- end
-- return bytes
-- end
-- function convertBytesToHexString(bytes)
-- local str = ""
-- local bytesLength = table.getn(bytes)
-- for i=1,bytesLength do
-- local hexString = string.sub(hex.to_hex(bytes[i]), 3)
-- if string.len(hexString) == 1 then
-- hexString = "0" .. hexString
-- end
-- str = str .. hexString
-- end
-- return str
-- end
}
return Utils

View file

@ -549,6 +549,7 @@ lfsr_common_prefix(uint32_t pfx, uint32_t rr, uint8_t ks[8], uint8_t par[8][8],
free(odd);
free(even);
return 0;
}
s = statelist;

View file

@ -280,7 +280,7 @@ void ProxWidget::paintEvent(QPaintEvent *event)
ProxWidget::ProxWidget(QWidget *parent) : QWidget(parent), GraphStart(0), GraphPixelsPerPoint(1)
{
resize(600, 300);
resize(600, 500);
QPalette palette(QColor(0,0,0,0));
palette.setColor(QPalette::WindowText, QColor(255,255,255));

View file

@ -20,7 +20,7 @@
#include "usb_cmd.h"
#define PROXPROMPT "pm3 --> "
#define PROXPROMPT "proxmark3> "
void SendCommand(UsbCommand *c);

View file

@ -18,8 +18,6 @@
#include "util.h"
#include "nonce2key/nonce2key.h"
#include "../common/iso15693tools.h"
#include <openssl/aes.h>
#include "../common/crc16.h"
/**
* The following params expected:
* UsbCommand c
@ -226,54 +224,6 @@ static int l_iso15693_crc(lua_State *L)
return 1;
}
/*
Simple AES 128 cbc hook up to OpenSSL.
params: key, input
*/
static int l_aes(lua_State *L)
{
//Check number of arguments
int i;
size_t size;
const char *p_key = luaL_checklstring(L, 1, &size);
if(size != 32) return returnToLuaWithError(L,"Wrong size of key, got %d bytes, expected 32", (int) size);
const char *p_encTxt = luaL_checklstring(L, 2, &size);
unsigned char indata[AES_BLOCK_SIZE] = {0x00};
unsigned char outdata[AES_BLOCK_SIZE] = {0x00};
unsigned char aes_key[AES_BLOCK_SIZE] = {0x00};
unsigned char iv[AES_BLOCK_SIZE] = {0x00};
// convert key to bytearray
for (i = 0; i < 32; i += 2) {
sscanf(&p_encTxt[i], "%02x", (unsigned int *)&indata[i / 2]);
}
// convert input to bytearray
for (i = 0; i < 32; i += 2) {
sscanf(&p_key[i], "%02x", (unsigned int *)&aes_key[i / 2]);
}
AES_KEY key;
AES_set_decrypt_key(aes_key, 128, &key);
AES_cbc_encrypt(indata, outdata, sizeof(indata), &key, iv, AES_DECRYPT);
//Push decrypted array as a string
lua_pushlstring(L,(const char *)&outdata, sizeof(outdata));
return 1;// return 1 to signal one return value
}
static int l_crc16(lua_State *L)
{
size_t size;
const char *p_str = luaL_checklstring(L, 1, &size);
uint16_t retval = crc16_ccitt( (uint8_t*) p_str, size);
lua_pushinteger(L, (int) retval);
return 1;
}
/**
* @brief Sets the lua path to include "./lualibs/?.lua", in order for a script to be
* able to do "require('foobar')" if foobar.lua is within lualibs folder.
@ -311,8 +261,6 @@ int set_pm3_libraries(lua_State *L)
{"clearCommandBuffer", l_clearCommandBuffer},
{"console", l_CmdConsole},
{"iso15693_crc", l_iso15693_crc},
{"aes", l_aes},
{"crc16", l_crc16},
{NULL, NULL}
};

View file

@ -90,10 +90,8 @@ function GetCardInfo()
elseif 0x09 == result.sak then -- NXP MIFARE Mini 0.3k
-- MIFARE Classic mini offers 320 bytes split into five sectors.
numSectors = 5
elseif 0x10 == result.sak then -- NXP MIFARE Plus 2k
elseif 0x10 == result.sak then-- "NXP MIFARE Plus 2k"
numSectors = 32
elseif 0x01 == sak then -- NXP MIFARE TNP3xxx 1K
numSectors = 16
else
print("I don't know how many sectors there are on this type of card, defaulting to 16")
end

View file

@ -133,8 +133,6 @@ function nested(key,sak)
typ = 0
elseif 0x10 == sak then-- "NXP MIFARE Plus 2k"
typ = 2
elseif 0x01 == sak then-- "NXP MIFARE TNP3xxx 1K"
typ = 1
else
print("I don't know how many sectors there are on this type of card, defaulting to 16")
end

View file

@ -1,272 +0,0 @@
local cmds = require('commands')
local getopt = require('getopt')
local bin = require('bin')
local lib14a = require('read14a')
local utils = require('utils')
local md5 = require('md5')
local dumplib = require('html_dumplib')
local toyNames = require('default_toys')
example =[[
1. script run tnp3dump
2. script run tnp3dump -n
3. script run tnp3dump -k aabbccddeeff
4. script run tnp3dump -k aabbccddeeff -n
5. script run tnp3dump -o myfile
6. script run tnp3dump -n -o myfile
7. script run tnp3dump -k aabbccddeeff -n -o myfile
]]
author = "Iceman"
usage = "script run tnp3dump -k <key> -n -o <filename>"
desc =[[
This script will try to dump the contents of a Mifare TNP3xxx card.
It will need a valid KeyA in order to find the other keys and decode the card.
Arguments:
-h : this help
-k <key> : Sector 0 Key A.
-n : Use the nested cmd to find all keys
-o : filename for the saved dumps
]]
local HASHCONSTANT = '20436F707972696768742028432920323031302041637469766973696F6E2E20416C6C205269676874732052657365727665642E20'
local TIMEOUT = 2000 -- Shouldn't take longer than 2 seconds
local DEBUG = false -- the debug flag
local numBlocks = 64
local numSectors = 16
---
-- A debug printout-function
function dbg(args)
if not DEBUG then
return
end
if type(args) == "table" then
local i = 1
while result[i] do
dbg(result[i])
i = i+1
end
else
print("###", args)
end
end
---
-- This is only meant to be used when errors occur
function oops(err)
print("ERROR: ",err)
end
---
-- Usage help
function help()
print(desc)
print("Example usage")
print(example)
end
--
-- Exit message
function ExitMsg(msg)
print( string.rep('--',20) )
print( string.rep('--',20) )
print(msg)
print()
end
local function readdumpkeys(infile)
t = infile:read("*all")
len = string.len(t)
local len,hex = bin.unpack(("H%d"):format(len),t)
return hex
end
local function waitCmd()
local response = core.WaitForResponseTimeout(cmds.CMD_ACK,TIMEOUT)
if response then
local count,cmd,arg0 = bin.unpack('LL',response)
if(arg0==1) then
local count,arg1,arg2,data = bin.unpack('LLH511',response,count)
return data:sub(1,32)
else
return nil, "Couldn't read block.."
end
end
return nil, "No response from device"
end
local function computeCrc16(s)
local hash = core.crc16(utils.ConvertHexToAscii(s))
return hash
end
local function reverseCrcBytes(crc)
crc2 = crc:sub(3,4)..crc:sub(1,2)
return tonumber(crc2,16)
end
local function main(args)
print( string.rep('--',20) )
print( string.rep('--',20) )
local keyA
local cmd
local err
local useNested = false
local cmdReadBlockString = 'hf mf rdbl %d A %s'
local input = "dumpkeys.bin"
local outputTemplate = os.date("toydump_%Y-%m-%d_%H%M%S");
-- Arguments for the script
for o, a in getopt.getopt(args, 'hk:no:') do
if o == "h" then return help() end
if o == "k" then keyA = a end
if o == "n" then useNested = true end
if o == "o" then outputTemplate = a end
end
-- validate input args.
keyA = keyA or '4b0b20107ccb'
if #(keyA) ~= 12 then
return oops( string.format('Wrong length of write key (was %d) expected 12', #keyA))
end
-- Turn off Debug
local cmdSetDbgOff = "hf mf dbg 0"
core.console( cmdSetDbgOff)
result, err = lib14a.read1443a(false)
if not result then
return oops(err)
end
core.clearCommandBuffer()
if 0x01 ~= result.sak then -- NXP MIFARE TNP3xxx
return oops('This is not a TNP3xxx tag. aborting.')
end
-- Show tag info
print((' Found tag : %s'):format(result.name))
print(('Using keyA : %s'):format(keyA))
--Trying to find the other keys
if useNested then
core.console( ('hf mf nested 1 0 A %s d'):format(keyA) )
end
core.clearCommandBuffer()
-- Loading keyfile
print('Loading dumpkeys.bin')
local hex, err = utils.ReadDumpFile(input)
if not hex then
return oops(err)
end
local akeys = hex:sub(0,12*16)
-- Read block 0
cmd = Command:new{cmd = cmds.CMD_MIFARE_READBL, arg1 = 0,arg2 = 0,arg3 = 0, data = keyA}
err = core.SendCommand(cmd:getBytes())
if err then return oops(err) end
local block0, err = waitCmd()
if err then return oops(err) end
-- Read block 1
cmd = Command:new{cmd = cmds.CMD_MIFARE_READBL, arg1 = 1,arg2 = 0,arg3 = 0, data = keyA}
err = core.SendCommand(cmd:getBytes())
if err then return oops(err) end
local block1, err = waitCmd()
if err then return oops(err) end
local key
local pos = 0
local blockNo
local blocks = {}
print('Reading card data')
core.clearCommandBuffer()
-- main loop
io.write('Decrypting blocks > ')
for blockNo = 0, numBlocks-1, 1 do
if core.ukbhit() then
print("aborted by user")
break
end
pos = (math.floor( blockNo / 4 ) * 12)+1
key = akeys:sub(pos, pos + 11 )
cmd = Command:new{cmd = cmds.CMD_MIFARE_READBL, arg1 = blockNo ,arg2 = 0,arg3 = 0, data = key}
local err = core.SendCommand(cmd:getBytes())
if err then return oops(err) end
local blockdata, err = waitCmd()
if err then return oops(err) end
if blockNo%4 ~= 3 then
if blockNo < 8 then
-- Block 0-7 not encrypted
blocks[blockNo+1] = ('%02d :: %s'):format(blockNo,blockdata)
else
local base = ('%s%s%02x%s'):format(block0, block1, blockNo, HASHCONSTANT)
local baseStr = utils.ConvertHexToAscii(base)
local md5hash = md5.sumhexa(baseStr)
local aestest = core.aes(md5hash, blockdata)
local hex = utils.ConvertAsciiToBytes(aestest)
hex = utils.ConvertBytesToHex(hex)
-- blocks with zero not encrypted.
if string.find(blockdata, '^0+$') then
blocks[blockNo+1] = ('%02d :: %s'):format(blockNo,blockdata)
else
blocks[blockNo+1] = ('%02d :: %s'):format(blockNo,hex)
io.write( blockNo..',')
end
end
else
-- Sectorblocks, not encrypted
blocks[blockNo+1] = ('%02d :: %s%s'):format(blockNo,key,blockdata:sub(13,32))
end
end
io.write('\n')
core.clearCommandBuffer()
-- Print results
local bindata = {}
local emldata = ''
for _,s in pairs(blocks) do
local slice = s:sub(8,#s)
local str = utils.ConvertBytesToAscii(
utils.ConvertHexToBytes(slice)
)
emldata = emldata..slice..'\n'
for c in (str):gmatch('.') do
bindata[#bindata+1] = c
end
end
-- Write dump to files
if not DEBUG then
local foo = dumplib.SaveAsBinary(bindata, outputTemplate..'.bin')
print(("Wrote a BIN dump to the file %s"):format(foo))
local bar = dumplib.SaveAsText(emldata, outputTemplate..'.eml')
print(("Wrote a EML dump to the file %s"):format(bar))
end
local uid = block0:sub(1,8)
local itemtype = block1:sub(1,4)
local cardid = block1:sub(9,24)
-- Show info
print( string.rep('--',20) )
print( (' ITEM TYPE : 0x%s - %s'):format(itemtype, toyNames[itemtype]) )
print( (' UID : 0x%s'):format(uid) )
print( (' CARDID : 0x%s'):format(cardid ) )
print( string.rep('--',20) )
end
main(args)

Some files were not shown because too many files have changed in this diff Show more