2010-02-21 08:47:22 +08:00
//-----------------------------------------------------------------------------
2010-07-13 21:39:30 +08:00
// Copyright (C) 2010 iZsh <izsh at fail0verflow.com>, Hagen Fritsch
2019-02-02 00:00:08 +08:00
// 2011, 2017 - 2019 Merlok
2017-11-25 15:18:30 +08:00
// 2014, Peter Fillmore
// 2015, 2016, 2017 Iceman
2010-02-21 08:47:22 +08:00
//
// 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 ISO14443A commands
//-----------------------------------------------------------------------------
Client cleanup and restructuring. Stage 1...
Next Step is refactoring some of the giant functions which are
just copy/paste of some other ones with just a few line changes,
removing unnecessary 'goto' etc.
The MS Windows version is broken with this commit but will be fixed
soon. Everything can't be done all at once :P
The commands are now hierarchical, for example:
"hf 14a read" vs. "hf 14b read".
You can also request help:
"hf help", "data help", "hf 15 help" etc.
Indents are now space-based, not tab-based anymore. Hopefully
no one will be trolling about it, considering the suicide-prone work
being done here ;)
client/cmdhw.c, client/proxusb.c, client/cmdhw.h, client/proxusb.h,
client/cmdmain.c, client/cmdlfhid.c, client/cmdmain.h, client/cmdlfhid.h,
client/data.c, client/data.h, client/cmdhf.c, client/cmdlf.c,
client/cmdhf.h, client/cmdhf15.c, client/cmdhf14b.c, client/cmdlf.h,
client/cmdhf15.h, client/cmdhf14b.h, client/cmddata.c, client/cmddata.h,
client/ui.c, client/cmdparser.c, client/cmdlfti.c, client/ui.h,
client/cmdlfem4x.c, client/cmdparser.h, client/cmdlfti.h, client/cmdlfem4x.h,
client/graph.c, client/graph.h, client/cmdhf14a.c, client/cmdhf14a.h,
client/cmdhflegic.c, client/cmdhflegic.c: New files.
client/cli.c, client/flasher.c, client/snooper.c, client/proxmark3.c,
client/proxmark3.h, client/Makefile: Update accordingly.
client/flash.h, client/flash.c, client/proxgui.cpp: Cosmetic changes.
client/translate.h, client/command.c, client/gui.c,
client/usb.c, client/prox.h: Remove.
include/usb_cmd.h (CMD_ACQUIRE_RAW_ADC_SAMPLES_ISO_14443_SIM): Remove dead cmd.
common/crc16.h: New file.
common/crc16.c: Modify accordingly.
common/iso14443crc.h: New file.
common/iso14443_crc.c: Rename to
common/iso14443crc.c: and modify accordingly.
armsrc/lfops.c, armsrc/iso14443.c,
armsrc/iso14443a.c: include .h files from
the common directory instead of including the c files.
common/Makefile.common, armsrc/Makefile: Modify accordingly.
2010-02-04 09:27:07 +08:00
# include "cmdhf14a.h"
2015-05-16 21:30:17 +08:00
2019-02-02 00:00:08 +08:00
bool APDUInFramingEnable = true ;
Client cleanup and restructuring. Stage 1...
Next Step is refactoring some of the giant functions which are
just copy/paste of some other ones with just a few line changes,
removing unnecessary 'goto' etc.
The MS Windows version is broken with this commit but will be fixed
soon. Everything can't be done all at once :P
The commands are now hierarchical, for example:
"hf 14a read" vs. "hf 14b read".
You can also request help:
"hf help", "data help", "hf 15 help" etc.
Indents are now space-based, not tab-based anymore. Hopefully
no one will be trolling about it, considering the suicide-prone work
being done here ;)
client/cmdhw.c, client/proxusb.c, client/cmdhw.h, client/proxusb.h,
client/cmdmain.c, client/cmdlfhid.c, client/cmdmain.h, client/cmdlfhid.h,
client/data.c, client/data.h, client/cmdhf.c, client/cmdlf.c,
client/cmdhf.h, client/cmdhf15.c, client/cmdhf14b.c, client/cmdlf.h,
client/cmdhf15.h, client/cmdhf14b.h, client/cmddata.c, client/cmddata.h,
client/ui.c, client/cmdparser.c, client/cmdlfti.c, client/ui.h,
client/cmdlfem4x.c, client/cmdparser.h, client/cmdlfti.h, client/cmdlfem4x.h,
client/graph.c, client/graph.h, client/cmdhf14a.c, client/cmdhf14a.h,
client/cmdhflegic.c, client/cmdhflegic.c: New files.
client/cli.c, client/flasher.c, client/snooper.c, client/proxmark3.c,
client/proxmark3.h, client/Makefile: Update accordingly.
client/flash.h, client/flash.c, client/proxgui.cpp: Cosmetic changes.
client/translate.h, client/command.c, client/gui.c,
client/usb.c, client/prox.h: Remove.
include/usb_cmd.h (CMD_ACQUIRE_RAW_ADC_SAMPLES_ISO_14443_SIM): Remove dead cmd.
common/crc16.h: New file.
common/crc16.c: Modify accordingly.
common/iso14443crc.h: New file.
common/iso14443_crc.c: Rename to
common/iso14443crc.c: and modify accordingly.
armsrc/lfops.c, armsrc/iso14443.c,
armsrc/iso14443a.c: include .h files from
the common directory instead of including the c files.
common/Makefile.common, armsrc/Makefile: Modify accordingly.
2010-02-04 09:27:07 +08:00
static int CmdHelp ( const char * Cmd ) ;
2019-04-07 03:59:34 +08:00
static int waitCmd ( uint8_t iSelect ) ;
2015-01-08 04:06:15 +08:00
2018-01-02 01:57:37 +08:00
static const manufactureName manufactureMapping [ ] = {
2019-03-10 06:35:06 +08:00
// ID, "Vendor Country"
{ 0x01 , " Motorola UK " } ,
{ 0x02 , " ST Microelectronics SA France " } ,
{ 0x03 , " Hitachi, Ltd Japan " } ,
{ 0x04 , " NXP Semiconductors Germany " } ,
{ 0x05 , " Infineon Technologies AG Germany " } ,
{ 0x06 , " Cylink USA " } ,
{ 0x07 , " Texas Instrument France " } ,
{ 0x08 , " Fujitsu Limited Japan " } ,
{ 0x09 , " Matsushita Electronics Corporation, Semiconductor Company Japan " } ,
{ 0x0A , " NEC Japan " } ,
{ 0x0B , " Oki Electric Industry Co. Ltd Japan " } ,
{ 0x0C , " Toshiba Corp. Japan " } ,
{ 0x0D , " Mitsubishi Electric Corp. Japan " } ,
{ 0x0E , " Samsung Electronics Co. Ltd Korea " } ,
{ 0x0F , " Hynix / Hyundai, Korea " } ,
{ 0x10 , " LG-Semiconductors Co. Ltd Korea " } ,
{ 0x11 , " Emosyn-EM Microelectronics USA " } ,
{ 0x12 , " INSIDE Technology France " } ,
{ 0x13 , " ORGA Kartensysteme GmbH Germany " } ,
{ 0x14 , " SHARP Corporation Japan " } ,
{ 0x15 , " ATMEL France " } ,
{ 0x16 , " EM Microelectronic-Marin SA Switzerland " } ,
{ 0x17 , " KSW Microtec GmbH Germany " } ,
{ 0x18 , " ZMD AG Germany " } ,
{ 0x19 , " XICOR, Inc. USA " } ,
{ 0x1A , " Sony Corporation Japan " } ,
{ 0x1B , " Malaysia Microelectronic Solutions Sdn. Bhd Malaysia " } ,
{ 0x1C , " Emosyn USA " } ,
{ 0x1D , " Shanghai Fudan Microelectronics Co. Ltd. P.R. China " } ,
{ 0x1E , " Magellan Technology Pty Limited Australia " } ,
{ 0x1F , " Melexis NV BO Switzerland " } ,
{ 0x20 , " Renesas Technology Corp. Japan " } ,
{ 0x21 , " TAGSYS France " } ,
{ 0x22 , " Transcore USA " } ,
{ 0x23 , " Shanghai belling corp., ltd. China " } ,
{ 0x24 , " Masktech Germany Gmbh Germany " } ,
{ 0x25 , " Innovision Research and Technology Plc UK " } ,
{ 0x26 , " Hitachi ULSI Systems Co., Ltd. Japan " } ,
{ 0x27 , " Cypak AB Sweden " } ,
{ 0x28 , " Ricoh Japan " } ,
{ 0x29 , " ASK France " } ,
{ 0x2A , " Unicore Microsystems, LLC Russian Federation " } ,
{ 0x2B , " Dallas Semiconductor/Maxim USA " } ,
{ 0x2C , " Impinj, Inc. USA " } ,
{ 0x2D , " RightPlug Alliance USA " } ,
{ 0x2E , " Broadcom Corporation USA " } ,
{ 0x2F , " MStar Semiconductor, Inc Taiwan, ROC " } ,
{ 0x30 , " BeeDar Technology Inc. USA " } ,
{ 0x31 , " RFIDsec Denmark " } ,
{ 0x32 , " Schweizer Electronic AG Germany " } ,
{ 0x33 , " AMIC Technology Corp Taiwan " } ,
{ 0x34 , " Mikron JSC Russia " } ,
{ 0x35 , " Fraunhofer Institute for Photonic Microsystems Germany " } ,
{ 0x36 , " IDS Microchip AG Switzerland " } ,
2019-08-02 00:16:33 +08:00
{ 0x37 , " Thinfilm - Kovio USA " } ,
2019-03-10 06:35:06 +08:00
{ 0x38 , " HMT Microelectronic Ltd Switzerland " } ,
{ 0x39 , " Silicon Craft Technology Thailand " } ,
{ 0x3A , " Advanced Film Device Inc. Japan " } ,
{ 0x3B , " Nitecrest Ltd UK " } ,
{ 0x3C , " Verayo Inc. USA " } ,
{ 0x3D , " HID Global USA " } ,
{ 0x3E , " Productivity Engineering Gmbh Germany " } ,
{ 0x3F , " Austriamicrosystems AG (reserved) Austria " } ,
{ 0x40 , " Gemalto SA France " } ,
{ 0x41 , " Renesas Electronics Corporation Japan " } ,
{ 0x42 , " 3Alogics Inc Korea " } ,
{ 0x43 , " Top TroniQ Asia Limited Hong Kong " } ,
{ 0x44 , " Gentag Inc. USA " } ,
{ 0x45 , " Invengo Information Technology Co.Ltd China " } ,
{ 0x46 , " Guangzhou Sysur Microelectronics, Inc China " } ,
{ 0x47 , " CEITEC S.A. Brazil " } ,
{ 0x48 , " Shanghai Quanray Electronics Co. Ltd. China " } ,
{ 0x49 , " MediaTek Inc Taiwan " } ,
{ 0x4A , " Angstrem PJSC Russia " } ,
{ 0x4B , " Celisic Semiconductor (Hong Kong) Limited China " } ,
{ 0x4C , " LEGIC Identsystems AG Switzerland " } ,
{ 0x4D , " Balluff GmbH Germany " } ,
{ 0x4E , " Oberthur Technologies France " } ,
{ 0x4F , " Silterra Malaysia Sdn. Bhd. Malaysia " } ,
{ 0x50 , " DELTA Danish Electronics, Light & Acoustics Denmark " } ,
{ 0x51 , " Giesecke & Devrient GmbH Germany " } ,
{ 0x52 , " Shenzhen China Vision Microelectronics Co., Ltd. China " } ,
{ 0x53 , " Shanghai Feiju Microelectronics Co. Ltd. China " } ,
{ 0x54 , " Intel Corporation USA " } ,
{ 0x55 , " Microsensys GmbH Germany " } ,
{ 0x56 , " Sonix Technology Co., Ltd. Taiwan " } ,
{ 0x57 , " Qualcomm Technologies Inc USA " } ,
{ 0x58 , " Realtek Semiconductor Corp Taiwan " } ,
{ 0x59 , " Freevision Technologies Co. Ltd China " } ,
{ 0x5A , " Giantec Semiconductor Inc. China " } ,
{ 0x5B , " JSC Angstrem-T Russia " } ,
{ 0x5C , " STARCHIP France " } ,
{ 0x5D , " SPIRTECH France " } ,
{ 0x5E , " GANTNER Electronic GmbH Austria " } ,
{ 0x5F , " Nordic Semiconductor Norway " } ,
{ 0x60 , " Verisiti Inc USA " } ,
{ 0x61 , " Wearlinks Technology Inc. China " } ,
{ 0x62 , " Userstar Information Systems Co., Ltd Taiwan " } ,
{ 0x63 , " Pragmatic Printing Ltd. UK " } ,
{ 0x64 , " Associacao do Laboratorio de Sistemas Integraveis Tecnologico – LSI-TEC Brazil " } ,
{ 0x65 , " Tendyron Corporation China " } ,
{ 0x66 , " MUTO Smart Co., Ltd. Korea " } ,
{ 0x67 , " ON Semiconductor USA " } ,
{ 0x68 , " TUBITAK BILGEM Turkey " } ,
{ 0x69 , " Huada Semiconductor Co., Ltd China " } ,
{ 0x6A , " SEVENEY France " } ,
{ 0x6B , " ISSM France " } ,
{ 0x6C , " Wisesec Ltd Israel " } ,
{ 0x7C , " DB HiTek Co Ltd Korea " } ,
{ 0x7D , " SATO Vicinity Australia " } ,
{ 0x7E , " Holtek Taiwan " } ,
{ 0x00 , " no tag-info available " } // must be the last entry
2015-01-08 04:06:15 +08:00
} ;
// get a product description based on the UID
2019-03-10 06:35:06 +08:00
// uid[8] tag uid
2019-03-09 15:59:13 +08:00
// returns description of the best match
2019-04-10 16:21:42 +08:00
const char * getTagInfo ( uint8_t uid ) {
2015-01-08 04:06:15 +08:00
2019-03-10 06:35:06 +08:00
int i ;
2019-03-09 15:59:13 +08:00
2019-08-01 05:44:53 +08:00
for ( i = 0 ; i < ARRAYLEN ( manufactureMapping ) ; + + i )
2019-03-10 07:00:59 +08:00
if ( uid = = manufactureMapping [ i ] . uid )
2019-03-10 06:35:06 +08:00
return manufactureMapping [ i ] . desc ;
2015-01-08 04:06:15 +08:00
2019-03-10 06:35:06 +08:00
//No match, return default
2019-08-01 05:44:53 +08:00
return manufactureMapping [ ARRAYLEN ( manufactureMapping ) - 1 ] . desc ;
2015-01-08 04:06:15 +08:00
}
2019-01-31 00:16:50 +08:00
// iso14a apdu input frame length
static uint16_t frameLength = 0 ;
uint16_t atsFSC [ ] = { 16 , 24 , 32 , 40 , 48 , 64 , 96 , 128 , 256 } ;
2019-04-10 19:06:05 +08:00
static int usage_hf_14a_sim ( void ) {
2019-03-10 06:35:06 +08:00
// PrintAndLogEx(NORMAL, "\n Emulating ISO/IEC 14443 type A tag with 4,7 or 10 byte UID\n");
PrintAndLogEx ( NORMAL , " \n Emulating ISO/IEC 14443 type A tag with 4,7 byte UID \n " ) ;
PrintAndLogEx ( NORMAL , " Usage: hf 14a sim [h] t <type> u <uid> [x] [e] [v] " ) ;
PrintAndLogEx ( NORMAL , " Options: " ) ;
PrintAndLogEx ( NORMAL , " h : This help " ) ;
PrintAndLogEx ( NORMAL , " t : 1 = MIFARE Classic 1k " ) ;
PrintAndLogEx ( NORMAL , " 2 = MIFARE Ultralight " ) ;
PrintAndLogEx ( NORMAL , " 3 = MIFARE Desfire " ) ;
PrintAndLogEx ( NORMAL , " 4 = ISO/IEC 14443-4 " ) ;
PrintAndLogEx ( NORMAL , " 5 = MIFARE Tnp3xxx " ) ;
PrintAndLogEx ( NORMAL , " 6 = MIFARE Mini " ) ;
PrintAndLogEx ( NORMAL , " 7 = AMIIBO (NTAG 215), pack 0x8080 " ) ;
PrintAndLogEx ( NORMAL , " 8 = MIFARE Classic 4k " ) ;
PrintAndLogEx ( NORMAL , " 9 = FM11RF005SH Shanghai Metro " ) ;
// PrintAndLogEx(NORMAL, " u : 4, 7 or 10 byte UID");
PrintAndLogEx ( NORMAL , " u : 4, 7 byte UID " ) ;
PrintAndLogEx ( NORMAL , " x : (Optional) Performs the 'reader attack', nr/ar attack against a reader " ) ;
PrintAndLogEx ( NORMAL , " e : (Optional) Fill simulator keys from found keys " ) ;
PrintAndLogEx ( NORMAL , " v : (Optional) Verbose " ) ;
PrintAndLogEx ( NORMAL , " Examples: " ) ;
PrintAndLogEx ( NORMAL , " hf 14a sim t 1 u 11223344 x " ) ;
PrintAndLogEx ( NORMAL , " hf 14a sim t 1 u 11223344 " ) ;
PrintAndLogEx ( NORMAL , " hf 14a sim t 1 u 11223344556677 " ) ;
// PrintAndLogEx(NORMAL, " hf 14a sim t 1 u 11223445566778899AA\n");
return 0 ;
2015-11-10 18:45:45 +08:00
}
2019-04-10 19:06:05 +08:00
static int usage_hf_14a_sniff ( void ) {
2019-03-10 06:35:06 +08:00
PrintAndLogEx ( NORMAL , " It get data from the field and saves it into command buffer. " ) ;
PrintAndLogEx ( NORMAL , " Buffer accessible from command 'hf list 14a' " ) ;
PrintAndLogEx ( NORMAL , " Usage: hf 14a sniff [c][r] " ) ;
PrintAndLogEx ( NORMAL , " c - triggered by first data from card " ) ;
PrintAndLogEx ( NORMAL , " r - triggered by first 7-bit request from reader (REQ,WUP,...) " ) ;
PrintAndLogEx ( NORMAL , " Examples: " ) ;
PrintAndLogEx ( NORMAL , " hf 14a sniff c r " ) ;
return 0 ;
2015-11-10 18:45:45 +08:00
}
2019-04-10 19:06:05 +08:00
static int usage_hf_14a_raw ( void ) {
2019-03-10 06:35:06 +08:00
PrintAndLogEx ( NORMAL , " Usage: hf 14a raw [-h] [-r] [-c] [-p] [-a] [-T] [-t] <milliseconds> [-b] <number of bits> <0A 0B 0C ... hex> " ) ;
PrintAndLogEx ( NORMAL , " -h this help " ) ;
PrintAndLogEx ( NORMAL , " -r do not read response " ) ;
PrintAndLogEx ( NORMAL , " -c calculate and append CRC " ) ;
PrintAndLogEx ( NORMAL , " -p leave the signal field ON after receive " ) ;
PrintAndLogEx ( NORMAL , " -a active signal field ON without select " ) ;
PrintAndLogEx ( NORMAL , " -s active signal field ON with select " ) ;
PrintAndLogEx ( NORMAL , " -b number of bits to send. Useful for send partial byte " ) ;
PrintAndLogEx ( NORMAL , " -t timeout in ms " ) ;
PrintAndLogEx ( NORMAL , " -T use Topaz protocol to send command " ) ;
PrintAndLogEx ( NORMAL , " -3 ISO14443-3 select only (skip RATS) " ) ;
return 0 ;
2015-11-10 18:45:45 +08:00
}
2019-04-10 19:06:05 +08:00
static int usage_hf_14a_reader ( void ) {
2019-03-10 06:35:06 +08:00
PrintAndLogEx ( NORMAL , " Usage: hf 14a reader [k|s|x] [3] " ) ;
PrintAndLogEx ( NORMAL , " k keep the field active after command executed " ) ;
PrintAndLogEx ( NORMAL , " s silent (no messages) " ) ;
PrintAndLogEx ( NORMAL , " x just drop the signal field " ) ;
PrintAndLogEx ( NORMAL , " 3 ISO14443-3 select only (skip RATS) " ) ;
return 0 ;
2017-11-11 05:55:33 +08:00
}
2019-04-10 19:06:05 +08:00
static int usage_hf_14a_info ( void ) {
2019-03-10 06:35:06 +08:00
PrintAndLogEx ( NORMAL , " This command makes more extensive tests against a ISO14443a tag in order to collect information " ) ;
PrintAndLogEx ( NORMAL , " Usage: hf 14a info [h|s] " ) ;
PrintAndLogEx ( NORMAL , " s silent (no messages) " ) ;
PrintAndLogEx ( NORMAL , " n test for nack bug " ) ;
return 0 ;
2017-11-11 05:55:33 +08:00
}
2015-11-10 18:45:45 +08:00
2019-04-13 00:41:14 +08:00
static int CmdHF14AList ( const char * Cmd ) {
2019-04-10 18:23:40 +08:00
( void ) Cmd ; // Cmd is not used so far
2019-03-10 06:35:06 +08:00
//PrintAndLogEx(NORMAL, "Deprecated command, use 'hf list 14a' instead");
CmdTraceList ( " 14a " ) ;
return 0 ;
Client cleanup and restructuring. Stage 1...
Next Step is refactoring some of the giant functions which are
just copy/paste of some other ones with just a few line changes,
removing unnecessary 'goto' etc.
The MS Windows version is broken with this commit but will be fixed
soon. Everything can't be done all at once :P
The commands are now hierarchical, for example:
"hf 14a read" vs. "hf 14b read".
You can also request help:
"hf help", "data help", "hf 15 help" etc.
Indents are now space-based, not tab-based anymore. Hopefully
no one will be trolling about it, considering the suicide-prone work
being done here ;)
client/cmdhw.c, client/proxusb.c, client/cmdhw.h, client/proxusb.h,
client/cmdmain.c, client/cmdlfhid.c, client/cmdmain.h, client/cmdlfhid.h,
client/data.c, client/data.h, client/cmdhf.c, client/cmdlf.c,
client/cmdhf.h, client/cmdhf15.c, client/cmdhf14b.c, client/cmdlf.h,
client/cmdhf15.h, client/cmdhf14b.h, client/cmddata.c, client/cmddata.h,
client/ui.c, client/cmdparser.c, client/cmdlfti.c, client/ui.h,
client/cmdlfem4x.c, client/cmdparser.h, client/cmdlfti.h, client/cmdlfem4x.h,
client/graph.c, client/graph.h, client/cmdhf14a.c, client/cmdhf14a.h,
client/cmdhflegic.c, client/cmdhflegic.c: New files.
client/cli.c, client/flasher.c, client/snooper.c, client/proxmark3.c,
client/proxmark3.h, client/Makefile: Update accordingly.
client/flash.h, client/flash.c, client/proxgui.cpp: Cosmetic changes.
client/translate.h, client/command.c, client/gui.c,
client/usb.c, client/prox.h: Remove.
include/usb_cmd.h (CMD_ACQUIRE_RAW_ADC_SAMPLES_ISO_14443_SIM): Remove dead cmd.
common/crc16.h: New file.
common/crc16.c: Modify accordingly.
common/iso14443crc.h: New file.
common/iso14443_crc.c: Rename to
common/iso14443crc.c: and modify accordingly.
armsrc/lfops.c, armsrc/iso14443.c,
armsrc/iso14443a.c: include .h files from
the common directory instead of including the c files.
common/Makefile.common, armsrc/Makefile: Modify accordingly.
2010-02-04 09:27:07 +08:00
}
2019-03-10 18:20:22 +08:00
int Hf14443_4aGetCardData ( iso14a_card_select_t * card ) {
2019-05-08 01:51:33 +08:00
SendCommandMIX ( CMD_READER_ISO_14443a , ISO14A_CONNECT , 0 , 0 , NULL , 0 ) ;
2019-03-10 06:35:06 +08:00
2019-04-18 18:43:35 +08:00
PacketResponseNG resp ;
2019-03-10 07:00:59 +08:00
WaitForResponse ( CMD_ACK , & resp ) ;
2019-03-10 06:35:06 +08:00
2019-04-18 05:44:48 +08:00
memcpy ( card , ( iso14a_card_select_t * ) resp . data . asBytes , sizeof ( iso14a_card_select_t ) ) ;
2019-03-10 06:35:06 +08:00
2019-04-18 05:44:48 +08:00
uint64_t select_status = resp . oldarg [ 0 ] ; // 0: couldn't read, 1: OK, with ATS, 2: OK, no ATS, 3: proprietary Anticollision
2019-03-10 06:35:06 +08:00
2019-03-10 07:00:59 +08:00
if ( select_status = = 0 ) {
2019-04-08 00:12:58 +08:00
PrintAndLogEx ( ERR , " E->iso14443a card select failed " ) ;
2019-03-10 06:35:06 +08:00
return 1 ;
}
2019-03-10 07:00:59 +08:00
if ( select_status = = 2 ) {
2019-04-08 00:12:58 +08:00
PrintAndLogEx ( ERR , " E->Card doesn't support iso14443-4 mode " ) ;
2019-03-10 06:35:06 +08:00
return 1 ;
}
2019-03-10 07:00:59 +08:00
if ( select_status = = 3 ) {
2019-04-08 00:12:58 +08:00
PrintAndLogEx ( NORMAL , " E->Card doesn't support standard iso14443-3 anticollision " ) ;
PrintAndLogEx ( NORMAL , " \t ATQA : %02x %02x " , card - > atqa [ 1 ] , card - > atqa [ 0 ] ) ;
2019-03-10 06:35:06 +08:00
return 1 ;
}
2019-04-08 00:12:58 +08:00
PrintAndLogEx ( NORMAL , " UID: %s " , sprint_hex ( card - > uid , card - > uidlen ) ) ;
PrintAndLogEx ( NORMAL , " ATQA: %02x %02x " , card - > atqa [ 1 ] , card - > atqa [ 0 ] ) ;
2019-04-18 05:44:48 +08:00
PrintAndLogEx ( NORMAL , " SAK: %02x [% " PRIu64 " ] " , card - > sak , resp . oldarg [ 0 ] ) ;
2019-03-10 07:00:59 +08:00
if ( card - > ats_len < 3 ) { // a valid ATS consists of at least the length byte (TL) and 2 CRC bytes
2019-04-08 00:12:58 +08:00
PrintAndLogEx ( NORMAL , " E-> Error ATS length(%d) : %s " , card - > ats_len , sprint_hex ( card - > ats , card - > ats_len ) ) ;
2019-03-10 06:35:06 +08:00
return 1 ;
}
2019-04-10 15:47:36 +08:00
2019-04-08 00:12:58 +08:00
PrintAndLogEx ( NORMAL , " ATS: %s " , sprint_hex ( card - > ats , card - > ats_len ) ) ;
2019-03-10 06:35:06 +08:00
return 0 ;
2018-11-20 22:25:19 +08:00
}
2019-04-13 00:41:14 +08:00
static int CmdHF14AReader ( const char * Cmd ) {
2017-11-11 05:55:33 +08:00
2019-03-10 06:35:06 +08:00
uint32_t cm = ISO14A_CONNECT ;
bool disconnectAfter = true , silent = false ;
int cmdp = 0 ;
while ( param_getchar ( Cmd , cmdp ) ! = 0x00 ) {
switch ( tolower ( param_getchar ( Cmd , cmdp ) ) ) {
2019-03-10 07:00:59 +08:00
case ' h ' :
return usage_hf_14a_reader ( ) ;
case ' 3 ' :
cm | = ISO14A_NO_RATS ;
break ;
case ' k ' :
disconnectAfter = false ;
break ;
case ' s ' :
silent = true ;
break ;
case ' x ' :
cm & = ~ ISO14A_CONNECT ;
break ;
default :
PrintAndLogEx ( WARNING , " Unknown command. " ) ;
return 1 ;
2019-03-10 06:35:06 +08:00
}
cmdp + + ;
}
if ( ! disconnectAfter )
cm | = ISO14A_NO_DISCONNECT ;
clearCommandBuffer ( ) ;
2019-05-08 01:51:33 +08:00
SendCommandMIX ( CMD_READER_ISO_14443a , cm , 0 , 0 , NULL , 0 ) ;
2019-03-10 06:35:06 +08:00
if ( ISO14A_CONNECT & cm ) {
2019-04-18 18:43:35 +08:00
PacketResponseNG resp ;
2019-03-10 06:35:06 +08:00
if ( ! WaitForResponseTimeout ( CMD_ACK , & resp , 2500 ) ) {
if ( ! silent ) PrintAndLogEx ( WARNING , " iso14443a card select failed " ) ;
DropField ( ) ;
return 1 ;
}
iso14a_card_select_t card ;
2019-04-18 05:44:48 +08:00
memcpy ( & card , ( iso14a_card_select_t * ) resp . data . asBytes , sizeof ( iso14a_card_select_t ) ) ;
2019-03-10 06:35:06 +08:00
/*
0 : couldn ' t read
1 : OK , with ATS
2 : OK , no ATS
3 : proprietary Anticollision
*/
2019-04-18 05:44:48 +08:00
uint64_t select_status = resp . oldarg [ 0 ] ;
2019-03-10 06:35:06 +08:00
if ( select_status = = 0 ) {
if ( ! silent ) PrintAndLogEx ( WARNING , " iso14443a card select failed " ) ;
DropField ( ) ;
return 1 ;
}
if ( select_status = = 3 ) {
PrintAndLogEx ( NORMAL , " Card doesn't support standard iso14443-3 anticollision " ) ;
PrintAndLogEx ( NORMAL , " ATQA : %02x %02x " , card . atqa [ 1 ] , card . atqa [ 0 ] ) ;
DropField ( ) ;
return 1 ;
}
PrintAndLogEx ( NORMAL , " UID : %s " , sprint_hex ( card . uid , card . uidlen ) ) ;
PrintAndLogEx ( NORMAL , " ATQA : %02x %02x " , card . atqa [ 1 ] , card . atqa [ 0 ] ) ;
2019-04-18 05:44:48 +08:00
PrintAndLogEx ( NORMAL , " SAK : %02x [% " PRIu64 " ] " , card . sak , resp . oldarg [ 0 ] ) ;
2019-03-10 06:35:06 +08:00
2019-03-10 07:00:59 +08:00
if ( card . ats_len > = 3 ) { // a valid ATS consists of at least the length byte (TL) and 2 CRC bytes
2019-03-10 06:35:06 +08:00
PrintAndLogEx ( NORMAL , " ATS : %s " , sprint_hex ( card . ats , card . ats_len ) ) ;
}
if ( ! disconnectAfter ) {
if ( ! silent ) PrintAndLogEx ( SUCCESS , " Card is selected. You can now start sending commands " ) ;
}
}
if ( disconnectAfter ) {
if ( ! silent ) PrintAndLogEx ( SUCCESS , " field dropped. " ) ;
}
return 0 ;
2017-10-30 19:29:02 +08:00
}
2019-04-13 00:41:14 +08:00
static int CmdHF14AInfo ( const char * Cmd ) {
2019-03-09 15:59:13 +08:00
2019-03-10 06:35:06 +08:00
if ( Cmd [ 0 ] = = ' h ' | | Cmd [ 0 ] = = ' H ' ) return usage_hf_14a_info ( ) ;
2019-04-13 00:41:14 +08:00
bool verbose = ! ( Cmd [ 0 ] = = ' s ' | | Cmd [ 0 ] = = ' S ' ) ;
2019-03-10 06:35:06 +08:00
bool do_nack_test = ( Cmd [ 0 ] = = ' n ' | | Cmd [ 0 ] = = ' N ' ) ;
2019-04-13 00:41:14 +08:00
infoHF14A ( verbose , do_nack_test ) ;
return 0 ;
}
2019-03-10 06:35:06 +08:00
2019-04-13 00:41:14 +08:00
// Collect ISO14443 Type A UIDs
static int CmdHF14ACUIDs ( const char * Cmd ) {
// requested number of UIDs
int n = atoi ( Cmd ) ;
// collect at least 1 (e.g. if no parameter was given)
n = n > 0 ? n : 1 ;
2019-03-10 06:35:06 +08:00
2019-04-13 00:41:14 +08:00
uint64_t t1 = msclock ( ) ;
PrintAndLogEx ( SUCCESS , " collecting %d UIDs " , n ) ;
2019-03-10 06:35:06 +08:00
2019-04-13 00:41:14 +08:00
// repeat n times
for ( int i = 0 ; i < n ; i + + ) {
2019-03-10 06:35:06 +08:00
2019-07-11 19:01:34 +08:00
if ( kbd_enter_pressed ( ) ) {
2019-04-13 00:41:14 +08:00
PrintAndLogEx ( WARNING , " \n [!] aborted via keyboard! \n " ) ;
break ;
}
2019-03-10 06:35:06 +08:00
2019-04-13 00:41:14 +08:00
// execute anticollision procedure
2019-05-08 01:51:33 +08:00
SendCommandMIX ( CMD_READER_ISO_14443a , ISO14A_CONNECT | ISO14A_NO_RATS , 0 , 0 , NULL , 0 ) ;
2019-03-10 06:35:06 +08:00
2019-04-18 18:43:35 +08:00
PacketResponseNG resp ;
2019-04-13 00:41:14 +08:00
WaitForResponse ( CMD_ACK , & resp ) ;
2019-03-10 06:35:06 +08:00
2019-04-18 05:44:48 +08:00
iso14a_card_select_t * card = ( iso14a_card_select_t * ) resp . data . asBytes ;
2019-03-10 06:35:06 +08:00
2019-04-13 00:41:14 +08:00
// check if command failed
2019-04-18 05:44:48 +08:00
if ( resp . oldarg [ 0 ] = = 0 ) {
2019-04-13 00:41:14 +08:00
PrintAndLogEx ( WARNING , " card select failed. " ) ;
} else {
char uid_string [ 20 ] ;
for ( uint16_t m = 0 ; m < card - > uidlen ; m + + ) {
sprintf ( & uid_string [ 2 * m ] , " %02X " , card - > uid [ m ] ) ;
2019-03-10 06:35:06 +08:00
}
2019-04-13 00:41:14 +08:00
PrintAndLogEx ( NORMAL , " %s " , uid_string ) ;
}
2019-03-10 06:35:06 +08:00
}
2019-04-13 00:41:14 +08:00
PrintAndLogEx ( SUCCESS , " end: % " PRIu64 " seconds " , ( msclock ( ) - t1 ) / 1000 ) ;
return 1 ;
}
// ## simulate iso14443a tag
int CmdHF14ASim ( const char * Cmd ) {
2019-05-27 01:42:27 +08:00
2019-04-13 00:41:14 +08:00
int uidlen = 0 ;
2019-05-27 01:42:27 +08:00
uint8_t flags = 0 , tagtype = 1 , cmdp = 0 ;
uint8_t uid [ 10 ] = { 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 } ;
2019-04-13 00:41:14 +08:00
bool useUIDfromEML = true ;
bool setEmulatorMem = false ;
bool verbose = false ;
2019-05-27 01:42:27 +08:00
bool errors = false ;
2019-03-10 06:35:06 +08:00
2019-04-13 00:41:14 +08:00
while ( param_getchar ( Cmd , cmdp ) ! = 0x00 & & ! errors ) {
2019-05-27 01:42:27 +08:00
switch ( tolower ( param_getchar ( Cmd , cmdp ) ) ) {
2019-04-13 00:41:14 +08:00
case ' h ' :
return usage_hf_14a_sim ( ) ;
case ' t ' :
// Retrieve the tag type
tagtype = param_get8ex ( Cmd , cmdp + 1 , 0 , 10 ) ;
if ( tagtype = = 0 )
errors = true ;
cmdp + = 2 ;
break ;
case ' u ' :
// Retrieve the full 4,7,10 byte long uid
param_gethex_ex ( Cmd , cmdp + 1 , uid , & uidlen ) ;
2019-05-27 01:42:27 +08:00
uidlen > > = 1 ;
2019-04-13 00:41:14 +08:00
switch ( uidlen ) {
2019-05-27 01:42:27 +08:00
//case 10: flags |= FLAG_10B_UID_IN_DATA; break;
case 7 :
2019-04-13 00:41:14 +08:00
flags | = FLAG_7B_UID_IN_DATA ;
break ;
2019-05-27 01:42:27 +08:00
case 4 :
2019-04-13 00:41:14 +08:00
flags | = FLAG_4B_UID_IN_DATA ;
break ;
default :
errors = true ;
break ;
}
if ( ! errors ) {
2019-05-27 01:42:27 +08:00
PrintAndLogEx ( SUCCESS , " Emulating ISO/IEC 14443 type A tag with %d byte UID (%s) " , uidlen , sprint_hex ( uid , uidlen ) ) ;
2019-04-13 00:41:14 +08:00
useUIDfromEML = false ;
}
cmdp + = 2 ;
break ;
case ' v ' :
verbose = true ;
cmdp + + ;
break ;
case ' x ' :
flags | = FLAG_NR_AR_ATTACK ;
cmdp + + ;
break ;
case ' e ' :
setEmulatorMem = true ;
cmdp + + ;
break ;
default :
PrintAndLogEx ( WARNING , " Unknown parameter '%c' " , param_getchar ( Cmd , cmdp ) ) ;
errors = true ;
break ;
}
2019-03-10 06:35:06 +08:00
}
2019-04-13 00:41:14 +08:00
//Validations
if ( errors | | cmdp = = 0 ) return usage_hf_14a_sim ( ) ;
2019-03-10 06:35:06 +08:00
2019-04-13 00:41:14 +08:00
if ( useUIDfromEML )
flags | = FLAG_UID_IN_EMUL ;
2019-03-10 06:35:06 +08:00
2019-05-27 01:42:27 +08:00
struct {
2019-06-08 03:40:33 +08:00
uint8_t tagtype ;
uint8_t flags ;
uint8_t uid [ 10 ] ;
2019-05-27 01:42:27 +08:00
} PACKED payload ;
2019-06-08 03:40:33 +08:00
2019-05-27 01:42:27 +08:00
payload . tagtype = tagtype ;
payload . flags = flags ;
memcpy ( payload . uid , uid , uidlen ) ;
2019-06-08 03:40:33 +08:00
2019-04-13 00:41:14 +08:00
clearCommandBuffer ( ) ;
2019-05-27 01:42:27 +08:00
SendCommandNG ( CMD_SIMULATE_TAG_ISO_14443a , ( uint8_t * ) & payload , sizeof ( payload ) ) ;
2019-04-18 18:43:35 +08:00
PacketResponseNG resp ;
2019-03-10 06:35:06 +08:00
2019-04-13 00:41:14 +08:00
PrintAndLogEx ( SUCCESS , " press pm3-button to abort simulation " ) ;
2019-03-10 06:35:06 +08:00
2019-07-11 19:01:34 +08:00
while ( ! kbd_enter_pressed ( ) ) {
2019-05-27 03:00:49 +08:00
if ( WaitForResponseTimeout ( CMD_SIMULATE_MIFARE_CARD , & resp , 1500 ) = = 0 ) continue ;
if ( resp . status ! = PM3_SUCCESS ) break ;
2019-06-08 03:40:33 +08:00
2019-05-27 03:00:49 +08:00
if ( ( flags & FLAG_NR_AR_ATTACK ) ! = FLAG_NR_AR_ATTACK ) break ;
2019-06-08 03:40:33 +08:00
nonces_t * data = ( nonces_t * ) resp . data . asBytes ;
2019-04-13 00:41:14 +08:00
readerAttack ( data [ 0 ] , setEmulatorMem , verbose ) ;
}
2019-06-08 03:40:33 +08:00
if ( resp . status = = PM3_EOPABORTED & & ( ( flags & FLAG_NR_AR_ATTACK ) = = FLAG_NR_AR_ATTACK ) )
2019-05-27 03:00:49 +08:00
showSectorTable ( ) ;
PrintAndLogEx ( INFO , " Done " ) ;
return PM3_SUCCESS ;
2019-04-13 00:41:14 +08:00
}
2019-03-28 21:19:41 +08:00
2019-04-13 00:41:14 +08:00
int CmdHF14ASniff ( const char * Cmd ) {
2019-06-08 00:41:39 +08:00
uint8_t param = 0 ;
2019-05-27 03:00:49 +08:00
for ( uint8_t i = 0 ; i < 2 ; i + + ) {
2019-06-08 00:41:39 +08:00
uint8_t ctmp = tolower ( param_getchar ( Cmd , i ) ) ;
2019-04-13 00:41:14 +08:00
if ( ctmp = = ' h ' ) return usage_hf_14a_sniff ( ) ;
if ( ctmp = = ' c ' ) param | = 0x01 ;
if ( ctmp = = ' r ' ) param | = 0x02 ;
}
clearCommandBuffer ( ) ;
2019-05-27 03:00:49 +08:00
SendCommandNG ( CMD_SNIFF_ISO_14443a , ( uint8_t * ) & param , sizeof ( uint8_t ) ) ;
return PM3_SUCCESS ;
2019-04-13 00:41:14 +08:00
}
int ExchangeRAW14a ( uint8_t * datain , int datainlen , bool activateField , bool leaveSignalON , uint8_t * dataout , int maxdataoutlen , int * dataoutlen ) {
static uint8_t responseNum = 0 ;
uint16_t cmdc = 0 ;
* dataoutlen = 0 ;
if ( activateField ) {
responseNum = 1 ;
2019-04-18 18:43:35 +08:00
PacketResponseNG resp ;
2019-04-13 00:41:14 +08:00
// Anticollision + SELECT card
2019-05-08 01:51:33 +08:00
SendCommandMIX ( CMD_READER_ISO_14443a , ISO14A_CONNECT | ISO14A_NO_DISCONNECT , 0 , 0 , NULL , 0 ) ;
2019-04-13 00:41:14 +08:00
if ( ! WaitForResponseTimeout ( CMD_ACK , & resp , 1500 ) ) {
2019-04-17 02:00:25 +08:00
PrintAndLogEx ( ERR , " Proxmark3 connection timeout. " ) ;
2019-04-13 00:41:14 +08:00
return 1 ;
2019-03-10 06:35:06 +08:00
}
2019-04-13 00:41:14 +08:00
// check result
2019-04-18 05:44:48 +08:00
if ( resp . oldarg [ 0 ] = = 0 ) {
2019-04-13 00:41:14 +08:00
PrintAndLogEx ( ERR , " No card in field. " ) ;
return 1 ;
2019-03-10 06:35:06 +08:00
}
2019-04-13 00:41:14 +08:00
2019-04-18 05:44:48 +08:00
if ( resp . oldarg [ 0 ] ! = 1 & & resp . oldarg [ 0 ] ! = 2 ) {
PrintAndLogEx ( ERR , " Card not in iso14443-4. res=%d. " , resp . oldarg [ 0 ] ) ;
2019-04-13 00:41:14 +08:00
return 1 ;
2019-03-10 06:35:06 +08:00
}
2019-04-13 00:41:14 +08:00
2019-04-18 05:44:48 +08:00
if ( resp . oldarg [ 0 ] = = 2 ) { // 0: couldn't read, 1: OK, with ATS, 2: OK, no ATS, 3: proprietary Anticollision
2019-04-13 00:41:14 +08:00
// get ATS
uint8_t rats [ ] = { 0xE0 , 0x80 } ; // FSDI=8 (FSD=256), CID=0
2019-04-19 23:03:39 +08:00
SendCommandOLD ( CMD_READER_ISO_14443a , ISO14A_RAW | ISO14A_APPEND_CRC | ISO14A_NO_DISCONNECT , 2 , 0 , rats , 2 ) ;
2019-04-13 00:41:14 +08:00
if ( ! WaitForResponseTimeout ( CMD_ACK , & resp , 1500 ) ) {
2019-04-17 02:00:25 +08:00
PrintAndLogEx ( ERR , " Proxmark3 connection timeout. " ) ;
2019-04-13 00:41:14 +08:00
return 1 ;
2019-03-10 06:35:06 +08:00
}
2019-04-13 00:41:14 +08:00
2019-04-18 05:44:48 +08:00
if ( resp . oldarg [ 0 ] = = 0 ) { // ats_len
2019-04-13 00:41:14 +08:00
PrintAndLogEx ( ERR , " Can't get ATS. " ) ;
return 1 ;
2019-03-10 06:35:06 +08:00
}
}
}
2019-04-13 00:41:14 +08:00
if ( leaveSignalON )
cmdc | = ISO14A_NO_DISCONNECT ;
2019-03-10 06:35:06 +08:00
2019-05-01 03:10:11 +08:00
uint8_t data [ PM3_CMD_DATA_SIZE ] = { 0x0a | responseNum , 0x00 } ;
2019-04-13 00:41:14 +08:00
responseNum ^ = 1 ;
2019-04-19 23:03:39 +08:00
memcpy ( & data [ 2 ] , datain , datainlen & 0xFFFF ) ;
SendCommandOLD ( CMD_READER_ISO_14443a , ISO14A_RAW | ISO14A_APPEND_CRC | cmdc , ( datainlen & 0xFFFF ) + 2 , 0 , data , ( datainlen & 0xFFFF ) + 2 ) ;
2019-03-10 06:35:06 +08:00
2019-04-13 00:41:14 +08:00
uint8_t * recv ;
2019-04-18 18:43:35 +08:00
PacketResponseNG resp ;
Client cleanup and restructuring. Stage 1...
Next Step is refactoring some of the giant functions which are
just copy/paste of some other ones with just a few line changes,
removing unnecessary 'goto' etc.
The MS Windows version is broken with this commit but will be fixed
soon. Everything can't be done all at once :P
The commands are now hierarchical, for example:
"hf 14a read" vs. "hf 14b read".
You can also request help:
"hf help", "data help", "hf 15 help" etc.
Indents are now space-based, not tab-based anymore. Hopefully
no one will be trolling about it, considering the suicide-prone work
being done here ;)
client/cmdhw.c, client/proxusb.c, client/cmdhw.h, client/proxusb.h,
client/cmdmain.c, client/cmdlfhid.c, client/cmdmain.h, client/cmdlfhid.h,
client/data.c, client/data.h, client/cmdhf.c, client/cmdlf.c,
client/cmdhf.h, client/cmdhf15.c, client/cmdhf14b.c, client/cmdlf.h,
client/cmdhf15.h, client/cmdhf14b.h, client/cmddata.c, client/cmddata.h,
client/ui.c, client/cmdparser.c, client/cmdlfti.c, client/ui.h,
client/cmdlfem4x.c, client/cmdparser.h, client/cmdlfti.h, client/cmdlfem4x.h,
client/graph.c, client/graph.h, client/cmdhf14a.c, client/cmdhf14a.h,
client/cmdhflegic.c, client/cmdhflegic.c: New files.
client/cli.c, client/flasher.c, client/snooper.c, client/proxmark3.c,
client/proxmark3.h, client/Makefile: Update accordingly.
client/flash.h, client/flash.c, client/proxgui.cpp: Cosmetic changes.
client/translate.h, client/command.c, client/gui.c,
client/usb.c, client/prox.h: Remove.
include/usb_cmd.h (CMD_ACQUIRE_RAW_ADC_SAMPLES_ISO_14443_SIM): Remove dead cmd.
common/crc16.h: New file.
common/crc16.c: Modify accordingly.
common/iso14443crc.h: New file.
common/iso14443_crc.c: Rename to
common/iso14443crc.c: and modify accordingly.
armsrc/lfops.c, armsrc/iso14443.c,
armsrc/iso14443a.c: include .h files from
the common directory instead of including the c files.
common/Makefile.common, armsrc/Makefile: Modify accordingly.
2010-02-04 09:27:07 +08:00
2019-04-13 00:41:14 +08:00
if ( WaitForResponseTimeout ( CMD_ACK , & resp , 1500 ) ) {
2019-04-18 05:44:48 +08:00
recv = resp . data . asBytes ;
int iLen = resp . oldarg [ 0 ] ;
2019-03-10 06:35:06 +08:00
2019-04-13 00:41:14 +08:00
if ( ! iLen ) {
PrintAndLogEx ( ERR , " No card response. " ) ;
return 1 ;
}
2019-03-10 06:35:06 +08:00
2019-04-13 00:41:14 +08:00
* dataoutlen = iLen - 2 ;
if ( * dataoutlen < 0 )
* dataoutlen = 0 ;
2019-03-10 06:35:06 +08:00
2019-04-13 00:41:14 +08:00
if ( maxdataoutlen & & * dataoutlen > maxdataoutlen ) {
PrintAndLogEx ( ERR , " Buffer too small(%d). Needs %d bytes " , * dataoutlen , maxdataoutlen ) ;
return 2 ;
2019-03-10 06:35:06 +08:00
}
2019-04-19 23:03:39 +08:00
if ( recv [ 0 ] ! = data [ 0 ] ) {
PrintAndLogEx ( ERR , " iso14443-4 framing error. Card send %2x must be %2x " , dataout [ 0 ] , data [ 0 ] ) ;
2019-04-13 00:41:14 +08:00
return 2 ;
}
2019-03-10 06:35:06 +08:00
2019-04-13 00:41:14 +08:00
memcpy ( dataout , & recv [ 2 ] , * dataoutlen ) ;
2019-03-10 06:35:06 +08:00
2019-04-13 00:41:14 +08:00
// CRC Check
if ( iLen = = - 1 ) {
PrintAndLogEx ( ERR , " ISO 14443A CRC error. " ) ;
return 3 ;
2019-03-10 06:35:06 +08:00
}
2019-04-13 00:41:14 +08:00
} else {
PrintAndLogEx ( ERR , " Reply timeout. " ) ;
return 4 ;
2019-03-10 06:35:06 +08:00
}
2019-04-13 00:41:14 +08:00
return 0 ;
2018-10-11 16:48:46 +08:00
}
2019-04-14 03:54:04 +08:00
static int SelectCard14443_4 ( bool disconnect , iso14a_card_select_t * card ) {
2019-04-18 18:43:35 +08:00
PacketResponseNG resp ;
2018-11-12 22:17:31 +08:00
2019-03-10 06:35:06 +08:00
frameLength = 0 ;
if ( card )
memset ( card , 0 , sizeof ( iso14a_card_select_t ) ) ;
DropField ( ) ;
// Anticollision + SELECT card
2019-05-08 01:51:33 +08:00
SendCommandMIX ( CMD_READER_ISO_14443a , ISO14A_CONNECT | ISO14A_NO_DISCONNECT , 0 , 0 , NULL , 0 ) ;
2019-03-10 06:35:06 +08:00
if ( ! WaitForResponseTimeout ( CMD_ACK , & resp , 1500 ) ) {
2019-04-17 02:00:25 +08:00
PrintAndLogEx ( ERR , " Proxmark3 connection timeout. " ) ;
2019-03-10 06:35:06 +08:00
return 1 ;
}
// check result
2019-04-18 05:44:48 +08:00
if ( resp . oldarg [ 0 ] = = 0 ) {
2019-03-10 06:35:06 +08:00
PrintAndLogEx ( ERR , " No card in field. " ) ;
return 1 ;
}
2019-04-18 05:44:48 +08:00
if ( resp . oldarg [ 0 ] ! = 1 & & resp . oldarg [ 0 ] ! = 2 ) {
PrintAndLogEx ( ERR , " Card not in iso14443-4. res=%d. " , resp . oldarg [ 0 ] ) ;
2019-03-10 06:35:06 +08:00
return 1 ;
}
2019-04-18 05:44:48 +08:00
if ( resp . oldarg [ 0 ] = = 2 ) { // 0: couldn't read, 1: OK, with ATS, 2: OK, no ATS, 3: proprietary Anticollision
2019-03-10 06:35:06 +08:00
// get ATS
uint8_t rats [ ] = { 0xE0 , 0x80 } ; // FSDI=8 (FSD=256), CID=0
2019-04-19 23:03:39 +08:00
SendCommandOLD ( CMD_READER_ISO_14443a , ISO14A_RAW | ISO14A_APPEND_CRC | ISO14A_NO_DISCONNECT , sizeof ( rats ) , 0 , rats , sizeof ( rats ) ) ;
2019-03-10 06:35:06 +08:00
if ( ! WaitForResponseTimeout ( CMD_ACK , & resp , 1500 ) ) {
2019-04-17 02:00:25 +08:00
PrintAndLogEx ( ERR , " Proxmark3 connection timeout. " ) ;
2019-03-10 06:35:06 +08:00
return 1 ;
}
2019-04-18 05:44:48 +08:00
if ( resp . oldarg [ 0 ] = = 0 ) { // ats_len
2019-03-10 06:35:06 +08:00
PrintAndLogEx ( ERR , " Can't get ATS. " ) ;
return 1 ;
}
// get frame length from ATS in data field
2019-04-18 05:44:48 +08:00
if ( resp . oldarg [ 0 ] > 1 ) {
uint8_t fsci = resp . data . asBytes [ 1 ] & 0x0f ;
2019-05-14 18:51:45 +08:00
if ( fsci < ARRAYLEN ( atsFSC ) )
2019-03-10 06:35:06 +08:00
frameLength = atsFSC [ fsci ] ;
}
} else {
// get frame length from ATS in card data structure
2019-04-18 05:44:48 +08:00
iso14a_card_select_t * vcard = ( iso14a_card_select_t * ) resp . data . asBytes ;
2019-03-10 06:35:06 +08:00
if ( vcard - > ats_len > 1 ) {
uint8_t fsci = vcard - > ats [ 1 ] & 0x0f ;
2019-05-14 18:51:45 +08:00
if ( fsci < ARRAYLEN ( atsFSC ) )
2019-03-10 06:35:06 +08:00
frameLength = atsFSC [ fsci ] ;
}
if ( card )
memcpy ( card , vcard , sizeof ( iso14a_card_select_t ) ) ;
}
if ( disconnect )
DropField ( ) ;
return 0 ;
2019-02-02 00:00:08 +08:00
}
2017-11-11 03:47:31 +08:00
2019-04-13 00:41:14 +08:00
static int CmdExchangeAPDU ( bool chainingin , uint8_t * datain , int datainlen , bool activateField , uint8_t * dataout , int maxdataoutlen , int * dataoutlen , bool * chainingout ) {
2019-03-10 06:35:06 +08:00
* chainingout = false ;
if ( activateField ) {
// select with no disconnect and set frameLength
int selres = SelectCard14443_4 ( false , NULL ) ;
if ( selres )
return selres ;
}
uint16_t cmdc = 0 ;
if ( chainingin )
cmdc = ISO14A_SEND_CHAINING ;
// "Command APDU" length should be 5+255+1, but javacard's APDU buffer might be smaller - 133 bytes
// https://stackoverflow.com/questions/32994936/safe-max-java-card-apdu-data-command-and-respond-size
2019-05-01 03:10:11 +08:00
// here length PM3_CMD_DATA_SIZE=512
2019-03-10 06:35:06 +08:00
// timeout must be authomatically set by "get ATS"
2019-03-28 21:19:41 +08:00
if ( datain )
2019-04-19 23:03:39 +08:00
SendCommandOLD ( CMD_READER_ISO_14443a , ISO14A_APDU | ISO14A_NO_DISCONNECT | cmdc , ( datainlen & 0xFFFF ) , 0 , datain , datainlen & 0xFFFF ) ;
else
2019-05-08 01:51:33 +08:00
SendCommandMIX ( CMD_READER_ISO_14443a , ISO14A_APDU | ISO14A_NO_DISCONNECT | cmdc , 0 , 0 , NULL , 0 ) ;
2019-03-09 15:59:13 +08:00
2019-04-18 18:43:35 +08:00
PacketResponseNG resp ;
2017-11-11 03:47:31 +08:00
if ( WaitForResponseTimeout ( CMD_ACK , & resp , 1500 ) ) {
2019-06-08 00:41:39 +08:00
uint8_t * recv = resp . data . asBytes ;
2019-04-18 05:44:48 +08:00
int iLen = resp . oldarg [ 0 ] ;
uint8_t res = resp . oldarg [ 1 ] ;
2019-03-09 15:59:13 +08:00
2019-03-10 06:35:06 +08:00
int dlen = iLen - 2 ;
if ( dlen < 0 )
dlen = 0 ;
* dataoutlen + = dlen ;
2019-03-09 15:59:13 +08:00
2019-03-10 06:35:06 +08:00
if ( maxdataoutlen & & * dataoutlen > maxdataoutlen ) {
PrintAndLogEx ( ERR , " APDU: Buffer too small(%d). Needs %d bytes " , * dataoutlen , maxdataoutlen ) ;
return 2 ;
}
2019-03-09 15:59:13 +08:00
2019-03-10 06:35:06 +08:00
// I-block ACK
if ( ( res & 0xf2 ) = = 0xa2 ) {
* dataoutlen = 0 ;
* chainingout = true ;
return 0 ;
}
2019-03-09 15:59:13 +08:00
2019-03-10 07:00:59 +08:00
if ( ! iLen ) {
2019-03-10 06:35:06 +08:00
PrintAndLogEx ( ERR , " APDU: No APDU response. " ) ;
2017-11-11 03:47:31 +08:00
return 1 ;
2019-03-10 06:35:06 +08:00
}
// check apdu length
if ( iLen < 2 & & iLen > = 0 ) {
PrintAndLogEx ( ERR , " APDU: Small APDU response. Len=%d " , iLen ) ;
return 2 ;
}
// check block TODO
if ( iLen = = - 2 ) {
PrintAndLogEx ( ERR , " APDU: Block type mismatch. " ) ;
return 2 ;
}
memcpy ( dataout , recv , dlen ) ;
// chaining
if ( ( res & 0x10 ) ! = 0 ) {
* chainingout = true ;
}
// CRC Check
if ( iLen = = - 1 ) {
PrintAndLogEx ( ERR , " APDU: ISO 14443A CRC error. " ) ;
return 3 ;
}
2017-11-11 03:47:31 +08:00
} else {
2018-11-12 22:17:31 +08:00
PrintAndLogEx ( ERR , " APDU: Reply timeout. " ) ;
2019-03-10 06:35:06 +08:00
return 4 ;
2017-11-11 03:47:31 +08:00
}
2018-11-12 22:17:31 +08:00
2019-03-10 06:35:06 +08:00
return 0 ;
2018-11-12 22:17:31 +08:00
}
2019-03-10 18:20:22 +08:00
int ExchangeAPDU14a ( uint8_t * datain , int datainlen , bool activateField , bool leaveSignalON , uint8_t * dataout , int maxdataoutlen , int * dataoutlen ) {
2019-03-10 06:35:06 +08:00
* dataoutlen = 0 ;
bool chaining = false ;
int res ;
// 3 byte here - 1b framing header, 2b crc16
if ( APDUInFramingEnable & &
2019-05-01 03:10:11 +08:00
( ( frameLength & & ( datainlen > frameLength - 3 ) ) | | ( datainlen > PM3_CMD_DATA_SIZE - 3 ) ) ) {
2019-03-10 06:35:06 +08:00
int clen = 0 ;
bool vActivateField = activateField ;
do {
int vlen = MIN ( frameLength - 3 , datainlen - clen ) ;
bool chainBlockNotLast = ( ( clen + vlen ) < datainlen ) ;
* dataoutlen = 0 ;
res = CmdExchangeAPDU ( chainBlockNotLast , & datain [ clen ] , vlen , vActivateField , dataout , maxdataoutlen , dataoutlen , & chaining ) ;
if ( res ) {
if ( ! leaveSignalON )
DropField ( ) ;
return 200 ;
}
// check R-block ACK
2019-06-12 21:41:23 +08:00
//TODO check this one...
if ( ( * dataoutlen = = 0 ) & & ( * dataoutlen ! = 0 | | chaining ! = chainBlockNotLast ) ) { // *dataoutlen!=0. 'A && (!A || B)' is equivalent to 'A && B'
2019-03-10 06:35:06 +08:00
if ( ! leaveSignalON )
DropField ( ) ;
return 201 ;
}
clen + = vlen ;
vActivateField = false ;
if ( * dataoutlen ) {
if ( clen ! = datainlen )
2019-07-14 06:35:18 +08:00
PrintAndLogEx ( ERR , " APDU: I-block/R-block sequence error. Data len=%d, Sent=%d, Last packet len=%d " , datainlen , clen , * dataoutlen ) ;
2019-03-10 06:35:06 +08:00
break ;
}
} while ( clen < datainlen ) ;
} else {
res = CmdExchangeAPDU ( false , datain , datainlen , activateField , dataout , maxdataoutlen , dataoutlen , & chaining ) ;
if ( res ) {
if ( ! leaveSignalON )
DropField ( ) ;
return res ;
}
}
while ( chaining ) {
// I-block with chaining
res = CmdExchangeAPDU ( false , NULL , 0 , false , & dataout [ * dataoutlen ] , maxdataoutlen , dataoutlen , & chaining ) ;
if ( res ) {
if ( ! leaveSignalON )
DropField ( ) ;
return 100 ;
}
}
if ( ! leaveSignalON )
DropField ( ) ;
return 0 ;
2017-11-11 03:47:31 +08:00
}
2018-11-20 22:25:19 +08:00
// ISO14443-4. 7. Half-duplex block transmission protocol
2019-04-13 00:41:14 +08:00
static int CmdHF14AAPDU ( const char * Cmd ) {
2019-05-01 03:10:11 +08:00
uint8_t data [ PM3_CMD_DATA_SIZE ] ;
2019-03-10 06:35:06 +08:00
int datalen = 0 ;
2019-07-14 20:14:54 +08:00
uint8_t header [ PM3_CMD_DATA_SIZE ] ;
int headerlen = 0 ;
2019-03-10 06:35:06 +08:00
bool activateField = false ;
bool leaveSignalON = false ;
bool decodeTLV = false ;
2019-07-14 19:59:59 +08:00
bool decodeAPDU = false ;
bool makeAPDU = false ;
bool extendedAPDU = false ;
int le = 0 ;
2019-03-10 06:35:06 +08:00
CLIParserInit ( " hf 14a apdu " ,
2019-07-14 19:59:59 +08:00
" Sends an ISO 7816-4 APDU via ISO 14443-4 block transmission protocol (T=CL). works with all apdu types from ISO 7816-4:2013 " ,
" Sample: \n \t hf 14a apdu -st 00A404000E325041592E5359532E444446303100 \n "
" \t hf 14a apdu -sd 00A404000E325041592E5359532E444446303100 - decode apdu \n "
2019-07-14 20:00:40 +08:00
" \t hf 14a apdu -sm 00A40400 325041592E5359532E4444463031 -l 256 - encode standard apdu \n "
" \t hf 14a apdu -sm 00A40400 325041592E5359532E4444463031 -el 65536 - encode extended apdu \n " ) ;
2019-03-10 06:35:06 +08:00
2019-03-10 07:00:59 +08:00
void * argtable [ ] = {
2019-03-10 06:35:06 +08:00
arg_param_begin ,
2019-07-14 19:59:59 +08:00
arg_lit0 ( " sS " , " select " , " activate field and select card " ) ,
arg_lit0 ( " kK " , " keep " , " leave the signal field ON after receive response " ) ,
arg_lit0 ( " tT " , " tlv " , " executes TLV decoder if it possible " ) ,
arg_lit0 ( " dD " , " decapdu " , " decode apdu request if it possible " ) ,
2019-07-15 22:26:42 +08:00
arg_str0 ( " mM " , " make " , " <head (CLA INS P1 P2) hex> " , " make apdu with head from this field and data from data field. Must be 4 bytes length: <CLA INS P1 P2> " ) ,
2019-07-14 19:59:59 +08:00
arg_lit0 ( " eE " , " extended " , " make extended length apdu if `m` parameter included " ) ,
2019-07-15 22:26:42 +08:00
arg_int0 ( " lL " , " le " , " <Le (int)> " , " Le apdu parameter if `m` parameter included " ) ,
2019-07-14 19:59:59 +08:00
arg_strx1 ( NULL , NULL , " <APDU (hex) | data (hex)> " , " data if `m` parameter included " ) ,
2019-03-10 06:35:06 +08:00
arg_param_end
} ;
2019-03-19 00:42:49 +08:00
CLIExecWithReturn ( Cmd , argtable , false ) ;
2019-03-10 06:35:06 +08:00
activateField = arg_get_lit ( 1 ) ;
leaveSignalON = arg_get_lit ( 2 ) ;
decodeTLV = arg_get_lit ( 3 ) ;
2019-07-14 19:59:59 +08:00
decodeAPDU = arg_get_lit ( 4 ) ;
2019-07-15 22:26:42 +08:00
CLIGetHexWithReturn ( 5 , header , & headerlen ) ;
makeAPDU = headerlen > 0 ;
if ( makeAPDU & & headerlen ! = 4 ) {
PrintAndLogEx ( ERR , " header length must be 4 bytes instead of %d " , headerlen ) ;
2019-07-16 00:12:01 +08:00
return 1 ;
2019-07-15 22:26:42 +08:00
}
2019-07-14 19:59:59 +08:00
extendedAPDU = arg_get_lit ( 6 ) ;
2019-07-15 22:26:42 +08:00
le = arg_get_int_def ( 7 , 0 ) ;
2019-07-16 00:12:01 +08:00
2019-07-14 19:59:59 +08:00
if ( makeAPDU ) {
2019-07-14 20:14:54 +08:00
uint8_t apdudata [ PM3_CMD_DATA_SIZE ] = { 0 } ;
int apdudatalen = 0 ;
2019-07-16 00:12:01 +08:00
2019-07-14 20:14:54 +08:00
CLIGetHexBLessWithReturn ( 8 , apdudata , & apdudatalen , 1 + 2 ) ;
APDUStruct apdu ;
apdu . cla = header [ 0 ] ;
apdu . ins = header [ 1 ] ;
apdu . p1 = header [ 2 ] ;
apdu . p2 = header [ 3 ] ;
2019-07-16 00:12:01 +08:00
2019-07-14 20:14:54 +08:00
apdu . lc = apdudatalen ;
apdu . data = apdudata ;
2019-07-16 00:12:01 +08:00
2019-07-14 20:14:54 +08:00
apdu . extended_apdu = extendedAPDU ;
apdu . le = le ;
2019-07-16 00:12:01 +08:00
2019-07-14 20:14:54 +08:00
if ( APDUEncode ( & apdu , data , & datalen ) ) {
PrintAndLogEx ( ERR , " can't make apdu with provided parameters. " ) ;
2019-07-16 00:12:01 +08:00
return 2 ;
2019-07-14 20:14:54 +08:00
}
2019-07-16 00:12:01 +08:00
} else {
2019-07-14 19:59:59 +08:00
if ( extendedAPDU ) {
PrintAndLogEx ( ERR , " make mode not set but here `e` option. " ) ;
2019-07-16 00:12:01 +08:00
return 3 ;
2019-07-14 19:59:59 +08:00
}
if ( le > 0 ) {
PrintAndLogEx ( ERR , " make mode not set but here `l` option. " ) ;
2019-07-16 00:12:01 +08:00
return 3 ;
2019-07-14 19:59:59 +08:00
}
2019-07-16 00:12:01 +08:00
2019-07-14 19:59:59 +08:00
// len = data + PCB(1b) + CRC(2b)
2019-07-14 20:14:54 +08:00
CLIGetHexBLessWithReturn ( 8 , data , & datalen , 1 + 2 ) ;
2019-07-14 19:59:59 +08:00
}
2017-11-11 03:47:31 +08:00
2019-03-10 07:00:59 +08:00
CLIParserFree ( ) ;
PrintAndLogEx ( NORMAL , " >>>>[%s%s%s] %s " , activateField ? " sel " : " " , leaveSignalON ? " keep " : " " , decodeTLV ? " TLV " : " " , sprint_hex ( data , datalen ) ) ;
2019-03-09 15:59:13 +08:00
2019-07-14 20:14:54 +08:00
if ( decodeAPDU ) {
2019-07-16 00:12:01 +08:00
APDUStruct apdu ;
2019-07-14 20:14:54 +08:00
if ( APDUDecode ( data , datalen , & apdu ) = = 0 )
APDUPrint ( apdu ) ;
else
2019-07-16 00:12:01 +08:00
PrintAndLogEx ( WARNING , " can't decode APDU. " ) ;
2019-07-14 20:14:54 +08:00
}
2019-05-01 03:10:11 +08:00
int res = ExchangeAPDU14a ( data , datalen , activateField , leaveSignalON , data , PM3_CMD_DATA_SIZE , & datalen ) ;
2017-11-11 03:47:31 +08:00
2019-03-10 06:35:06 +08:00
if ( res )
return res ;
2017-11-11 03:47:31 +08:00
2019-03-10 06:35:06 +08:00
PrintAndLogEx ( NORMAL , " <<<< %s " , sprint_hex ( data , datalen ) ) ;
2019-03-09 15:59:13 +08:00
2019-03-10 06:35:06 +08:00
PrintAndLogEx ( SUCCESS , " APDU response: %02x %02x - %s " , data [ datalen - 2 ] , data [ datalen - 1 ] , GetAPDUCodeDescription ( data [ datalen - 2 ] , data [ datalen - 1 ] ) ) ;
2017-11-11 03:47:31 +08:00
2019-03-10 06:35:06 +08:00
// TLV decoder
if ( decodeTLV & & datalen > 4 ) {
TLVPrintFromBuffer ( data , datalen - 2 ) ;
}
2019-03-09 15:59:13 +08:00
2019-03-10 06:35:06 +08:00
return 0 ;
2017-11-11 03:47:31 +08:00
}
2019-04-13 00:41:14 +08:00
static int CmdHF14ACmdRaw ( const char * Cmd ) {
2017-10-02 04:06:06 +08:00
bool reply = 1 ;
2017-06-27 03:45:22 +08:00
bool crc = false ;
bool power = false ;
bool active = false ;
bool active_select = false ;
2019-03-10 06:35:06 +08:00
bool no_rats = false ;
2017-10-02 04:06:06 +08:00
uint16_t numbits = 0 ;
2019-03-10 06:35:06 +08:00
bool bTimeout = false ;
uint32_t timeout = 0 ;
bool topazmode = false ;
2019-03-10 07:00:59 +08:00
char buf [ 5 ] = " " ;
2017-10-02 04:06:06 +08:00
int i = 0 ;
2019-05-01 03:10:11 +08:00
uint8_t data [ PM3_CMD_DATA_SIZE ] ;
2019-03-10 06:35:06 +08:00
uint16_t datalen = 0 ;
uint32_t temp ;
2013-09-29 03:28:55 +08:00
2019-03-19 00:42:49 +08:00
if ( strlen ( Cmd ) < 2 ) return usage_hf_14a_raw ( ) ;
2015-03-24 18:45:31 +08:00
2013-09-29 03:28:55 +08:00
// strip
2019-03-19 00:42:49 +08:00
while ( * Cmd = = ' ' | | * Cmd = = ' \t ' ) Cmd + + ;
2013-09-29 03:28:55 +08:00
2019-03-19 00:42:49 +08:00
while ( Cmd [ i ] ! = ' \0 ' ) {
if ( Cmd [ i ] = = ' ' | | Cmd [ i ] = = ' \t ' ) { i + + ; continue ; }
if ( Cmd [ i ] = = ' - ' ) {
switch ( Cmd [ i + 1 ] ) {
2019-03-10 06:35:06 +08:00
case ' H ' :
case ' h ' :
return usage_hf_14a_raw ( ) ;
2019-03-09 15:59:13 +08:00
case ' r ' :
2017-06-27 03:45:22 +08:00
reply = false ;
2013-09-29 03:28:55 +08:00
break ;
case ' c ' :
2017-06-27 03:45:22 +08:00
crc = true ;
2013-09-29 03:28:55 +08:00
break ;
case ' p ' :
2017-06-27 03:45:22 +08:00
power = true ;
2013-09-29 03:28:55 +08:00
break ;
case ' a ' :
2017-06-27 03:45:22 +08:00
active = true ;
2013-09-29 03:28:55 +08:00
break ;
case ' s ' :
2017-06-27 03:45:22 +08:00
active_select = true ;
2013-09-29 03:28:55 +08:00
break ;
2019-03-09 15:59:13 +08:00
case ' b ' :
2019-03-19 00:42:49 +08:00
sscanf ( Cmd + i + 2 , " %d " , & temp ) ;
2013-09-29 03:28:55 +08:00
numbits = temp & 0xFFFF ;
2019-03-10 07:00:59 +08:00
i + = 3 ;
2019-03-19 00:42:49 +08:00
while ( Cmd [ i ] ! = ' ' & & Cmd [ i ] ! = ' \0 ' ) { i + + ; }
2019-03-10 07:00:59 +08:00
i - = 2 ;
2013-09-29 03:28:55 +08:00
break ;
2019-03-10 06:35:06 +08:00
case ' t ' :
bTimeout = true ;
2019-03-19 00:42:49 +08:00
sscanf ( Cmd + i + 2 , " %d " , & temp ) ;
2019-03-10 06:35:06 +08:00
timeout = temp ;
2019-03-10 07:00:59 +08:00
i + = 3 ;
2019-03-19 00:42:49 +08:00
while ( Cmd [ i ] ! = ' ' & & Cmd [ i ] ! = ' \0 ' ) { i + + ; }
2019-03-10 07:00:59 +08:00
i - = 2 ;
2019-03-10 06:35:06 +08:00
break ;
2015-03-24 18:45:31 +08:00
case ' T ' :
2019-03-10 06:35:06 +08:00
topazmode = true ;
break ;
case ' 3 ' :
no_rats = true ;
break ;
2013-09-29 03:28:55 +08:00
default :
2015-11-10 18:45:45 +08:00
return usage_hf_14a_raw ( ) ;
2013-09-29 03:28:55 +08:00
}
2017-10-02 04:06:06 +08:00
i + = 2 ;
2013-09-29 03:28:55 +08:00
continue ;
}
2019-03-19 00:42:49 +08:00
if ( ( Cmd [ i ] > = ' 0 ' & & Cmd [ i ] < = ' 9 ' ) | |
( Cmd [ i ] > = ' a ' & & Cmd [ i ] < = ' f ' ) | |
( Cmd [ i ] > = ' A ' & & Cmd [ i ] < = ' F ' ) ) {
2019-03-10 07:00:59 +08:00
buf [ strlen ( buf ) + 1 ] = 0 ;
2019-03-19 00:42:49 +08:00
buf [ strlen ( buf ) ] = Cmd [ i ] ;
2013-09-29 03:28:55 +08:00
i + + ;
2018-07-09 17:22:51 +08:00
if ( strlen ( buf ) > = 2 ) {
sscanf ( buf , " %x " , & temp ) ;
data [ datalen ] = ( uint8_t ) ( temp & 0xff ) ;
* buf = 0 ;
2019-03-10 07:00:59 +08:00
if ( + + datalen > = sizeof ( data ) ) {
2019-03-10 06:35:06 +08:00
if ( crc )
PrintAndLogEx ( NORMAL , " Buffer is full, we can't add CRC to your data " ) ;
break ;
}
2013-09-29 03:28:55 +08:00
}
continue ;
}
2018-02-21 14:19:44 +08:00
PrintAndLogEx ( NORMAL , " Invalid char on input " ) ;
2013-09-29 03:28:55 +08:00
return 0 ;
}
2015-03-24 18:45:31 +08:00
2019-03-10 07:00:59 +08:00
if ( crc & & datalen > 0 & & datalen < sizeof ( data ) - 2 ) {
2013-09-29 03:28:55 +08:00
uint8_t first , second ;
2019-03-10 06:35:06 +08:00
if ( topazmode ) {
compute_crc ( CRC_14443_B , data , datalen , & first , & second ) ;
} else {
compute_crc ( CRC_14443_A , data , datalen , & first , & second ) ;
}
2013-09-29 03:28:55 +08:00
data [ datalen + + ] = first ;
data [ datalen + + ] = second ;
}
2019-04-19 23:03:39 +08:00
uint16_t flags = 0 ;
2017-10-02 04:06:06 +08:00
if ( active | | active_select ) {
2019-04-19 23:03:39 +08:00
flags | = ISO14A_CONNECT ;
2018-02-08 19:35:59 +08:00
if ( active )
2019-04-19 23:03:39 +08:00
flags | = ISO14A_NO_SELECT ;
2013-09-29 03:28:55 +08:00
}
2015-03-12 03:17:24 +08:00
2019-04-19 23:03:39 +08:00
uint32_t argtimeout = 0 ;
2019-03-10 07:00:59 +08:00
if ( bTimeout ) {
# define MAX_TIMEOUT 40542464 // = (2^32-1) * (8*16) / 13560000Hz * 1000ms/s
2019-04-19 23:03:39 +08:00
flags | = ISO14A_SET_TIMEOUT ;
2019-03-10 07:00:59 +08:00
if ( timeout > MAX_TIMEOUT ) {
2015-02-12 01:30:36 +08:00
timeout = MAX_TIMEOUT ;
2018-02-21 14:19:44 +08:00
PrintAndLogEx ( NORMAL , " Set timeout to 40542 seconds (11.26 hours). The max we can wait for response " ) ;
2015-01-08 06:23:17 +08:00
}
2019-04-19 23:03:39 +08:00
argtimeout = 13560000 / 1000 / ( 8 * 16 ) * timeout ; // timeout in ETUs (time to transfer 1 bit, approx. 9.4 us)
2019-03-10 06:35:06 +08:00
}
2015-03-24 18:45:31 +08:00
2017-10-02 04:06:06 +08:00
if ( power ) {
2019-04-19 23:03:39 +08:00
flags | = ISO14A_NO_DISCONNECT ;
2019-03-10 06:35:06 +08:00
}
2019-03-09 15:59:13 +08:00
2018-02-08 19:35:59 +08:00
if ( datalen > 0 ) {
2019-04-19 23:03:39 +08:00
flags | = ISO14A_RAW ;
2019-03-10 06:35:06 +08:00
}
2019-03-09 15:59:13 +08:00
2019-03-10 06:35:06 +08:00
if ( topazmode ) {
2019-04-19 23:03:39 +08:00
flags | = ISO14A_TOPAZMODE ;
2019-03-10 06:35:06 +08:00
}
if ( no_rats ) {
2019-04-19 23:03:39 +08:00
flags | = ISO14A_NO_RATS ;
2019-03-10 06:35:06 +08:00
}
2019-03-09 15:59:13 +08:00
2019-05-01 03:10:11 +08:00
// Max buffer is PM3_CMD_DATA_SIZE
datalen = ( datalen > PM3_CMD_DATA_SIZE ) ? PM3_CMD_DATA_SIZE : datalen ;
2019-03-09 15:59:13 +08:00
2019-03-10 06:35:06 +08:00
clearCommandBuffer ( ) ;
2019-04-19 23:03:39 +08:00
SendCommandOLD ( CMD_READER_ISO_14443a , flags , ( datalen & 0xFFFF ) | ( ( uint32_t ) ( numbits < < 16 ) ) , argtimeout , data , datalen & 0xFFFF ) ;
2013-09-29 03:28:55 +08:00
if ( reply ) {
2019-03-10 06:35:06 +08:00
int res = 0 ;
2017-10-02 04:06:06 +08:00
if ( active_select )
2019-03-10 06:35:06 +08:00
res = waitCmd ( 1 ) ;
if ( ! res & & datalen > 0 )
2013-09-29 03:28:55 +08:00
waitCmd ( 0 ) ;
2017-10-02 04:06:06 +08:00
}
2013-09-29 03:28:55 +08:00
return 0 ;
}
2019-03-10 18:20:22 +08:00
static int waitCmd ( uint8_t iSelect ) {
2019-04-18 18:43:35 +08:00
PacketResponseNG resp ;
2013-09-29 03:28:55 +08:00
2019-03-09 15:59:13 +08:00
if ( WaitForResponseTimeout ( CMD_ACK , & resp , 1500 ) ) {
2019-04-18 05:44:48 +08:00
uint16_t len = ( resp . oldarg [ 0 ] & 0xFFFF ) ;
2019-03-10 07:00:59 +08:00
if ( iSelect ) {
2019-04-18 05:44:48 +08:00
len = ( resp . oldarg [ 1 ] & 0xFFFF ) ;
2019-03-10 07:00:59 +08:00
if ( len ) {
2019-03-10 06:35:06 +08:00
PrintAndLogEx ( NORMAL , " Card selected. UID[%i]: " , len ) ;
} else {
PrintAndLogEx ( WARNING , " Can't select card. " ) ;
}
} else {
PrintAndLogEx ( NORMAL , " received %i bytes " , len ) ;
}
2019-03-09 15:59:13 +08:00
2017-10-30 03:07:45 +08:00
if ( ! len )
2017-11-11 03:47:31 +08:00
return 1 ;
2019-03-09 15:59:13 +08:00
2019-04-18 05:44:48 +08:00
PrintAndLogEx ( NORMAL , " %s " , sprint_hex ( resp . data . asBytes , len ) ) ;
2013-09-29 03:28:55 +08:00
} else {
2018-04-27 17:22:30 +08:00
PrintAndLogEx ( WARNING , " timeout while waiting for reply. " ) ;
2019-03-10 06:35:06 +08:00
return 3 ;
2013-09-29 03:28:55 +08:00
}
2019-03-10 06:35:06 +08:00
return 0 ;
2013-09-29 03:28:55 +08:00
}
2019-04-13 00:41:14 +08:00
static int CmdHF14AAntiFuzz ( const char * Cmd ) {
2019-03-09 15:59:13 +08:00
2019-03-10 06:35:06 +08:00
CLIParserInit ( " hf 14a antifuzz " ,
2019-03-10 07:00:59 +08:00
" Tries to fuzz the ISO14443a anticollision phase " ,
" Usage: \n "
" \t hf 14a antifuzz -4 \n " ) ;
2019-03-10 06:35:06 +08:00
2019-03-10 07:00:59 +08:00
void * argtable [ ] = {
2019-03-10 06:35:06 +08:00
arg_param_begin ,
arg_lit0 ( " 4 " , NULL , " 4 byte uid " ) ,
arg_lit0 ( " 7 " , NULL , " 7 byte uid " ) ,
arg_lit0 ( NULL , " 10 " , " 10 byte uid " ) ,
arg_param_end
} ;
2019-03-19 00:42:49 +08:00
CLIExecWithReturn ( Cmd , argtable , false ) ;
2019-03-10 06:35:06 +08:00
uint8_t arg0 = FLAG_4B_UID_IN_DATA ;
if ( arg_get_lit ( 2 ) )
arg0 = FLAG_7B_UID_IN_DATA ;
if ( arg_get_lit ( 3 ) )
arg0 = FLAG_10B_UID_IN_DATA ;
CLIParserFree ( ) ;
clearCommandBuffer ( ) ;
2019-05-08 01:13:14 +08:00
SendCommandMIX ( CMD_ANTIFUZZ_ISO_14443a , arg0 , 0 , 0 , NULL , 0 ) ;
2019-03-10 06:35:06 +08:00
return 0 ;
2018-02-28 20:21:47 +08:00
}
2019-04-13 00:41:14 +08:00
static int CmdHF14AChaining ( const char * Cmd ) {
2019-03-09 15:59:13 +08:00
2019-03-10 06:35:06 +08:00
CLIParserInit ( " hf 14a chaining " ,
2019-03-10 07:00:59 +08:00
" Enable/Disable ISO14443a input chaining. Maximum input length goes from ATS. " ,
" Usage: \n "
" \t hf 14a chaining disable -> disable chaining \n "
" \t hf 14a chaining -> show chaining enable/disable state \n " ) ;
2019-02-02 00:51:53 +08:00
2019-03-10 07:00:59 +08:00
void * argtable [ ] = {
2019-03-10 06:35:06 +08:00
arg_param_begin ,
arg_str0 ( NULL , NULL , " <enable/disable or 0/1> " , NULL ) ,
arg_param_end
} ;
2019-03-19 00:42:49 +08:00
CLIExecWithReturn ( Cmd , argtable , true ) ;
2019-02-02 00:51:53 +08:00
2019-03-10 06:35:06 +08:00
struct arg_str * str = arg_get_str ( 1 ) ;
int len = arg_get_str_len ( 1 ) ;
2019-03-09 15:59:13 +08:00
2019-03-10 06:35:06 +08:00
if ( len & & ( ! strcmp ( str - > sval [ 0 ] , " enable " ) | | ! strcmp ( str - > sval [ 0 ] , " 1 " ) ) )
APDUInFramingEnable = true ;
2019-03-09 15:59:13 +08:00
2019-03-10 06:35:06 +08:00
if ( len & & ( ! strcmp ( str - > sval [ 0 ] , " disable " ) | | ! strcmp ( str - > sval [ 0 ] , " 0 " ) ) )
APDUInFramingEnable = false ;
2019-02-02 00:51:53 +08:00
2019-03-10 06:35:06 +08:00
CLIParserFree ( ) ;
2019-02-02 00:51:53 +08:00
2019-03-10 06:35:06 +08:00
PrintAndLogEx ( INFO , " \n ISO 14443-4 input chaining %s. \n " , APDUInFramingEnable ? " enabled " : " disabled " ) ;
2019-03-09 15:59:13 +08:00
2019-03-10 06:35:06 +08:00
return 0 ;
2019-02-02 00:51:53 +08:00
}
2016-08-05 03:54:11 +08:00
static command_t CommandTable [ ] = {
2019-05-02 02:48:15 +08:00
{ " help " , CmdHelp , AlwaysAvailable , " This help " } ,
2019-05-02 16:42:02 +08:00
{ " list " , CmdHF14AList , AlwaysAvailable , " List ISO 14443-a history " } ,
2019-05-02 05:38:57 +08:00
{ " info " , CmdHF14AInfo , IfPm3Iso14443a , " Tag information " } ,
{ " reader " , CmdHF14AReader , IfPm3Iso14443a , " Act like an ISO14443-a reader " } ,
{ " cuids " , CmdHF14ACUIDs , IfPm3Iso14443a , " <n> Collect n>0 ISO14443-a UIDs in one go " } ,
{ " sim " , CmdHF14ASim , IfPm3Iso14443a , " <UID> -- Simulate ISO 14443-a tag " } ,
{ " sniff " , CmdHF14ASniff , IfPm3Iso14443a , " sniff ISO 14443-a traffic " } ,
{ " apdu " , CmdHF14AAPDU , IfPm3Iso14443a , " Send ISO 14443-4 APDU to tag " } ,
{ " chaining " , CmdHF14AChaining , IfPm3Iso14443a , " Control ISO 14443-4 input chaining " } ,
{ " raw " , CmdHF14ACmdRaw , IfPm3Iso14443a , " Send raw hex data to tag " } ,
{ " antifuzz " , CmdHF14AAntiFuzz , IfPm3Iso14443a , " Fuzzing the anticollision phase. Warning! Readers may react strange " } ,
2019-05-02 02:48:15 +08:00
{ NULL , NULL , NULL , NULL }
Client cleanup and restructuring. Stage 1...
Next Step is refactoring some of the giant functions which are
just copy/paste of some other ones with just a few line changes,
removing unnecessary 'goto' etc.
The MS Windows version is broken with this commit but will be fixed
soon. Everything can't be done all at once :P
The commands are now hierarchical, for example:
"hf 14a read" vs. "hf 14b read".
You can also request help:
"hf help", "data help", "hf 15 help" etc.
Indents are now space-based, not tab-based anymore. Hopefully
no one will be trolling about it, considering the suicide-prone work
being done here ;)
client/cmdhw.c, client/proxusb.c, client/cmdhw.h, client/proxusb.h,
client/cmdmain.c, client/cmdlfhid.c, client/cmdmain.h, client/cmdlfhid.h,
client/data.c, client/data.h, client/cmdhf.c, client/cmdlf.c,
client/cmdhf.h, client/cmdhf15.c, client/cmdhf14b.c, client/cmdlf.h,
client/cmdhf15.h, client/cmdhf14b.h, client/cmddata.c, client/cmddata.h,
client/ui.c, client/cmdparser.c, client/cmdlfti.c, client/ui.h,
client/cmdlfem4x.c, client/cmdparser.h, client/cmdlfti.h, client/cmdlfem4x.h,
client/graph.c, client/graph.h, client/cmdhf14a.c, client/cmdhf14a.h,
client/cmdhflegic.c, client/cmdhflegic.c: New files.
client/cli.c, client/flasher.c, client/snooper.c, client/proxmark3.c,
client/proxmark3.h, client/Makefile: Update accordingly.
client/flash.h, client/flash.c, client/proxgui.cpp: Cosmetic changes.
client/translate.h, client/command.c, client/gui.c,
client/usb.c, client/prox.h: Remove.
include/usb_cmd.h (CMD_ACQUIRE_RAW_ADC_SAMPLES_ISO_14443_SIM): Remove dead cmd.
common/crc16.h: New file.
common/crc16.c: Modify accordingly.
common/iso14443crc.h: New file.
common/iso14443_crc.c: Rename to
common/iso14443crc.c: and modify accordingly.
armsrc/lfops.c, armsrc/iso14443.c,
armsrc/iso14443a.c: include .h files from
the common directory instead of including the c files.
common/Makefile.common, armsrc/Makefile: Modify accordingly.
2010-02-04 09:27:07 +08:00
} ;
2019-04-13 00:41:14 +08:00
static int CmdHelp ( const char * Cmd ) {
2019-04-14 04:07:58 +08:00
( void ) Cmd ; // Cmd is not used so far
2019-04-13 00:41:14 +08:00
CmdsHelp ( CommandTable ) ;
return 0 ;
}
2019-03-10 18:20:22 +08:00
int CmdHF14A ( const char * Cmd ) {
2019-03-10 06:35:06 +08:00
clearCommandBuffer ( ) ;
2019-04-19 06:47:51 +08:00
return CmdsParse ( CommandTable , Cmd ) ;
Client cleanup and restructuring. Stage 1...
Next Step is refactoring some of the giant functions which are
just copy/paste of some other ones with just a few line changes,
removing unnecessary 'goto' etc.
The MS Windows version is broken with this commit but will be fixed
soon. Everything can't be done all at once :P
The commands are now hierarchical, for example:
"hf 14a read" vs. "hf 14b read".
You can also request help:
"hf help", "data help", "hf 15 help" etc.
Indents are now space-based, not tab-based anymore. Hopefully
no one will be trolling about it, considering the suicide-prone work
being done here ;)
client/cmdhw.c, client/proxusb.c, client/cmdhw.h, client/proxusb.h,
client/cmdmain.c, client/cmdlfhid.c, client/cmdmain.h, client/cmdlfhid.h,
client/data.c, client/data.h, client/cmdhf.c, client/cmdlf.c,
client/cmdhf.h, client/cmdhf15.c, client/cmdhf14b.c, client/cmdlf.h,
client/cmdhf15.h, client/cmdhf14b.h, client/cmddata.c, client/cmddata.h,
client/ui.c, client/cmdparser.c, client/cmdlfti.c, client/ui.h,
client/cmdlfem4x.c, client/cmdparser.h, client/cmdlfti.h, client/cmdlfem4x.h,
client/graph.c, client/graph.h, client/cmdhf14a.c, client/cmdhf14a.h,
client/cmdhflegic.c, client/cmdhflegic.c: New files.
client/cli.c, client/flasher.c, client/snooper.c, client/proxmark3.c,
client/proxmark3.h, client/Makefile: Update accordingly.
client/flash.h, client/flash.c, client/proxgui.cpp: Cosmetic changes.
client/translate.h, client/command.c, client/gui.c,
client/usb.c, client/prox.h: Remove.
include/usb_cmd.h (CMD_ACQUIRE_RAW_ADC_SAMPLES_ISO_14443_SIM): Remove dead cmd.
common/crc16.h: New file.
common/crc16.c: Modify accordingly.
common/iso14443crc.h: New file.
common/iso14443_crc.c: Rename to
common/iso14443crc.c: and modify accordingly.
armsrc/lfops.c, armsrc/iso14443.c,
armsrc/iso14443a.c: include .h files from
the common directory instead of including the c files.
common/Makefile.common, armsrc/Makefile: Modify accordingly.
2010-02-04 09:27:07 +08:00
}
2019-04-13 00:41:14 +08:00
int infoHF14A ( bool verbose , bool do_nack_test ) {
clearCommandBuffer ( ) ;
2019-05-08 01:51:33 +08:00
SendCommandMIX ( CMD_READER_ISO_14443a , ISO14A_CONNECT | ISO14A_NO_DISCONNECT , 0 , 0 , NULL , 0 ) ;
2019-04-18 18:43:35 +08:00
PacketResponseNG resp ;
2019-04-13 00:41:14 +08:00
if ( ! WaitForResponseTimeout ( CMD_ACK , & resp , 2500 ) ) {
if ( verbose ) PrintAndLogEx ( WARNING , " iso14443a card select failed " ) ;
DropField ( ) ;
return 0 ;
}
iso14a_card_select_t card ;
2019-04-18 05:44:48 +08:00
memcpy ( & card , ( iso14a_card_select_t * ) resp . data . asBytes , sizeof ( iso14a_card_select_t ) ) ;
2019-04-13 00:41:14 +08:00
/*
0 : couldn ' t read
1 : OK , with ATS
2 : OK , no ATS
3 : proprietary Anticollision
*/
2019-04-18 05:44:48 +08:00
uint64_t select_status = resp . oldarg [ 0 ] ;
2019-04-13 00:41:14 +08:00
if ( select_status = = 0 ) {
if ( verbose ) PrintAndLogEx ( WARNING , " iso14443a card select failed " ) ;
DropField ( ) ;
return select_status ;
}
if ( select_status = = 3 ) {
PrintAndLogEx ( NORMAL , " Card doesn't support standard iso14443-3 anticollision " ) ;
PrintAndLogEx ( NORMAL , " ATQA : %02x %02x " , card . atqa [ 1 ] , card . atqa [ 0 ] ) ;
DropField ( ) ;
return select_status ;
}
PrintAndLogEx ( NORMAL , " UID : %s " , sprint_hex ( card . uid , card . uidlen ) ) ;
PrintAndLogEx ( NORMAL , " ATQA : %02x %02x " , card . atqa [ 1 ] , card . atqa [ 0 ] ) ;
2019-04-18 05:44:48 +08:00
PrintAndLogEx ( NORMAL , " SAK : %02x [% " PRIu64 " ] " , card . sak , resp . oldarg [ 0 ] ) ;
2019-04-13 00:41:14 +08:00
bool isMifareClassic = true ;
switch ( card . sak ) {
case 0x00 :
isMifareClassic = false ;
// ******** is card of the MFU type (UL/ULC/NTAG/ etc etc)
DropField ( ) ;
uint32_t tagT = GetHF14AMfU_Type ( ) ;
if ( tagT ! = UL_ERROR )
ul_print_type ( tagT , 0 ) ;
else
PrintAndLogEx ( NORMAL , " TYPE: Possible AZTEK (iso14443a compliant) " ) ;
// reconnect for further tests
clearCommandBuffer ( ) ;
2019-05-08 01:51:33 +08:00
SendCommandMIX ( CMD_READER_ISO_14443a , ISO14A_CONNECT | ISO14A_NO_DISCONNECT , 0 , 0 , NULL , 0 ) ;
2019-04-13 00:41:14 +08:00
WaitForResponse ( CMD_ACK , & resp ) ;
2019-04-18 05:44:48 +08:00
memcpy ( & card , ( iso14a_card_select_t * ) resp . data . asBytes , sizeof ( iso14a_card_select_t ) ) ;
2019-04-13 00:41:14 +08:00
2019-04-18 05:44:48 +08:00
select_status = resp . oldarg [ 0 ] ; // 0: couldn't read, 1: OK, with ATS, 2: OK, no ATS
2019-04-13 00:41:14 +08:00
if ( select_status = = 0 ) {
DropField ( ) ;
return select_status ;
}
break ;
case 0x01 :
PrintAndLogEx ( NORMAL , " TYPE : NXP TNP3xxx Activision Game Appliance " ) ;
break ;
case 0x04 :
PrintAndLogEx ( NORMAL , " TYPE : NXP MIFARE (various !DESFire !DESFire EV1) " ) ;
isMifareClassic = false ;
break ;
case 0x08 :
PrintAndLogEx ( NORMAL , " TYPE : NXP MIFARE CLASSIC 1k | Plus 2k SL1 | 1k Ev1 " ) ;
break ;
case 0x09 :
PrintAndLogEx ( NORMAL , " TYPE : NXP MIFARE Mini 0.3k " ) ;
break ;
case 0x0A :
PrintAndLogEx ( NORMAL , " TYPE : FM11RF005SH (Shanghai Metro) " ) ;
break ;
case 0x10 :
PrintAndLogEx ( NORMAL , " TYPE : NXP MIFARE Plus 2k SL2 " ) ;
break ;
case 0x11 :
PrintAndLogEx ( NORMAL , " TYPE : NXP MIFARE Plus 4k SL2 " ) ;
break ;
case 0x18 :
PrintAndLogEx ( NORMAL , " TYPE : NXP MIFARE Classic 4k | Plus 4k SL1 | 4k Ev1 " ) ;
break ;
case 0x20 :
PrintAndLogEx ( NORMAL , " TYPE : NXP MIFARE DESFire 4k | DESFire EV1 2k/4k/8k | Plus 2k/4k SL3 | JCOP 31/41 " ) ;
isMifareClassic = false ;
break ;
case 0x24 :
PrintAndLogEx ( NORMAL , " TYPE : NXP MIFARE DESFire | DESFire EV1 " ) ;
isMifareClassic = false ;
break ;
case 0x28 :
PrintAndLogEx ( NORMAL , " TYPE : JCOP31 or JCOP41 v2.3.1 " ) ;
break ;
case 0x38 :
PrintAndLogEx ( NORMAL , " TYPE : Nokia 6212 or 6131 MIFARE CLASSIC 4K " ) ;
break ;
case 0x88 :
PrintAndLogEx ( NORMAL , " TYPE : Infineon MIFARE CLASSIC 1K " ) ;
break ;
case 0x98 :
PrintAndLogEx ( NORMAL , " TYPE : Gemplus MPCOS " ) ;
break ;
default :
;
}
// Double & triple sized UID, can be mapped to a manufacturer.
if ( card . uidlen > 4 ) {
PrintAndLogEx ( NORMAL , " MANUFACTURER : %s " , getTagInfo ( card . uid [ 0 ] ) ) ;
}
// try to request ATS even if tag claims not to support it
if ( select_status = = 2 ) {
uint8_t rats [ ] = { 0xE0 , 0x80 } ; // FSDI=8 (FSD=256), CID=0
clearCommandBuffer ( ) ;
2019-04-19 23:03:39 +08:00
SendCommandOLD ( CMD_READER_ISO_14443a , ISO14A_RAW | ISO14A_APPEND_CRC | ISO14A_NO_DISCONNECT , 2 , 0 , rats , sizeof ( rats ) ) ;
2019-04-13 00:41:14 +08:00
WaitForResponse ( CMD_ACK , & resp ) ;
2019-04-18 05:44:48 +08:00
memcpy ( card . ats , resp . data . asBytes , resp . oldarg [ 0 ] ) ;
card . ats_len = resp . oldarg [ 0 ] ; // note: ats_len includes CRC Bytes
2019-04-13 00:41:14 +08:00
}
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 ;
if ( select_status = = 2 ) {
PrintAndLogEx ( NORMAL , " SAK incorrectly claims that card doesn't support RATS " ) ;
}
PrintAndLogEx ( NORMAL , " ATS : %s " , sprint_hex ( card . ats , card . ats_len ) ) ;
PrintAndLogEx ( NORMAL , " - TL : length is %d bytes " , card . ats [ 0 ] ) ;
if ( card . ats [ 0 ] ! = card . ats_len - 2 ) {
PrintAndLogEx ( NORMAL , " ATS may be corrupted. Length of ATS (%d bytes incl. 2 Bytes CRC) doesn't match TL " , card . ats_len ) ;
}
if ( card . ats [ 0 ] > 1 ) { // there is a format byte (T0)
ta1 = ( card . ats [ 1 ] & 0x10 ) = = 0x10 ;
tb1 = ( card . ats [ 1 ] & 0x20 ) = = 0x20 ;
tc1 = ( card . ats [ 1 ] & 0x40 ) = = 0x40 ;
int16_t fsci = card . ats [ 1 ] & 0x0f ;
PrintAndLogEx ( NORMAL , " - T0 : TA1 is%s present, TB1 is%s present, "
" TC1 is%s present, FSCI is %d (FSC = %ld) " ,
( ta1 ? " " : " NOT " ) ,
( tb1 ? " " : " NOT " ) ,
( tc1 ? " " : " NOT " ) ,
fsci ,
2019-05-14 18:51:45 +08:00
fsci < ARRAYLEN ( atsFSC ) ? atsFSC [ fsci ] : - 1
2019-04-13 00:41:14 +08:00
) ;
}
pos = 2 ;
if ( ta1 ) {
char dr [ 16 ] , ds [ 16 ] ;
dr [ 0 ] = ds [ 0 ] = ' \0 ' ;
if ( card . ats [ pos ] & 0x10 ) strcat ( ds , " 2, " ) ;
if ( card . ats [ pos ] & 0x20 ) strcat ( ds , " 4, " ) ;
if ( card . ats [ pos ] & 0x40 ) strcat ( ds , " 8, " ) ;
if ( card . ats [ pos ] & 0x01 ) strcat ( dr , " 2, " ) ;
if ( card . ats [ pos ] & 0x02 ) strcat ( dr , " 4, " ) ;
if ( card . ats [ pos ] & 0x04 ) strcat ( dr , " 8, " ) ;
if ( strlen ( ds ) ! = 0 ) ds [ strlen ( ds ) - 2 ] = ' \0 ' ;
if ( strlen ( dr ) ! = 0 ) dr [ strlen ( dr ) - 2 ] = ' \0 ' ;
PrintAndLogEx ( NORMAL , " - TA1 : different divisors are%s supported, "
" DR: [%s], DS: [%s] " ,
( ( card . ats [ pos ] & 0x80 ) ? " NOT " : " " ) ,
dr ,
ds
) ;
pos + + ;
}
if ( tb1 ) {
uint32_t sfgi = card . ats [ pos ] & 0x0F ;
uint32_t fwi = card . ats [ pos ] > > 4 ;
PrintAndLogEx ( NORMAL , " - TB1 : SFGI = %d (SFGT = %s%ld/fc), FWI = %d (FWT = %ld/fc) " ,
( sfgi ) ,
sfgi ? " " : " (not needed) " ,
sfgi ? ( 1 < < 12 ) < < sfgi : 0 ,
fwi ,
( 1 < < 12 ) < < fwi
) ;
pos + + ;
}
if ( tc1 ) {
PrintAndLogEx ( NORMAL , " - TC1 : NAD is%s supported, CID is%s supported " ,
( card . ats [ pos ] & 0x01 ) ? " " : " NOT " ,
( card . ats [ pos ] & 0x02 ) ? " " : " NOT " ) ;
pos + + ;
}
if ( card . ats [ 0 ] > pos & & card . ats [ 0 ] < card . ats_len - 2 ) {
const char * tip = " " ;
if ( card . ats [ 0 ] - pos > = 7 ) {
if ( memcmp ( card . ats + pos , " \xC1 \x05 \x2F \x2F \x01 \xBC \xD6 " , 7 ) = = 0 ) {
tip = " -> MIFARE Plus X 2K or 4K " ;
} else if ( memcmp ( card . ats + pos , " \xC1 \x05 \x2F \x2F \x00 \x35 \xC7 " , 7 ) = = 0 ) {
tip = " -> MIFARE Plus S 2K or 4K " ;
}
}
PrintAndLogEx ( NORMAL , " - HB : %s%s " , sprint_hex ( card . ats + pos , card . ats [ 0 ] - pos ) , tip ) ;
if ( card . ats [ pos ] = = 0xC1 ) {
PrintAndLogEx ( NORMAL , " c1 -> Mifare or (multiple) virtual cards of various type " ) ;
PrintAndLogEx ( NORMAL , " %02x -> Length is %d bytes " , card . ats [ pos + 1 ] , card . ats [ pos + 1 ] ) ;
switch ( card . ats [ pos + 2 ] & 0xf0 ) {
case 0x10 :
PrintAndLogEx ( NORMAL , " 1x -> MIFARE DESFire " ) ;
break ;
case 0x20 :
PrintAndLogEx ( NORMAL , " 2x -> MIFARE Plus " ) ;
break ;
}
switch ( card . ats [ pos + 2 ] & 0x0f ) {
case 0x00 :
PrintAndLogEx ( NORMAL , " x0 -> <1 kByte " ) ;
break ;
case 0x01 :
PrintAndLogEx ( NORMAL , " x1 -> 1 kByte " ) ;
break ;
case 0x02 :
PrintAndLogEx ( NORMAL , " x2 -> 2 kByte " ) ;
break ;
case 0x03 :
PrintAndLogEx ( NORMAL , " x3 -> 4 kByte " ) ;
break ;
case 0x04 :
PrintAndLogEx ( NORMAL , " x4 -> 8 kByte " ) ;
break ;
}
switch ( card . ats [ pos + 3 ] & 0xf0 ) {
case 0x00 :
PrintAndLogEx ( NORMAL , " 0x -> Engineering sample " ) ;
break ;
case 0x20 :
PrintAndLogEx ( NORMAL , " 2x -> Released " ) ;
break ;
}
switch ( card . ats [ pos + 3 ] & 0x0f ) {
case 0x00 :
PrintAndLogEx ( NORMAL , " x0 -> Generation 1 " ) ;
break ;
case 0x01 :
PrintAndLogEx ( NORMAL , " x1 -> Generation 2 " ) ;
break ;
case 0x02 :
PrintAndLogEx ( NORMAL , " x2 -> Generation 3 " ) ;
break ;
}
switch ( card . ats [ pos + 4 ] & 0x0f ) {
case 0x00 :
PrintAndLogEx ( NORMAL , " x0 -> Only VCSL supported " ) ;
break ;
case 0x01 :
PrintAndLogEx ( NORMAL , " x1 -> VCS, VCSL, and SVC supported " ) ;
break ;
case 0x0E :
PrintAndLogEx ( NORMAL , " xE -> no VCS command supported " ) ;
break ;
}
}
}
} else {
PrintAndLogEx ( INFO , " proprietary non iso14443-4 card found, RATS not supported " ) ;
}
detect_classic_magic ( ) ;
if ( isMifareClassic ) {
int res = detect_classic_prng ( ) ;
if ( res = = 1 )
PrintAndLogEx ( SUCCESS , " Prng detection: " _GREEN_ ( " WEAK " ) ) ;
else if ( res = = 0 )
PrintAndLogEx ( SUCCESS , " Prng detection: " _YELLOW_ ( " HARD " ) ) ;
else
PrintAndLogEx ( FAILED , " prng detection: " _RED_ ( " Fail " ) ) ;
if ( do_nack_test )
detect_classic_nackbug ( ! verbose ) ;
}
return select_status ;
Client cleanup and restructuring. Stage 1...
Next Step is refactoring some of the giant functions which are
just copy/paste of some other ones with just a few line changes,
removing unnecessary 'goto' etc.
The MS Windows version is broken with this commit but will be fixed
soon. Everything can't be done all at once :P
The commands are now hierarchical, for example:
"hf 14a read" vs. "hf 14b read".
You can also request help:
"hf help", "data help", "hf 15 help" etc.
Indents are now space-based, not tab-based anymore. Hopefully
no one will be trolling about it, considering the suicide-prone work
being done here ;)
client/cmdhw.c, client/proxusb.c, client/cmdhw.h, client/proxusb.h,
client/cmdmain.c, client/cmdlfhid.c, client/cmdmain.h, client/cmdlfhid.h,
client/data.c, client/data.h, client/cmdhf.c, client/cmdlf.c,
client/cmdhf.h, client/cmdhf15.c, client/cmdhf14b.c, client/cmdlf.h,
client/cmdhf15.h, client/cmdhf14b.h, client/cmddata.c, client/cmddata.h,
client/ui.c, client/cmdparser.c, client/cmdlfti.c, client/ui.h,
client/cmdlfem4x.c, client/cmdparser.h, client/cmdlfti.h, client/cmdlfem4x.h,
client/graph.c, client/graph.h, client/cmdhf14a.c, client/cmdhf14a.h,
client/cmdhflegic.c, client/cmdhflegic.c: New files.
client/cli.c, client/flasher.c, client/snooper.c, client/proxmark3.c,
client/proxmark3.h, client/Makefile: Update accordingly.
client/flash.h, client/flash.c, client/proxgui.cpp: Cosmetic changes.
client/translate.h, client/command.c, client/gui.c,
client/usb.c, client/prox.h: Remove.
include/usb_cmd.h (CMD_ACQUIRE_RAW_ADC_SAMPLES_ISO_14443_SIM): Remove dead cmd.
common/crc16.h: New file.
common/crc16.c: Modify accordingly.
common/iso14443crc.h: New file.
common/iso14443_crc.c: Rename to
common/iso14443crc.c: and modify accordingly.
armsrc/lfops.c, armsrc/iso14443.c,
armsrc/iso14443a.c: include .h files from
the common directory instead of including the c files.
common/Makefile.common, armsrc/Makefile: Modify accordingly.
2010-02-04 09:27:07 +08:00
}
2019-04-13 00:41:14 +08:00