1 //-----------------------------------------------------------------------------
2 // Copyright (C) 2010 iZsh <izsh at fail0verflow.com>
3 // Modified 2010-2012 by <adrian -at- atrox.at>
4 // Modified 2012 by <vsza at vsza.hu>
5 // Modfified 2018 by <iceman>
7 // This code is licensed to you under the terms of the GNU GPL, version 2 or,
8 // at your option, any later version. See the LICENSE.txt file for the text of
10 //-----------------------------------------------------------------------------
11 // High frequency ISO15693 commands
12 //-----------------------------------------------------------------------------
13 // There are three basic operation modes, depending on which device (proxmark/pc)
14 // the signal processing, (de)modulation, transmission protocol and logic is done.
16 // All steps are done on the proxmark, the output of the commands is returned via
17 // USB-debug-print commands.
19 // The protocol is done on the PC, passing only Iso15693 data frames via USB. This
20 // allows direct communication with a tag on command level
22 // The proxmark just samples the antenna and passes this "analog" data via USB to
23 // the client. Signal Processing & decoding is done on the pc. This is the slowest
24 // variant, but offers the possibility to analyze the waveforms directly.
27 #include "cmdparser.h" // command_t
28 #include "commonutil.h" // ARRAYLEN
29 #include "comms.h" // clearCommandBuffer
31 #include "iso15693tools.h" // ISO15693 error codes etc
32 #include "protocols.h" // ISO15693 command set
33 #include "crypto/libpcrypto.h"
35 #include "crc16.h" // iso15 crc
36 #include "cmddata.h" // getsamples
37 #include "fileutils.h" // savefileEML
38 #include "cliparser.h"
39 #include "util_posix.h" // msleep
41 #define FrameSOF Iso15693FrameSOF
42 #define Logic0 Iso15693Logic0
43 #define Logic1 Iso15693Logic1
44 #define FrameEOF Iso15693FrameEOF
47 # define Crc15(data, len) Crc16ex(CRC_15693, (data), (len))
50 # define CheckCrc15(data, len) check_crc(CRC_15693, (data), (len))
53 #define AddCrc15(data, len) compute_crc(CRC_15693, (data), (len), (data)+(len), (data)+(len)+1)
61 // structure and database for uid -> tagtype lookups
64 int mask
; // how many MSB bits used
68 const productName_t uidmapping
[] = {
70 // UID, #significant Bits, "Vendor(+Product)"
71 { 0xE001000000000000LL
, 16, "Motorola UK" },
74 // 02 = ST Microelectronics
75 // XX = IC id (Chip ID Family)
76 { 0xE002000000000000LL
, 16, "ST Microelectronics SA France" },
77 { 0xE002050000000000LL
, 24, "ST Microelectronics; LRI64 [IC id = 05]"},
78 { 0xE002080000000000LL
, 24, "ST Microelectronics; LRI2K [IC id = 08]"},
79 { 0xE0020A0000000000LL
, 24, "ST Microelectronics; LRIS2K [IC id = 10]"},
80 { 0xE002440000000000LL
, 24, "ST Microelectronics; LRIS64K [IC id = 68]"},
82 { 0xE003000000000000LL
, 16, "Hitachi, Ltd Japan" },
85 // 04 = Manufacturer code (Philips/NXP)
86 // XX = IC id (Chip ID Family)
87 //I-Code SLI SL2 ICS20 [IC id = 01]
88 //I-Code SLI-S [IC id = 02]
89 //I-Code SLI-L [IC id = 03]
90 //I-Code SLIX [IC id = 01 + bit36 set to 1 (starting from bit0 - different from normal SLI)]
91 //I-Code SLIX2 [IC id = 01 + bit35 set to 1 + bit36 set to 0]
92 //I-Code SLIX-S [IC id = 02 + bit36 set to 1]
93 //I-Code SLIX-L [IC id = 03 + bit36 set to 1]
94 { 0xE004000000000000LL
, 16, "NXP Semiconductors Germany (Philips)" },
95 { 0xE004010000000000LL
, 24, "NXP(Philips); IC SL2 ICS20/ICS21(SLI) ICS2002/ICS2102(SLIX) ICS2602(SLIX2)" },
96 { 0xE004020000000000LL
, 24, "NXP(Philips); IC SL2 ICS53/ICS54(SLI-S) ICS5302/ICS5402(SLIX-S)" },
97 { 0xE004030000000000LL
, 24, "NXP(Philips); IC SL2 ICS50/ICS51(SLI-L) ICS5002/ICS5102(SLIX-L)" },
100 // 05 = Manufacturer code (Infineon)
101 // XX = IC id (Chip ID Family)
102 { 0xE005000000000000LL
, 16, "Infineon Technologies AG Germany" },
103 { 0xE005A10000000000LL
, 24, "Infineon; SRF55V01P [IC id = 161] plain mode 1kBit"},
104 { 0xE005A80000000000LL
, 24, "Infineon; SRF55V01P [IC id = 168] pilot series 1kBit"},
105 { 0xE005400000000000LL
, 24, "Infineon; SRF55V02P [IC id = 64] plain mode 2kBit"},
106 { 0xE005000000000000LL
, 24, "Infineon; SRF55V10P [IC id = 00] plain mode 10KBit"},
107 { 0xE005500000000000LL
, 24, "Infineon; SRF55V02S [IC id = 80] secure mode 2kBit"},
108 { 0xE005100000000000LL
, 24, "Infineon; SRF55V10S [IC id = 16] secure mode 10KBit"},
109 { 0xE0051E0000000000LL
, 23, "Infineon; SLE66r01P [IC id = 3x = My-d Move or My-d move NFC]"},
110 { 0xE005200000000000LL
, 21, "Infineon; SLE66r01P [IC id = 3x = My-d Move or My-d move NFC]"},
112 { 0xE006000000000000LL
, 16, "Cylink USA" },
116 // 07 = Texas Instruments
117 // XX = from bit 41 to bit 43 = product configuration - from bit 44 to bit 47 IC id (Chip ID Family)
118 //Tag IT RFIDType-I Plus, 2kBit, TI Inlay
119 //Tag-it HF-I Plus Inlay [IC id = 00] -> b'0000 000 2kBit
120 //Tag-it HF-I Plus Chip [IC id = 64] -> b'1000 000 2kBit
121 //Tag-it HF-I Standard Chip / Inlays [IC id = 96] -> b'1100 000 256Bit
122 //Tag-it HF-I Pro Chip / Inlays [IC id = 98] -> b'1100 010 256Bit, Password protection
123 { 0xE007000000000000LL
, 16, "Texas Instrument France" },
124 { 0xE007000000000000LL
, 20, "Texas Instrument; Tag-it HF-I Plus Inlay; 64x32bit" },
125 { 0xE007100000000000LL
, 20, "Texas Instrument; Tag-it HF-I Plus Chip; 64x32bit" },
126 { 0xE007800000000000LL
, 23, "Texas Instrument; Tag-it HF-I Plus (RF-HDT-DVBB tag or Third Party Products)" },
127 { 0xE007C00000000000LL
, 23, "Texas Instrument; Tag-it HF-I Standard; 8x32bit" },
128 { 0xE007C40000000000LL
, 23, "Texas Instrument; Tag-it HF-I Pro; 8x23bit; password" },
130 { 0xE008000000000000LL
, 16, "Fujitsu Limited Japan" },
131 { 0xE009000000000000LL
, 16, "Matsushita Electronics Corporation, Semiconductor Company Japan" },
132 { 0xE00A000000000000LL
, 16, "NEC Japan" },
133 { 0xE00B000000000000LL
, 16, "Oki Electric Industry Co. Ltd Japan" },
134 { 0xE00C000000000000LL
, 16, "Toshiba Corp. Japan" },
135 { 0xE00D000000000000LL
, 16, "Mitsubishi Electric Corp. Japan" },
136 { 0xE00E000000000000LL
, 16, "Samsung Electronics Co. Ltd Korea" },
137 { 0xE00F000000000000LL
, 16, "Hynix / Hyundai, Korea" },
138 { 0xE010000000000000LL
, 16, "LG-Semiconductors Co. Ltd Korea" },
139 { 0xE011000000000000LL
, 16, "Emosyn-EM Microelectronics USA" },
141 { 0xE012000000000000LL
, 16, "HID Corporation" },
142 { 0xE012000000000000LL
, 16, "INSIDE Technology France" },
143 { 0xE013000000000000LL
, 16, "ORGA Kartensysteme GmbH Germany" },
144 { 0xE014000000000000LL
, 16, "SHARP Corporation Japan" },
145 { 0xE015000000000000LL
, 16, "ATMEL France" },
147 { 0xE016000000000000LL
, 16, "EM Microelectronic-Marin SA Switzerland (Skidata)"},
148 { 0xE016040000000000LL
, 24, "EM-Marin SA (Skidata Keycard-eco); EM4034 [IC id = 01] (Read/Write - no AFI)"},
149 { 0xE0160C0000000000LL
, 24, "EM-Marin SA (Skidata); EM4035 [IC id = 03] (Read/Write - replaced by 4233)"},
150 { 0xE016100000000000LL
, 24, "EM-Marin SA (Skidata); EM4135 [IC id = 04] (Read/Write - replaced by 4233) 36x64bit start page 13"},
151 { 0xE016140000000000LL
, 24, "EM-Marin SA (Skidata); EM4036 [IC id = 05] 28pF"},
152 { 0xE016180000000000LL
, 24, "EM-Marin SA (Skidata); EM4006 [IC id = 06] (Read Only)"},
153 { 0xE0161C0000000000LL
, 24, "EM-Marin SA (Skidata); EM4133 [IC id = 07] 23,5pF (Read/Write)"},
154 { 0xE016200000000000LL
, 24, "EM-Marin SA (Skidata); EM4033 [IC id = 08] 23,5pF (Read Only - no AFI / no DSFID / no security blocks)"},
155 { 0xE016240000000000LL
, 24, "EM-Marin SA (Skidata); EM4233 [IC id = 09] 23,5pF CustomerID-102"},
156 { 0xE016280000000000LL
, 24, "EM-Marin SA (Skidata); EM4233 SLIC [IC id = 10] 23,5pF (1Kb flash memory - not provide High Security mode and QuietStorage feature)" },
157 { 0xE0163C0000000000LL
, 24, "EM-Marin SA (Skidata); EM4237 [IC id = 15] 23,5pF"},
158 { 0xE0167C0000000000LL
, 24, "EM-Marin SA (Skidata); EM4233 [IC id = 31] 95pF"},
159 { 0xE016940000000000LL
, 24, "EM-Marin SA (Skidata); EM4036 [IC id = 37] 95pF 51x64bit "},
160 { 0xE0169c0000000000LL
, 24, "EM-Marin SA (Skidata); EM4133 [IC id = 39] 95pF (Read/Write)" },
161 { 0xE016A80000000000LL
, 24, "EM-Marin SA (Skidata); EM4233 SLIC [IC id = 42] 97pF" },
162 { 0xE016BC0000000000LL
, 24, "EM-Marin SA (Skidata); EM4237 [IC id = 47] 97pF" },
164 { 0xE017000000000000LL
, 16, "KSW Microtec GmbH Germany" },
165 { 0xE018000000000000LL
, 16, "ZMD AG Germany" },
166 { 0xE019000000000000LL
, 16, "XICOR, Inc. USA" },
167 { 0xE01A000000000000LL
, 16, "Sony Corporation Japan Identifier Company Country" },
168 { 0xE01B000000000000LL
, 16, "Malaysia Microelectronic Solutions Sdn. Bhd Malaysia" },
169 { 0xE01C000000000000LL
, 16, "Emosyn USA" },
170 { 0xE01D000000000000LL
, 16, "Shanghai Fudan Microelectronics Co. Ltd. P.R. China" },
171 { 0xE01E000000000000LL
, 16, "Magellan Technology Pty Limited Australia" },
172 { 0xE01F000000000000LL
, 16, "Melexis NV BO Switzerland" },
173 { 0xE020000000000000LL
, 16, "Renesas Technology Corp. Japan" },
174 { 0xE021000000000000LL
, 16, "TAGSYS France" },
175 { 0xE022000000000000LL
, 16, "Transcore USA" },
176 { 0xE023000000000000LL
, 16, "Shanghai belling corp., ltd. China" },
177 { 0xE024000000000000LL
, 16, "Masktech Germany Gmbh Germany" },
178 { 0xE025000000000000LL
, 16, "Innovision Research and Technology Plc UK" },
179 { 0xE026000000000000LL
, 16, "Hitachi ULSI Systems Co., Ltd. Japan" },
180 { 0xE027000000000000LL
, 16, "Cypak AB Sweden" },
181 { 0xE028000000000000LL
, 16, "Ricoh Japan" },
182 { 0xE029000000000000LL
, 16, "ASK France" },
183 { 0xE02A000000000000LL
, 16, "Unicore Microsystems, LLC Russian Federation" },
184 { 0xE02B000000000000LL
, 16, "Dallas Semiconductor/Maxim USA" },
185 { 0xE02C000000000000LL
, 16, "Impinj, Inc. USA" },
186 { 0xE02D000000000000LL
, 16, "RightPlug Alliance USA" },
187 { 0xE02E000000000000LL
, 16, "Broadcom Corporation USA" },
188 { 0xE02F000000000000LL
, 16, "MStar Semiconductor, Inc Taiwan, ROC" },
189 { 0xE030000000000000LL
, 16, "BeeDar Technology Inc. USA" },
190 { 0xE031000000000000LL
, 16, "RFIDsec Denmark" },
191 { 0xE032000000000000LL
, 16, "Schweizer Electronic AG Germany" },
192 { 0xE033000000000000LL
, 16, "AMIC Technology Corp Taiwan" },
193 { 0xE034000000000000LL
, 16, "Mikron JSC Russia" },
194 { 0xE035000000000000LL
, 16, "Fraunhofer Institute for Photonic Microsystems Germany" },
195 { 0xE036000000000000LL
, 16, "IDS Microchip AG Switzerland" },
196 { 0xE037000000000000LL
, 16, "Kovio USA" },
197 { 0xE038000000000000LL
, 16, "HMT Microelectronic Ltd Switzerland Identifier Company Country" },
198 { 0xE039000000000000LL
, 16, "Silicon Craft Technology Thailand" },
199 { 0xE03A000000000000LL
, 16, "Advanced Film Device Inc. Japan" },
200 { 0xE03B000000000000LL
, 16, "Nitecrest Ltd UK" },
201 { 0xE03C000000000000LL
, 16, "Verayo Inc. USA" },
202 { 0xE03D000000000000LL
, 16, "HID Global USA" },
203 { 0xE03E000000000000LL
, 16, "Productivity Engineering Gmbh Germany" },
204 { 0xE03F000000000000LL
, 16, "Austriamicrosystems AG (reserved) Austria" },
205 { 0xE040000000000000LL
, 16, "Gemalto SA France" },
206 { 0xE041000000000000LL
, 16, "Renesas Electronics Corporation Japan" },
207 { 0xE042000000000000LL
, 16, "3Alogics Inc Korea" },
208 { 0xE043000000000000LL
, 16, "Top TroniQ Asia Limited Hong Kong" },
209 { 0xE044000000000000LL
, 16, "Gentag Inc (USA) USA" },
210 { 0, 0, "no tag-info available" } // must be the last entry
213 static int CmdHF15Help(const char *Cmd
);
215 static int nxp_15693_print_signature(uint8_t *uid
, uint8_t *signature
) {
217 #define PUBLIC_ECDA_KEYLEN 33
218 const ecdsa_publickey_t nxp_15693_public_keys
[] = {
219 {"NXP Mifare Classic MFC1C14_x", "044F6D3F294DEA5737F0F46FFEE88A356EED95695DD7E0C27A591E6F6F65962BAF"},
220 {"Manufacturer Mifare Classic MFC1C14_x", "046F70AC557F5461CE5052C8E4A7838C11C7A236797E8A0730A101837C004039C2"},
221 {"NXP ICODE DNA, ICODE SLIX2", "048878A2A2D3EEC336B4F261A082BD71F9BE11C4E2E896648B32EFA59CEA6E59F0"},
222 {"NXP Public key", "04A748B6A632FBEE2C0897702B33BEA1C074998E17B84ACA04FF267E5D2C91F6DC"},
223 {"NXP Ultralight Ev1", "0490933BDCD6E99B4E255E3DA55389A827564E11718E017292FAF23226A96614B8"},
224 {"NXP NTAG21x (2013)", "04494E1A386D3D3CFE3DC10E5DE68A499B1C202DB5B132393E89ED19FE5BE8BC61"},
225 {"MIKRON Public key", "04f971eda742a4a80d32dcf6a814a707cc3dc396d35902f72929fdcd698b3468f2"},
226 {"VivoKey Spark1 Public key", "04d64bb732c0d214e7ec580736acf847284b502c25c0f7f2fa86aace1dada4387a"},
229 uint8_t nxp_15693_public_keys[][PUBLIC_ECDA_KEYLEN] = {
232 0x04, 0x88, 0x78, 0xA2, 0xA2, 0xD3, 0xEE, 0xC3,
233 0x36, 0xB4, 0xF2, 0x61, 0xA0, 0x82, 0xBD, 0x71,
234 0xF9, 0xBE, 0x11, 0xC4, 0xE2, 0xE8, 0x96, 0x64,
235 0x8B, 0x32, 0xEF, 0xA5, 0x9C, 0xEA, 0x6E, 0x59, 0xF0
237 // unknown. Needs identification
239 0x04, 0x4F, 0x6D, 0x3F, 0x29, 0x4D, 0xEA, 0x57,
240 0x37, 0xF0, 0xF4, 0x6F, 0xFE, 0xE8, 0x8A, 0x35,
241 0x6E, 0xED, 0x95, 0x69, 0x5D, 0xD7, 0xE0, 0xC2,
242 0x7A, 0x59, 0x1E, 0x6F, 0x6F, 0x65, 0x96, 0x2B, 0xAF
244 // unknown. Needs identification
246 0x04, 0xA7, 0x48, 0xB6, 0xA6, 0x32, 0xFB, 0xEE,
247 0x2C, 0x08, 0x97, 0x70, 0x2B, 0x33, 0xBE, 0xA1,
248 0xC0, 0x74, 0x99, 0x8E, 0x17, 0xB8, 0x4A, 0xCA,
249 0x04, 0xFF, 0x26, 0x7E, 0x5D, 0x2C, 0x91, 0xF6, 0xDC
251 // manufacturer public key
253 0x04, 0x6F, 0x70, 0xAC, 0x55, 0x7F, 0x54, 0x61,
254 0xCE, 0x50, 0x52, 0xC8, 0xE4, 0xA7, 0x83, 0x8C,
255 0x11, 0xC7, 0xA2, 0x36, 0x79, 0x7E, 0x8A, 0x07,
256 0x30, 0xA1, 0x01, 0x83, 0x7C, 0x00, 0x40, 0x39, 0xC2
258 // MIKRON public key.
260 0x04, 0xf9, 0x71, 0xed, 0xa7, 0x42, 0xa4, 0xa8,
261 0x0d, 0x32, 0xdc, 0xf6, 0xa8, 0x14, 0xa7, 0x07,
262 0xcc, 0x3d, 0xc3, 0x96, 0xd3, 0x59, 0x02, 0xf7,
263 0x29, 0x29, 0xfd, 0xcd, 0x69, 0x8b, 0x34, 0x68, 0xf2
269 for (i
= 0; i
< sizeof(revuid
); i
++) {
270 revuid
[i
] = uid
[7 - i
];
273 for (i
= 0; i
< sizeof(revsign
); i
++) {
274 revsign
[i
] = signature
[31 - i
];
278 bool is_valid
= false;
279 for (i
= 0; i
< ARRAYLEN(nxp_15693_public_keys
); i
++) {
282 uint8_t key
[PUBLIC_ECDA_KEYLEN
];
283 param_gethex_to_eol(nxp_15693_public_keys
[i
].value
, 0, key
, PUBLIC_ECDA_KEYLEN
, &dl
);
285 int res
= ecdsa_signature_r_s_verify(MBEDTLS_ECP_DP_SECP128R1
, key
, uid
, 8, signature
, 32, false);
286 is_valid
= (res
== 0);
293 res
= ecdsa_signature_r_s_verify(MBEDTLS_ECP_DP_SECP128R1
, key
, uid
, 8, signature
, 32, true);
294 is_valid
= (res
== 0);
300 // try with reversed uid / signature
301 res
= ecdsa_signature_r_s_verify(MBEDTLS_ECP_DP_SECP128R1
, key
, revuid
, sizeof(revuid
), revsign
, sizeof(revsign
), false);
302 is_valid
= (res
== 0);
310 res
= ecdsa_signature_r_s_verify(MBEDTLS_ECP_DP_SECP128R1
, key
, revuid
, sizeof(revuid
), revsign
, sizeof(revsign
), true);
311 is_valid
= (res
== 0);
318 PrintAndLogEx(NORMAL
, "");
319 PrintAndLogEx(INFO
, "--- " _CYAN_("Tag Signature"));
320 if (is_valid
== false || i
== ARRAYLEN(nxp_15693_public_keys
)) {
321 PrintAndLogEx(INFO
, " Elliptic curve parameters: NID_secp128r1");
322 PrintAndLogEx(INFO
, " TAG IC Signature: %s", sprint_hex_inrow(signature
, 32));
323 PrintAndLogEx(SUCCESS
, " Signature verification: " _RED_("failed"));
327 PrintAndLogEx(INFO
, " IC signature public key name: %s", nxp_15693_public_keys
[i
].desc
);
328 PrintAndLogEx(INFO
, "IC signature public key value: %s", nxp_15693_public_keys
[i
].value
);
329 PrintAndLogEx(INFO
, " Elliptic curve parameters: NID_secp128r1");
330 PrintAndLogEx(INFO
, " TAG IC Signature: %s", sprint_hex_inrow(signature
, 32));
331 PrintAndLogEx(SUCCESS
, " Signature verification: " _GREEN_("successful"));
334 PrintAndLogEx(INFO
, " Params used: UID and signature, plain");
337 PrintAndLogEx(INFO
, " Params used: UID and signature, SHA256");
340 PrintAndLogEx(INFO
, " Params used: reversed UID and signature, plain");
343 PrintAndLogEx(INFO
, " Params used: reversed UID and signature, SHA256");
349 // get a product description based on the UID
351 // returns description of the best match
352 static const char *getTagInfo_15(uint8_t *uid
) {
357 uint64_t myuid
, mask
;
358 int i
= 0, best
= -1;
359 memcpy(&myuid
, uid
, sizeof(uint64_t));
360 while (uidmapping
[i
].mask
> 0) {
361 mask
= (~0ULL) << (64 - uidmapping
[i
].mask
);
362 if ((myuid
& mask
) == uidmapping
[i
].uid
) {
366 if (uidmapping
[i
].mask
> uidmapping
[best
].mask
) {
375 return uidmapping
[best
].desc
;
376 return uidmapping
[i
].desc
;
379 // return a clear-text message to an errorcode
380 static const char *TagErrorStr(uint8_t error
) {
383 return "The command is not supported";
385 return "The command is not recognized";
387 return "The option is not supported.";
389 return "Unknown error.";
391 return "The specified block is not available (doesn't exist).";
393 return "The specified block is already -locked and thus cannot be locked again";
395 return "The specified block is locked and its content cannot be changed.";
397 return "The specified block was not successfully programmed.";
399 return "The specified block was not successfully locked.";
401 return "Reserved for Future Use or Custom command error.";
405 // fast method to just read the UID of a tag (collision detection not supported)
406 // *buf should be large enough to fit the 64bit uid
407 // returns 1 if succeeded
408 static int getUID(bool loop
, uint8_t *buf
) {
411 data
[0] = ISO15_REQ_SUBCARRIER_SINGLE
| ISO15_REQ_DATARATE_HIGH
| ISO15_REQ_INVENTORY
| ISO15_REQINV_SLOT1
;
412 data
[1] = ISO15693_INVENTORY
;
413 data
[2] = 0; // mask length
424 clearCommandBuffer();
425 SendCommandMIX(CMD_HF_ISO15693_COMMAND
, sizeof(data
), fast
, reply
, data
, sizeof(data
));
426 PacketResponseNG resp
;
427 if (WaitForResponseTimeout(CMD_ACK
, &resp
, 2000)) {
429 int resplen
= resp
.oldarg
[0];
430 if (resplen
>= 12 && CheckCrc15(resp
.data
.asBytes
, 12)) {
433 memcpy(buf
, resp
.data
.asBytes
+ 2, 8);
437 PrintAndLogEx(NORMAL
, "");
438 PrintAndLogEx(SUCCESS
, " UID: " _GREEN_("%s"), iso15693_sprintUID(NULL
, buf
));
439 PrintAndLogEx(SUCCESS
, "TYPE: " _YELLOW_("%s"), getTagInfo_15(buf
));
448 } while (loop
&& kbd_enter_pressed() == false);
454 // used with 'hf search'
455 bool readHF15Uid(bool loop
, bool verbose
) {
456 uint8_t uid
[8] = {0};
457 if (getUID(loop
, uid
) != PM3_SUCCESS
) {
458 if (verbose
) PrintAndLogEx(WARNING
, "no tag found");
465 static uint8_t arg_add_default(void *at
[]) {
466 at
[0] = arg_param_begin
;
467 at
[1] = arg_str0("u", "uid", "<hex>", "full UID, 8 bytes");
468 at
[2] = arg_lit0(NULL
, "ua", "unaddressed mode");
469 at
[3] = arg_lit0("*", NULL
, "scan for tag");
470 at
[4] = arg_lit0("2", NULL
, "use slower '1 out of 256' mode");
471 at
[5] = arg_lit0("o", "opt", "set OPTION Flag (needed for TI)");
474 static uint16_t arg_get_raw_flag(uint8_t uidlen
, bool unaddressed
, bool scan
, bool add_option
) {
477 // unaddressed mode may not be supported by all vendors
478 flags
|= (ISO15_REQ_SUBCARRIER_SINGLE
| ISO15_REQ_DATARATE_HIGH
| ISO15_REQ_NONINVENTORY
);
481 flags
|= (ISO15_REQ_SUBCARRIER_SINGLE
| ISO15_REQ_DATARATE_HIGH
| ISO15_REQ_NONINVENTORY
| ISO15_REQ_ADDRESS
);
484 flags
|= (ISO15_REQ_SUBCARRIER_SINGLE
| ISO15_REQ_DATARATE_HIGH
| ISO15_REQ_NONINVENTORY
| ISO15_REQ_ADDRESS
);
487 flags
|= (ISO15_REQ_OPTION
);
493 static int CmdHF15Demod(const char *Cmd
) {
495 CLIParserContext
*ctx
;
496 CLIParserInit(&ctx
, "hf 15 demod",
497 "Tries to demodulate / decode ISO-15693, from downloaded samples.\n"
498 "Gather samples with 'hf 15 samples' / 'hf 15 sniff'",
505 CLIExecWithReturn(ctx
, Cmd
, argtable
, true);
508 // The sampling rate is 106.353 ksps/s, for T = 18.8 us
510 int max
= 0, maxPos
= 0;
513 if (GraphTraceLen
< 1000) {
514 PrintAndLogEx(FAILED
, "Too few samples in GraphBuffer. Need more than 1000");
515 PrintAndLogEx(HINT
, "Run " _YELLOW_("`hf 15 samples`") " to collect and download data");
519 // First, correlate for SOF
520 for (i
= 0; i
< 1000; i
++) {
522 for (j
= 0; j
< ARRAYLEN(FrameSOF
); j
+= skip
) {
523 corr
+= FrameSOF
[j
] * GraphBuffer
[i
+ (j
/ skip
)];
531 PrintAndLogEx(INFO
, "SOF at %d, correlation %zu", maxPos
, max
/ (ARRAYLEN(FrameSOF
) / skip
));
533 i
= maxPos
+ ARRAYLEN(FrameSOF
) / skip
;
535 uint8_t outBuf
[2048] = {0};
536 memset(outBuf
, 0, sizeof(outBuf
));
539 int corr0
= 0, corr1
= 0, corrEOF
= 0;
540 for (j
= 0; j
< ARRAYLEN(Logic0
); j
+= skip
) {
541 corr0
+= Logic0
[j
] * GraphBuffer
[i
+ (j
/ skip
)];
543 for (j
= 0; j
< ARRAYLEN(Logic1
); j
+= skip
) {
544 corr1
+= Logic1
[j
] * GraphBuffer
[i
+ (j
/ skip
)];
546 for (j
= 0; j
< ARRAYLEN(FrameEOF
); j
+= skip
) {
547 corrEOF
+= FrameEOF
[j
] * GraphBuffer
[i
+ (j
/ skip
)];
549 // Even things out by the length of the target waveform.
553 if (corrEOF
> corr1
&& corrEOF
> corr0
) {
554 PrintAndLogEx(INFO
, "EOF at %d", i
);
556 } else if (corr1
> corr0
) {
557 i
+= ARRAYLEN(Logic1
) / skip
;
560 i
+= ARRAYLEN(Logic0
) / skip
;
569 if ((i
+ (int)ARRAYLEN(FrameEOF
)) >= GraphTraceLen
) {
570 PrintAndLogEx(INFO
, "ran off end!");
575 PrintAndLogEx(INFO
, "ran out of buffer");
581 PrintAndLogEx(WARNING
, "Warning, uneven octet! (discard extra bits!)");
582 PrintAndLogEx(INFO
, " mask = %02x", mask
);
590 PrintAndLogEx(NORMAL
, "");
591 PrintAndLogEx(INFO
, "Got %d octets, decoded as following", k
);
592 PrintAndLogEx(NORMAL
, "");
593 PrintAndLogEx(SUCCESS
, " idx | data");
594 PrintAndLogEx(SUCCESS
, "-----+-------------------------------------------------");
596 for (; i
< k
; i
+= 16) {
597 PrintAndLogEx(SUCCESS
, " %3i | %s", i
, sprint_hex(outBuf
+ i
, 16));
601 uint8_t mod
= (k
% 16);
603 PrintAndLogEx(SUCCESS
, " %3i | %s", i
, sprint_hex(outBuf
+ i
, mod
));
605 PrintAndLogEx(SUCCESS
, "-----+-------------------------------------------------");
607 PrintAndLogEx(SUCCESS
, "--> CRC %04x", Crc15(outBuf
, k
- 2));
609 PrintAndLogEx(NORMAL
, "");
613 // * Acquire Samples as Reader (enables carrier, sends inquiry)
615 static int CmdHF15Samples(const char *Cmd
) {
617 CLIParserContext
*ctx
;
618 CLIParserInit(&ctx
, "hf 15 samples",
619 "Acquire samples as Reader (enables carrier, send inquiry\n"
620 "and download it to graphbuffer. Try 'hf 15 demod' to try to demodulate/decode signal",
627 CLIExecWithReturn(ctx
, Cmd
, argtable
, false);
630 clearCommandBuffer();
631 SendCommandNG(CMD_HF_ISO15693_ACQ_RAW_ADC
, NULL
, 0);
635 PrintAndLogEx(HINT
, "Try `" _YELLOW_("hf 15 demod") "` to decode signal");
639 // Get NXP system information from SLIX2 tag/VICC
640 static int NxpSysInfo(uint8_t *uid
) {
646 uint8_t req
[PM3_CMD_DATA_SIZE
] = {0};
651 req
[reqlen
++] |= ISO15_REQ_SUBCARRIER_SINGLE
| ISO15_REQ_DATARATE_HIGH
| ISO15_REQ_NONINVENTORY
| ISO15_REQ_ADDRESS
;
652 req
[reqlen
++] = ISO15693_GET_SYSTEM_INFO
;
653 req
[reqlen
++] = 0x04; // IC manufacturer code
654 memcpy(req
+ 3, uid
, 8); // add UID
657 AddCrc15(req
, reqlen
);
660 PacketResponseNG resp
;
661 clearCommandBuffer();
662 SendCommandMIX(CMD_HF_ISO15693_COMMAND
, reqlen
, fast
, reply
, req
, reqlen
);
663 if (!WaitForResponseTimeout(CMD_ACK
, &resp
, 2000)) {
664 PrintAndLogEx(WARNING
, "iso15693 timeout");
671 int status
= resp
.oldarg
[0];
672 if (status
== PM3_ETEAROFF
) {
677 PrintAndLogEx(WARNING
, "iso15693 card doesn't answer to NXP systeminfo command");
678 return PM3_EWRONGANSWER
;
681 uint8_t *recv
= resp
.data
.asBytes
;
683 if ((recv
[0] & ISO15_RES_ERROR
) == ISO15_RES_ERROR
) {
684 PrintAndLogEx(ERR
, "iso15693 card returned error %i: %s", recv
[0], TagErrorStr(recv
[0]));
685 return PM3_EWRONGANSWER
;
688 bool support_signature
= (recv
[5] & 0x01);
689 bool support_easmode
= (recv
[4] & 0x03);
691 PrintAndLogEx(INFO
, "--------- " _CYAN_("NXP Sysinfo") " ---------");
692 PrintAndLogEx(INFO
, " raw : %s", sprint_hex(recv
, 8));
693 PrintAndLogEx(INFO
, " Password protection configuration:");
694 PrintAndLogEx(INFO
, " * Page L read%s password protected", ((recv
[2] & 0x01) ? "" : " not"));
695 PrintAndLogEx(INFO
, " * Page L write%s password protected", ((recv
[2] & 0x02) ? "" : " not"));
696 PrintAndLogEx(INFO
, " * Page H read%s password protected", ((recv
[2] & 0x08) ? "" : " not"));
697 PrintAndLogEx(INFO
, " * Page H write%s password protected", ((recv
[2] & 0x20) ? "" : " not"));
699 PrintAndLogEx(INFO
, " Lock bits:");
700 PrintAndLogEx(INFO
, " * AFI%s locked", ((recv
[3] & 0x01) ? "" : " not")); // AFI lock bit
701 PrintAndLogEx(INFO
, " * EAS%s locked", ((recv
[3] & 0x02) ? "" : " not")); // EAS lock bit
702 PrintAndLogEx(INFO
, " * DSFID%s locked", ((recv
[3] & 0x03) ? "" : " not")); // DSFID lock bit
703 PrintAndLogEx(INFO
, " * Password protection configuration%s locked", ((recv
[3] & 0x04) ? "" : " not")); // Password protection pointer address and access conditions lock bit
705 PrintAndLogEx(INFO
, " Features:");
706 PrintAndLogEx(INFO
, " * User memory password protection%s supported", ((recv
[4] & 0x01) ? "" : " not"));
707 PrintAndLogEx(INFO
, " * Counter feature%s supported", ((recv
[4] & 0x02) ? "" : " not"));
708 PrintAndLogEx(INFO
, " * EAS ID%s supported by EAS ALARM command", support_easmode
? "" : " not");
709 PrintAndLogEx(INFO
, " * EAS password protection%s supported", ((recv
[4] & 0x04) ? "" : " not"));
710 PrintAndLogEx(INFO
, " * AFI password protection%s supported", ((recv
[4] & 0x10) ? "" : " not"));
711 PrintAndLogEx(INFO
, " * Extended mode%s supported by INVENTORY READ command", ((recv
[4] & 0x20) ? "" : " not"));
712 PrintAndLogEx(INFO
, " * EAS selection%s supported by extended mode in INVENTORY READ command", ((recv
[4] & 0x40) ? "" : " not"));
713 PrintAndLogEx(INFO
, " * READ SIGNATURE command%s supported", support_signature
? "" : " not");
714 PrintAndLogEx(INFO
, " * Password protection for READ SIGNATURE command%s supported", ((recv
[5] & 0x02) ? "" : " not"));
715 PrintAndLogEx(INFO
, " * STAY QUIET PERSISTENT command%s supported", ((recv
[5] & 0x03) ? "" : " not"));
716 PrintAndLogEx(INFO
, " * ENABLE PRIVACY command%s supported", ((recv
[5] & 0x10) ? "" : " not"));
717 PrintAndLogEx(INFO
, " * DESTROY command%s supported", ((recv
[5] & 0x20) ? "" : " not"));
718 PrintAndLogEx(INFO
, " * Additional 32 bits feature flags are%s transmitted", ((recv
[5] & 0x80) ? "" : " not"));
720 if (support_easmode
) {
722 req
[reqlen
++] |= ISO15_REQ_SUBCARRIER_SINGLE
| ISO15_REQ_DATARATE_HIGH
| ISO15_REQ_NONINVENTORY
| ISO15_REQ_ADDRESS
;
723 req
[reqlen
++] = ISO15693_EAS_ALARM
;
724 req
[reqlen
++] = 0x04; // IC manufacturer code
725 memcpy(req
+ 3, uid
, 8); // add UID
728 AddCrc15(req
, reqlen
);
731 clearCommandBuffer();
732 SendCommandMIX(CMD_HF_ISO15693_COMMAND
, reqlen
, fast
, reply
, req
, reqlen
);
734 if (!WaitForResponseTimeout(CMD_ACK
, &resp
, 2000)) {
735 PrintAndLogEx(WARNING
, "iso15693 timeout");
737 PrintAndLogEx(NORMAL
, "");
739 status
= resp
.oldarg
[0];
741 PrintAndLogEx(INFO
, " EAS (Electronic Article Surveillance) is not active");
743 recv
= resp
.data
.asBytes
;
745 if (!(recv
[0] & ISO15_RES_ERROR
)) {
746 PrintAndLogEx(INFO
, " EAS (Electronic Article Surveillance) is active.");
747 PrintAndLogEx(INFO
, " EAS sequence: %s", sprint_hex(recv
+ 1, 32));
753 if (support_signature
) {
754 // Check if we can also read the signature
756 req
[reqlen
++] |= ISO15_REQ_SUBCARRIER_SINGLE
| ISO15_REQ_DATARATE_HIGH
| ISO15_REQ_NONINVENTORY
| ISO15_REQ_ADDRESS
;
757 req
[reqlen
++] = ISO15693_READ_SIGNATURE
;
758 req
[reqlen
++] = 0x04; // IC manufacturer code
759 memcpy(req
+ 3, uid
, 8); // add UID
762 AddCrc15(req
, reqlen
);
765 clearCommandBuffer();
766 SendCommandMIX(CMD_HF_ISO15693_COMMAND
, reqlen
, fast
, reply
, req
, reqlen
);
768 if (WaitForResponseTimeout(CMD_ACK
, &resp
, 2000) == false) {
769 PrintAndLogEx(WARNING
, "iso15693 timeout");
776 status
= resp
.oldarg
[0];
778 PrintAndLogEx(WARNING
, "iso15693 card doesn't answer to READ SIGNATURE command");
779 return PM3_EWRONGANSWER
;
782 recv
= resp
.data
.asBytes
;
784 if ((recv
[0] & ISO15_RES_ERROR
) == ISO15_RES_ERROR
) {
785 PrintAndLogEx(ERR
, "iso15693 card returned error %i: %s", recv
[0], TagErrorStr(recv
[0]));
786 return PM3_EWRONGANSWER
;
789 uint8_t signature
[32] = {0x00};
790 memcpy(signature
, recv
+ 1, 32);
792 nxp_15693_print_signature(uid
, signature
);
799 * Commandline handling: HF15 CMD SYSINFO
800 * get system information from tag/VICC
802 static int CmdHF15Info(const char *Cmd
) {
804 CLIParserContext
*ctx
;
805 CLIParserInit(&ctx
, "hf 15 info",
806 "Uses the optional command `get_systeminfo` 0x2B to try and extract information",
809 "hf 15 info -u E011223344556677"
812 void *argtable
[6 + 1] = {};
813 uint8_t arglen
= arg_add_default(argtable
);
814 argtable
[arglen
++] = arg_param_end
;
816 CLIExecWithReturn(ctx
, Cmd
, argtable
, true);
820 CLIGetHexWithReturn(ctx
, 1, uid
, &uidlen
);
821 bool unaddressed
= arg_get_lit(ctx
, 2);
822 bool scan
= arg_get_lit(ctx
, 3);
823 int fast
= (arg_get_lit(ctx
, 4) == false);
824 bool add_option
= arg_get_lit(ctx
, 5);
829 if ((scan
+ unaddressed
+ uidlen
) > 1) {
830 PrintAndLogEx(WARNING
, "Select only one option /scan/unaddress/uid");
834 // default fallback to scan for tag.
835 if (unaddressed
== false && uidlen
!= 8) {
839 // request to be sent to device/card
840 uint16_t flags
= arg_get_raw_flag(uidlen
, unaddressed
, scan
, add_option
);
841 uint8_t req
[PM3_CMD_DATA_SIZE
] = {flags
, ISO15693_GET_SYSTEM_INFO
};
845 if (getUID(false, uid
) != PM3_SUCCESS
) {
846 PrintAndLogEx(WARNING
, "no tag found");
853 // add UID (scan, uid)
854 memcpy(req
+ reqlen
, uid
, sizeof(uid
));
855 reqlen
+= sizeof(uid
);
857 PrintAndLogEx(SUCCESS
, "Using UID... " _GREEN_("%s"), iso15693_sprintUID(NULL
, uid
));
860 AddCrc15(req
, reqlen
);
863 uint8_t read_response
= 1;
864 PacketResponseNG resp
;
865 clearCommandBuffer();
866 SendCommandMIX(CMD_HF_ISO15693_COMMAND
, reqlen
, fast
, read_response
, req
, reqlen
);
867 if (WaitForResponseTimeout(CMD_ACK
, &resp
, 2000) == false) {
868 PrintAndLogEx(WARNING
, "iso15693 timeout");
875 int status
= resp
.oldarg
[0];
876 if (status
== PM3_ETEAROFF
) {
880 PrintAndLogEx(WARNING
, "iso15693 card doesn't answer to systeminfo command (%d)", status
);
881 return PM3_EWRONGANSWER
;
884 uint8_t *data
= resp
.data
.asBytes
;
886 if ((data
[0] & ISO15_RES_ERROR
) == ISO15_RES_ERROR
) {
887 PrintAndLogEx(ERR
, "iso15693 card returned error %i: %s", data
[0], TagErrorStr(data
[0]));
888 return PM3_EWRONGANSWER
;
891 memcpy(uid
, data
+ 2, sizeof(uid
));
892 PrintAndLogEx(NORMAL
, "");
893 PrintAndLogEx(INFO
, "--- " _CYAN_("Tag Information") " ---------------------------");
894 PrintAndLogEx(INFO
, "-------------------------------------------------------------");
895 PrintAndLogEx(SUCCESS
, " TYPE: " _YELLOW_("%s"), getTagInfo_15(data
+ 2));
896 PrintAndLogEx(SUCCESS
, " UID: " _GREEN_("%s"), iso15693_sprintUID(NULL
, uid
));
897 PrintAndLogEx(SUCCESS
, " SYSINFO: %s", sprint_hex(data
, status
- 2));
901 PrintAndLogEx(SUCCESS
, " - DSFID supported [0x%02X]", data
[10]);
903 PrintAndLogEx(SUCCESS
, " - DSFID not supported");
907 PrintAndLogEx(SUCCESS
, " - AFI supported [0x%02X]", data
[11]);
909 PrintAndLogEx(SUCCESS
, " - AFI not supported");
913 PrintAndLogEx(SUCCESS
, " - IC reference supported [0x%02X]", data
[14]);
915 PrintAndLogEx(SUCCESS
, " - IC reference not supported");
918 if (data
[1] & 0x04) {
919 PrintAndLogEx(SUCCESS
, " - Tag provides info on memory layout (vendor dependent)");
920 uint8_t blocks
= data
[12] + 1;
921 uint8_t size
= (data
[13] & 0x1F);
922 PrintAndLogEx(SUCCESS
, " %u (or %u) bytes/blocks x %u blocks", size
+ 1, size
, blocks
);
924 PrintAndLogEx(SUCCESS
, " - Tag does not provide information on memory layout");
927 // Check if SLIX2 and attempt to get NXP System Information
928 PrintAndLogEx(DEBUG
, "4 & 08 :: %02x 7 == 1 :: %u 8 == 4 :: %u", data
[4], data
[7], data
[8]);
929 if (data
[8] == 0x04 && data
[7] == 0x01 && data
[4] & 0x80) {
930 return NxpSysInfo(uid
);
933 PrintAndLogEx(NORMAL
, "");
937 // Sniff Activity without enabling carrier
938 static int CmdHF15Sniff(const char *Cmd
) {
939 CLIParserContext
*ctx
;
940 CLIParserInit(&ctx
, "hf 15 sniff",
941 "Sniff activity without enabling carrier",
948 CLIExecWithReturn(ctx
, Cmd
, argtable
, true);
951 PacketResponseNG resp
;
952 clearCommandBuffer();
953 SendCommandNG(CMD_HF_ISO15693_SNIFF
, NULL
, 0);
955 WaitForResponse(CMD_HF_ISO15693_SNIFF
, &resp
);
957 PrintAndLogEx(HINT
, "Try `" _YELLOW_("hf 15 list") "` to view captured tracelog");
958 PrintAndLogEx(HINT
, "Try `" _YELLOW_("trace save -h") "` to save tracelog for later analysing");
962 static int CmdHF15Reader(const char *Cmd
) {
963 CLIParserContext
*ctx
;
964 CLIParserInit(&ctx
, "hf 15 reader",
965 "Act as a ISO-15693 reader. Look for ISO-15693 tags until Enter or the pm3 button is pressed\n",
967 "hf 15 reader -@ -> Continuous mode");
971 arg_lit0("@", NULL
, "continuous reader mode"),
974 CLIExecWithReturn(ctx
, Cmd
, argtable
, true);
975 bool cm
= arg_get_lit(ctx
, 1);
979 PrintAndLogEx(INFO
, "press " _GREEN_("`Enter`") " to exit");
981 readHF15Uid(cm
, true);
985 // Simulation is still not working very good
987 static int CmdHF15Sim(const char *Cmd
) {
989 CLIParserContext
*ctx
;
990 CLIParserInit(&ctx
, "hf 15 sim",
991 "Simulate a ISO-15693 tag\n",
992 "hf 15 sim -u E011223344556677");
996 arg_str1("u", "uid", "<8b hex>", "UID eg E011223344556677"),
999 CLIExecWithReturn(ctx
, Cmd
, argtable
, false);
1006 CLIGetHexWithReturn(ctx
, 1, payload
.uid
, &uidlen
);
1010 PrintAndLogEx(WARNING
, "UID must include 16 HEX symbols");
1014 PrintAndLogEx(SUCCESS
, "Starting simulating UID " _YELLOW_("%s"), iso15693_sprintUID(NULL
, payload
.uid
));
1015 PrintAndLogEx(INFO
, "press " _YELLOW_("`Pm3 button`") " to cancel");
1017 PacketResponseNG resp
;
1018 clearCommandBuffer();
1019 SendCommandNG(CMD_HF_ISO15693_SIMULATE
, (uint8_t *)&payload
, sizeof(payload
));
1020 WaitForResponse(CMD_HF_ISO15693_SIMULATE
, &resp
);
1024 // finds the AFI (Application Family Identifier) of a card, by trying all values
1025 // (There is no standard way of reading the AFI, although some tags support this)
1027 static int CmdHF15FindAfi(const char *Cmd
) {
1028 CLIParserContext
*ctx
;
1029 CLIParserInit(&ctx
, "hf 15 findafi",
1030 "This command attempts to brute force AFI of an ISO-15693 tag\n"
1031 "Estimated execution time is around 2 minutes",
1034 void *argtable
[] = {
1038 CLIExecWithReturn(ctx
, Cmd
, argtable
, true);
1041 PrintAndLogEx(INFO
, "click " _GREEN_("pm3 button") " or press " _GREEN_("Enter") " to exit");
1042 clearCommandBuffer();
1043 PacketResponseNG resp
;
1044 SendCommandMIX(CMD_HF_ISO15693_FINDAFI
, strtol(Cmd
, NULL
, 0), 0, 0, NULL
, 0);
1046 uint32_t timeout
= 0;
1049 if (kbd_enter_pressed()) {
1050 SendCommandNG(CMD_BREAK_LOOP
, NULL
, 0);
1051 PrintAndLogEx(DEBUG
, "User aborted");
1056 if (WaitForResponseTimeout(CMD_HF_ISO15693_FINDAFI
, &resp
, 2000)) {
1057 if (resp
.status
== PM3_EOPABORTED
) {
1058 PrintAndLogEx(DEBUG
, "Button pressed, user aborted");
1063 // should be done in about 2 minutes
1064 if (timeout
> 180) {
1065 PrintAndLogEx(WARNING
, "\nNo response from Proxmark3. Aborting...");
1072 PrintAndLogEx(INFO
, "Done");
1076 // Writes the AFI (Application Family Identifier) of a card
1077 static int CmdHF15WriteAfi(const char *Cmd
) {
1078 CLIParserContext
*ctx
;
1079 CLIParserInit(&ctx
, "hf 15 writeafi",
1080 "Write AFI on card",
1081 "hf 15 writeafi -* --afi 12\n"
1082 "hf 15 writeafi -u E011223344556677 --afi 12"
1085 void *argtable
[6 + 2] = {};
1086 uint8_t arglen
= arg_add_default(argtable
);
1087 argtable
[arglen
++] = arg_int1(NULL
, "afi", "<dec>", "AFI number (0-255)");
1088 argtable
[arglen
++] = arg_param_end
;
1090 CLIExecWithReturn(ctx
, Cmd
, argtable
, false);
1094 CLIGetHexWithReturn(ctx
, 1, uid
, &uidlen
);
1095 bool unaddressed
= arg_get_lit(ctx
, 2);
1096 bool scan
= arg_get_lit(ctx
, 3);
1097 int fast
= (arg_get_lit(ctx
, 4) == false);
1098 bool add_option
= arg_get_lit(ctx
, 5);
1100 int afi
= arg_get_int_def(ctx
, 6, 0);
1104 if ((scan
+ unaddressed
+ uidlen
) > 1) {
1105 PrintAndLogEx(WARNING
, "Select only one option /scan/unaddress/uid");
1109 // request to be sent to device/card
1110 uint16_t flags
= arg_get_raw_flag(uidlen
, unaddressed
, scan
, add_option
);
1111 uint8_t req
[16] = {flags
, ISO15693_WRITE_AFI
};
1112 uint16_t reqlen
= 2;
1114 if (unaddressed
== false) {
1116 if (getUID(false, uid
) != PM3_SUCCESS
) {
1117 PrintAndLogEx(WARNING
, "no tag found");
1124 // add UID (scan, uid)
1125 memcpy(req
+ reqlen
, uid
, sizeof(uid
));
1126 reqlen
+= sizeof(uid
);
1128 PrintAndLogEx(SUCCESS
, "Using UID... " _GREEN_("%s"), iso15693_sprintUID(NULL
, uid
));
1131 // enforce, since we are writing
1132 req
[0] |= ISO15_REQ_OPTION
;
1134 req
[reqlen
++] = (uint8_t)afi
;
1136 AddCrc15(req
, reqlen
);
1139 // arg: len, speed, recv?
1140 // arg0 (datalen, cmd len? .arg0 == crc?)
1141 // arg1 (speed == 0 == 1 of 256, == 1 == 1 of 4 )
1142 // arg2 (recv == 1 == expect a response)
1143 uint8_t read_respone
= 1;
1145 PacketResponseNG resp
;
1146 clearCommandBuffer();
1147 SendCommandMIX(CMD_HF_ISO15693_COMMAND
, reqlen
, fast
, read_respone
, req
, reqlen
);
1149 if (WaitForResponseTimeout(CMD_ACK
, &resp
, 2000) == false) {
1150 PrintAndLogEx(ERR
, "iso15693 timeout");
1152 return PM3_ETIMEOUT
;
1156 int status
= resp
.oldarg
[0];
1157 if (status
== PM3_ETEAROFF
) {
1161 uint8_t *data
= resp
.data
.asBytes
;
1163 if ((data
[0] & ISO15_RES_ERROR
) == ISO15_RES_ERROR
) {
1164 PrintAndLogEx(ERR
, "iso15693 card returned error %i: %s", data
[0], TagErrorStr(data
[0]));
1165 return PM3_EWRONGANSWER
;
1168 PrintAndLogEx(NORMAL
, "");
1169 PrintAndLogEx(SUCCESS
, "Wrote AFI 0x%02X", afi
);
1173 // Writes the DSFID (Data Storage Format Identifier) of a card
1174 static int CmdHF15WriteDsfid(const char *Cmd
) {
1175 CLIParserContext
*ctx
;
1176 CLIParserInit(&ctx
, "hf 15 writedsfid",
1177 "Write DSFID on card",
1178 "hf 15 writedsfid -* --dsfid 12\n"
1179 "hf 15 writedsfid -u E011223344556677 --dsfid 12"
1182 void *argtable
[6 + 2] = {};
1183 uint8_t arglen
= arg_add_default(argtable
);
1184 argtable
[arglen
++] = arg_int1(NULL
, "dsfid", "<dec>", "DSFID number (0-255)");
1185 argtable
[arglen
++] = arg_param_end
;
1187 CLIExecWithReturn(ctx
, Cmd
, argtable
, false);
1191 CLIGetHexWithReturn(ctx
, 1, uid
, &uidlen
);
1192 bool unaddressed
= arg_get_lit(ctx
, 2);
1193 bool scan
= arg_get_lit(ctx
, 3);
1194 int fast
= (arg_get_lit(ctx
, 4) == false);
1195 bool add_option
= arg_get_lit(ctx
, 5);
1197 int dsfid
= arg_get_int_def(ctx
, 6, 0);
1201 if ((scan
+ unaddressed
+ uidlen
) > 1) {
1202 PrintAndLogEx(WARNING
, "Select only one option /scan/unaddress/uid");
1206 // request to be sent to device/card
1207 uint16_t flags
= arg_get_raw_flag(uidlen
, unaddressed
, scan
, add_option
);
1208 uint8_t req
[16] = {flags
, ISO15693_WRITE_DSFID
};
1209 // enforce, since we are writing
1210 req
[0] |= ISO15_REQ_OPTION
;
1211 uint16_t reqlen
= 2;
1213 if (unaddressed
== false) {
1215 if (getUID(false, uid
) != PM3_SUCCESS
) {
1216 PrintAndLogEx(WARNING
, "no tag found");
1223 // add UID (scan, uid)
1224 memcpy(req
+ reqlen
, uid
, sizeof(uid
));
1225 reqlen
+= sizeof(uid
);
1227 PrintAndLogEx(SUCCESS
, "Using UID... " _GREEN_("%s"), iso15693_sprintUID(NULL
, uid
));
1231 req
[reqlen
++] = (uint8_t)dsfid
;
1233 AddCrc15(req
, reqlen
);
1237 // arg: len, speed, recv?
1238 // arg0 (datalen, cmd len? .arg0 == crc?)
1239 // arg1 (speed == 0 == 1 of 256, == 1 == 1 of 4 )
1240 // arg2 (recv == 1 == expect a response)
1241 uint8_t read_respone
= 1;
1243 PrintAndLogEx(DEBUG
, "cmd %s", sprint_hex(req
, reqlen
));
1244 PacketResponseNG resp
;
1245 clearCommandBuffer();
1246 SendCommandMIX(CMD_HF_ISO15693_COMMAND
, reqlen
, fast
, read_respone
, req
, reqlen
);
1248 if (WaitForResponseTimeout(CMD_ACK
, &resp
, 2000) == false) {
1249 PrintAndLogEx(ERR
, "iso15693 timeout");
1251 return PM3_ETIMEOUT
;
1255 int status
= resp
.oldarg
[0];
1256 if (status
== PM3_ETEAROFF
) {
1260 uint8_t *data
= resp
.data
.asBytes
;
1262 if ((data
[0] & ISO15_RES_ERROR
) == ISO15_RES_ERROR
) {
1263 PrintAndLogEx(ERR
, "iso15693 card returned error %i: %s", data
[0], TagErrorStr(data
[0]));
1264 return PM3_EWRONGANSWER
;
1267 PrintAndLogEx(NORMAL
, "");
1268 PrintAndLogEx(SUCCESS
, "Wrote DSFID 0x%02X", dsfid
);
1272 // Reads all memory pages
1273 // need to write to file
1274 static int CmdHF15Dump(const char *Cmd
) {
1275 CLIParserContext
*ctx
;
1276 CLIParserInit(&ctx
, "hf 15 dump",
1277 "This command dumps the contents of a ISO-15693 tag and save it to file",
1280 "hf 15 dump -u E011223344556677 -f hf-15-my-dump.bin"
1283 void *argtable
[6 + 2] = {};
1284 uint8_t arglen
= arg_add_default(argtable
);
1285 argtable
[arglen
++] = arg_str0("f", "file", "<fn>", "filename of dump"),
1286 argtable
[arglen
++] = arg_param_end
;
1288 CLIExecWithReturn(ctx
, Cmd
, argtable
, true);
1292 CLIGetHexWithReturn(ctx
, 1, uid
, &uidlen
);
1293 bool unaddressed
= arg_get_lit(ctx
, 2);
1294 bool scan
= arg_get_lit(ctx
, 3);
1295 int fast
= (arg_get_lit(ctx
, 4) == false);
1296 bool add_option
= arg_get_lit(ctx
, 5);
1299 char filename
[FILE_PATH_SIZE
] = {0};
1300 CLIParamStrToBuf(arg_get_str(ctx
, 6), (uint8_t *)filename
, FILE_PATH_SIZE
, &fnlen
);
1305 if ((scan
+ unaddressed
+ uidlen
) > 1) {
1306 PrintAndLogEx(WARNING
, "Select only one option /scan/unaddress/uid");
1310 // default fallback to scan for tag.
1311 // overriding unaddress parameter :)
1316 // request to be sent to device/card
1317 uint16_t flags
= arg_get_raw_flag(uidlen
, unaddressed
, scan
, add_option
);
1318 uint8_t req
[13] = {flags
, ISO15693_READBLOCK
};
1319 uint16_t reqlen
= 2;
1322 if (getUID(false, uid
) != PM3_SUCCESS
) {
1323 PrintAndLogEx(WARNING
, "no tag found");
1330 // add UID (scan, uid)
1331 memcpy(req
+ reqlen
, uid
, sizeof(uid
));
1332 reqlen
+= sizeof(uid
);
1334 PrintAndLogEx(SUCCESS
, "Using UID... " _GREEN_("%s"), iso15693_sprintUID(NULL
, uid
));
1336 // detect blocksize from card :)
1338 PrintAndLogEx(SUCCESS
, "Reading memory from tag UID " _YELLOW_("%s"), iso15693_sprintUID(NULL
, uid
));
1342 t15memory_t mem
[256];
1344 uint8_t data
[256 * 4] = {0};
1345 memset(data
, 0, sizeof(data
));
1347 PrintAndLogEx(INFO
, "." NOLF
);
1348 for (int retry
= 0; retry
< 5; retry
++) {
1353 // arg: len, speed, recv?
1354 // arg0 (datalen, cmd len? .arg0 == crc?)
1355 // arg1 (speed == 0 == 1 of 256, == 1 == 1 of 4 )
1356 // arg2 (recv == 1 == expect a response)
1357 uint8_t read_respone
= 1;
1358 PacketResponseNG resp
;
1359 clearCommandBuffer();
1360 SendCommandMIX(CMD_HF_ISO15693_COMMAND
, sizeof(req
), fast
, read_respone
, req
, sizeof(req
));
1362 if (WaitForResponseTimeout(CMD_ACK
, &resp
, 2000)) {
1364 int len
= resp
.oldarg
[0];
1365 if (len
== PM3_ETEAROFF
) {
1369 PrintAndLogEx(NORMAL
, "");
1370 PrintAndLogEx(FAILED
, "iso15693 command failed");
1374 uint8_t *recv
= resp
.data
.asBytes
;
1376 if (CheckCrc15(recv
, len
) == false) {
1377 PrintAndLogEx(NORMAL
, "");
1378 PrintAndLogEx(FAILED
, "crc (" _RED_("fail") ")");
1382 if ((recv
[0] & ISO15_RES_ERROR
) == ISO15_RES_ERROR
) {
1383 PrintAndLogEx(NORMAL
, "");
1384 PrintAndLogEx(FAILED
, "Tag returned Error %i: %s", recv
[1], TagErrorStr(recv
[1]));
1388 mem
[blocknum
].lock
= resp
.data
.asBytes
[0];
1389 memcpy(mem
[blocknum
].block
, resp
.data
.asBytes
+ 1, 4);
1390 memcpy(data
+ (blocknum
* 4), resp
.data
.asBytes
+ 1, 4);
1395 PrintAndLogEx(NORMAL
, "." NOLF
);
1402 PrintAndLogEx(NORMAL
, "");
1403 PrintAndLogEx(INFO
, "block# | data |lck| ascii");
1404 PrintAndLogEx(INFO
, "---------+--------------+---+----------");
1405 for (int i
= 0; i
< blocknum
; i
++) {
1408 sprintf(lck
, _RED_("%d"), mem
[i
].lock
);
1410 sprintf(lck
, "%d", mem
[i
].lock
);
1412 PrintAndLogEx(INFO
, "%3d/0x%02X | %s | %s | %s"
1415 , sprint_hex(mem
[i
].block
, 4)
1417 , sprint_ascii(mem
[i
].block
, 4)
1420 PrintAndLogEx(NORMAL
, "");
1422 // user supplied filename ?
1423 if (strlen(filename
) < 1) {
1424 char *fptr
= filename
;
1425 PrintAndLogEx(INFO
, "Using UID as filename");
1426 fptr
+= snprintf(fptr
, sizeof(filename
), "hf-15-");
1427 FillFileNameByUID(fptr
, SwapEndian64(uid
, sizeof(uid
), 8), "-dump", sizeof(uid
));
1430 size_t datalen
= blocknum
* 4;
1431 saveFile(filename
, ".bin", data
, datalen
);
1432 saveFileEML(filename
, data
, datalen
, 4);
1433 saveFileJSON(filename
, jsf15
, data
, datalen
, NULL
);
1437 static int CmdHF15List(const char *Cmd
) {
1438 return CmdTraceListAlias(Cmd
, "hf 15", "15");
1441 static int CmdHF15Raw(const char *Cmd
) {
1442 CLIParserContext
*ctx
;
1443 CLIParserInit(&ctx
, "hf 15 raw",
1444 "Sends raw bytes over ISO-15693 to card",
1445 "hf 15 raw -c -d 260100 --> add crc\n"
1446 "hf 15 raw -krc -d 260100 --> add crc, keep field on, skip response"
1449 void *argtable
[] = {
1451 arg_lit0("2", NULL
, "use slower '1 out of 256' mode"),
1452 arg_lit0("c", "crc", "calculate and append CRC"),
1453 arg_lit0("k", NULL
, "keep signal field ON after receive"),
1454 arg_lit0("r", NULL
, "do not read response"),
1455 arg_strx1("d", "data", "<hex>", "raw bytes to send"),
1458 CLIExecWithReturn(ctx
, Cmd
, argtable
, false);
1459 int fast
= (arg_get_lit(ctx
, 1) == false);
1460 bool crc
= arg_get_lit(ctx
, 2);
1461 bool keep_field_on
= arg_get_lit(ctx
, 3);
1462 bool read_respone
= (arg_get_lit(ctx
, 4) == false);
1465 CLIGetHexWithReturn(ctx
, 5, data
, &datalen
);
1469 AddCrc15(data
, datalen
);
1473 // arg: len, speed, recv?
1474 // arg0 (datalen, cmd len? .arg0 == crc?)
1475 // arg1 (speed == 0 == 1 of 256, == 1 == 1 of 4 )
1476 // arg2 (recv == 1 == expect a response)
1477 PacketResponseNG resp
;
1478 clearCommandBuffer();
1479 SendCommandMIX(CMD_HF_ISO15693_COMMAND
, datalen
, fast
, read_respone
, data
, datalen
);
1482 if (WaitForResponseTimeout(CMD_ACK
, &resp
, 2000)) {
1483 int len
= resp
.oldarg
[0];
1484 if (len
== PM3_ETEAROFF
) {
1489 PrintAndLogEx(WARNING
, "command failed");
1491 PrintAndLogEx(SUCCESS
, "received %i octets", len
);
1492 PrintAndLogEx(SUCCESS
, "%s", sprint_hex(resp
.data
.asBytes
, len
));
1495 PrintAndLogEx(WARNING
, "timeout while waiting for reply");
1499 if (keep_field_on
== false) {
1506 * Commandline handling: HF15 CMD READMULTI
1507 * Read multiple blocks at once (not all tags support this)
1509 static int CmdHF15Readmulti(const char *Cmd
) {
1510 CLIParserContext
*ctx
;
1511 CLIParserInit(&ctx
, "hf 15 rdmulti",
1512 "Read multiple pages on a ISO-15693 tag ",
1513 "hf 15 rdmulti -* -b 1 --cnt 6 -> read 6 blocks\n"
1514 "hf 15 rdmulti -u E011223344556677 -b 12 --cnt 3 -> read three blocks"
1517 void *argtable
[6 + 3] = {};
1518 uint8_t arglen
= arg_add_default(argtable
);
1519 argtable
[arglen
++] = arg_int1("b", NULL
, "<dec>", "first page number (0-255)");
1520 argtable
[arglen
++] = arg_int1(NULL
, "cnt", "<dec>", "number of pages (1-6)");
1521 argtable
[arglen
++] = arg_param_end
;
1523 CLIExecWithReturn(ctx
, Cmd
, argtable
, false);
1527 CLIGetHexWithReturn(ctx
, 1, uid
, &uidlen
);
1528 bool unaddressed
= arg_get_lit(ctx
, 2);
1529 bool scan
= arg_get_lit(ctx
, 3);
1530 int fast
= (arg_get_lit(ctx
, 4) == false);
1531 bool add_option
= arg_get_lit(ctx
, 5);
1533 int block
= arg_get_int_def(ctx
, 6, 0);
1534 int blockcnt
= arg_get_int_def(ctx
, 7, 0);
1540 PrintAndLogEx(WARNING
, "Page count must be 6 or less (%d)", blockcnt
);
1544 if ((scan
+ unaddressed
+ uidlen
) > 1) {
1545 PrintAndLogEx(WARNING
, "Select only one option /scan/unaddress/uid");
1549 // request to be sent to device/card
1550 uint16_t flags
= arg_get_raw_flag(uidlen
, unaddressed
, scan
, add_option
);
1551 uint8_t req
[PM3_CMD_DATA_SIZE
] = {flags
, ISO15693_READ_MULTI_BLOCK
};
1552 uint16_t reqlen
= 2;
1554 if (unaddressed
== false) {
1556 if (getUID(false, uid
) != PM3_SUCCESS
) {
1557 PrintAndLogEx(WARNING
, "no tag found");
1564 // add UID (scan, uid)
1565 memcpy(req
+ reqlen
, uid
, sizeof(uid
));
1566 reqlen
+= sizeof(uid
);
1568 PrintAndLogEx(SUCCESS
, "Using UID... " _GREEN_("%s"), iso15693_sprintUID(NULL
, uid
));
1570 // add OPTION flag, in order to get lock-info
1571 req
[0] |= ISO15_REQ_OPTION
;
1574 // 1 means 2 pages, ...
1575 if (blockcnt
> 0) blockcnt
--;
1577 req
[reqlen
++] = block
;
1578 req
[reqlen
++] = blockcnt
;
1580 AddCrc15(req
, reqlen
);
1583 uint8_t read_respone
= 1;
1584 PacketResponseNG resp
;
1585 clearCommandBuffer();
1586 SendCommandMIX(CMD_HF_ISO15693_COMMAND
, reqlen
, fast
, read_respone
, req
, reqlen
);
1588 if (WaitForResponseTimeout(CMD_ACK
, &resp
, 2000) == false) {
1589 PrintAndLogEx(FAILED
, "iso15693 card timeout");
1591 return PM3_ETIMEOUT
;
1596 int status
= resp
.oldarg
[0];
1597 if (status
== PM3_ETEAROFF
) {
1602 PrintAndLogEx(FAILED
, "iso15693 card readmulti failed");
1603 return PM3_EWRONGANSWER
;
1606 uint8_t *data
= resp
.data
.asBytes
;
1608 if (CheckCrc15(data
, status
) == false) {
1609 PrintAndLogEx(FAILED
, "crc (" _RED_("fail") ")");
1613 if ((data
[0] & ISO15_RES_ERROR
) == ISO15_RES_ERROR
) {
1614 PrintAndLogEx(FAILED
, "iso15693 card returned error %i: %s", data
[0], TagErrorStr(data
[0]));
1615 return PM3_EWRONGANSWER
;
1620 int stop
= (blockcnt
+ 1) * 5;
1621 int currblock
= block
;
1623 PrintAndLogEx(NORMAL
, "");
1624 PrintAndLogEx(INFO
, " # | data |lck| ascii");
1625 PrintAndLogEx(INFO
, "---------+--------------+---+----------");
1627 for (int i
= start
; i
< stop
; i
+= 5) {
1630 sprintf(lck
, _RED_("%d"), data
[i
]);
1632 sprintf(lck
, "%d", data
[i
]);
1634 PrintAndLogEx(INFO
, "%3d/0x%02X | %s | %s | %s", currblock
, currblock
, sprint_hex(data
+ i
+ 1, 4), lck
, sprint_ascii(data
+ i
+ 1, 4));
1637 PrintAndLogEx(NORMAL
, "");
1642 * Commandline handling: HF15 CMD READ
1643 * Reads a single Block
1645 static int CmdHF15Readblock(const char *Cmd
) {
1646 CLIParserContext
*ctx
;
1647 CLIParserInit(&ctx
, "hf 15 rdbl",
1648 "Read page on ISO-15693 tag",
1649 "hf 15 rdbl -* -b 12\n"
1650 "hf 15 rdbl -u E011223344556677 -b 12"
1653 void *argtable
[6 + 2] = {};
1654 uint8_t arglen
= arg_add_default(argtable
);
1655 argtable
[arglen
++] = arg_int1("b", "blk", "<dec>", "page number (0-255)");
1656 argtable
[arglen
++] = arg_param_end
;
1658 CLIExecWithReturn(ctx
, Cmd
, argtable
, false);
1662 CLIGetHexWithReturn(ctx
, 1, uid
, &uidlen
);
1663 bool unaddressed
= arg_get_lit(ctx
, 2);
1664 bool scan
= arg_get_lit(ctx
, 3);
1665 int fast
= (arg_get_lit(ctx
, 4) == false);
1666 bool add_option
= arg_get_lit(ctx
, 5);
1668 int block
= arg_get_int_def(ctx
, 6, 0);
1672 if ((scan
+ unaddressed
+ uidlen
) > 1) {
1673 PrintAndLogEx(WARNING
, "Select only one option /scan/unaddress/uid");
1677 // default fallback to scan for tag.
1678 // overriding unaddress parameter :)
1683 // request to be sent to device/card
1684 uint16_t flags
= arg_get_raw_flag(uidlen
, unaddressed
, scan
, add_option
);
1685 uint8_t req
[PM3_CMD_DATA_SIZE
] = {flags
, ISO15693_READBLOCK
};
1686 uint16_t reqlen
= 2;
1688 if (unaddressed
== false) {
1690 if (getUID(false, uid
) != PM3_SUCCESS
) {
1691 PrintAndLogEx(WARNING
, "no tag found");
1698 // add UID (scan, uid)
1699 memcpy(req
+ reqlen
, uid
, sizeof(uid
));
1700 reqlen
+= sizeof(uid
);
1702 PrintAndLogEx(SUCCESS
, "Using UID... " _GREEN_("%s"), iso15693_sprintUID(NULL
, uid
));
1704 // add OPTION flag, in order to get lock-info
1705 req
[0] |= ISO15_REQ_OPTION
;
1707 req
[reqlen
++] = (uint8_t)block
;
1709 AddCrc15(req
, reqlen
);
1712 // arg: len, speed, recv?
1713 // arg0 (datalen, cmd len? .arg0 == crc?)
1714 // arg1 (speed == 0 == 1 of 256, == 1 == 1 of 4 )
1715 // arg2 (recv == 1 == expect a response)
1716 uint8_t read_respone
= 1;
1717 PacketResponseNG resp
;
1718 clearCommandBuffer();
1719 SendCommandMIX(CMD_HF_ISO15693_COMMAND
, reqlen
, fast
, read_respone
, req
, reqlen
);
1721 if (WaitForResponseTimeout(CMD_ACK
, &resp
, 2000) == false) {
1722 PrintAndLogEx(ERR
, "iso15693 timeout");
1724 return PM3_ETIMEOUT
;
1729 int status
= resp
.oldarg
[0];
1730 if (status
== PM3_ETEAROFF
) {
1734 PrintAndLogEx(ERR
, "iso15693 command failed");
1735 return PM3_EWRONGANSWER
;
1738 uint8_t *data
= resp
.data
.asBytes
;
1740 if (CheckCrc15(data
, status
) == false) {
1741 PrintAndLogEx(FAILED
, "crc (" _RED_("fail") ")");
1745 if ((data
[0] & ISO15_RES_ERROR
) == ISO15_RES_ERROR
) {
1746 PrintAndLogEx(ERR
, "iso15693 card returned error %i: %s", data
[0], TagErrorStr(data
[0]));
1747 return PM3_EWRONGANSWER
;
1753 sprintf(lck
, _RED_("%d"), data
[1]);
1755 sprintf(lck
, "%d", data
[1]);
1757 PrintAndLogEx(NORMAL
, "");
1758 PrintAndLogEx(INFO
, " #%3d |lck| ascii", block
);
1759 PrintAndLogEx(INFO
, "------------+---+------");
1760 PrintAndLogEx(INFO
, "%s| %s | %s", sprint_hex(data
+ 2, status
- 4), lck
, sprint_ascii(data
+ 2, status
- 4));
1761 PrintAndLogEx(NORMAL
, "");
1765 static int hf_15_write_blk(bool verbose
, bool fast
, uint8_t *req
, uint8_t reqlen
) {
1767 uint8_t read_response
= 1;
1768 clearCommandBuffer();
1769 SendCommandMIX(CMD_HF_ISO15693_COMMAND
, reqlen
, fast
, read_response
, req
, reqlen
);
1770 PacketResponseNG resp
;
1771 if (WaitForResponseTimeout(CMD_ACK
, &resp
, 2000) == false) {
1772 PrintAndLogEx(FAILED
, "iso15693 card timeout, data may be written anyway");
1774 return PM3_ETIMEOUT
;
1778 int status
= resp
.oldarg
[0];
1779 if (status
== PM3_ETEAROFF
) {
1785 PrintAndLogEx(FAILED
, "iso15693 command failed");
1787 return PM3_EWRONGANSWER
;
1790 uint8_t *recv
= resp
.data
.asBytes
;
1791 if (CheckCrc15(recv
, status
) == false) {
1793 PrintAndLogEx(FAILED
, "crc (" _RED_("fail") ")");
1798 if ((recv
[0] & ISO15_RES_ERROR
) == ISO15_RES_ERROR
) {
1800 PrintAndLogEx(ERR
, "iso15693 card returned error %i: %s", recv
[0], TagErrorStr(recv
[0]));
1802 return PM3_EWRONGANSWER
;
1808 * Commandline handling: HF15 CMD WRITE
1809 * Writes a single Block - might run into timeout, even when successful
1811 static int CmdHF15Write(const char *Cmd
) {
1812 CLIParserContext
*ctx
;
1813 CLIParserInit(&ctx
, "hf 15 wrbl",
1814 "Write block on ISO-15693 tag",
1815 "hf 15 wrbl -* -b 12 -d AABBCCDD\n"
1816 "hf 15 wrbl -u E011223344556677 -b 12 -d AABBCCDD"
1819 void *argtable
[6 + 4] = {};
1820 uint8_t arglen
= arg_add_default(argtable
);
1821 argtable
[arglen
++] = arg_int1("b", "blk", "<dec>", "page number (0-255)");
1822 argtable
[arglen
++] = arg_str1("d", "data", "<hex>", "data, 4 bytes");
1823 argtable
[arglen
++] = arg_lit0("v", "verbose", "verbose output");
1824 argtable
[arglen
++] = arg_param_end
;
1825 CLIExecWithReturn(ctx
, Cmd
, argtable
, false);
1829 CLIGetHexWithReturn(ctx
, 1, uid
, &uidlen
);
1830 bool unaddressed
= arg_get_lit(ctx
, 2);
1831 bool scan
= arg_get_lit(ctx
, 3);
1832 int fast
= (arg_get_lit(ctx
, 4) == false);
1833 bool add_option
= arg_get_lit(ctx
, 5);
1835 int block
= arg_get_int_def(ctx
, 6, 0);
1838 CLIGetHexWithReturn(ctx
, 7, d
, &dlen
);
1840 bool verbose
= arg_get_lit(ctx
, 8);
1844 if ((scan
+ unaddressed
+ uidlen
) > 1) {
1845 PrintAndLogEx(WARNING
, "Select only one option /scan/unaddress/uid");
1850 PrintAndLogEx(WARNING
, "expected data, 4 bytes, got %d", dlen
);
1854 // default fallback to scan for tag.
1855 // overriding unaddress parameter :)
1860 // request to be sent to device/card
1861 uint16_t flags
= arg_get_raw_flag(uidlen
, unaddressed
, scan
, add_option
);
1862 uint8_t req
[17] = {flags
, ISO15693_WRITEBLOCK
};
1864 // enforce, since we are writing
1865 req
[0] |= ISO15_REQ_OPTION
;
1866 uint16_t reqlen
= 2;
1868 if (unaddressed
== false) {
1870 if (getUID(false, uid
) != PM3_SUCCESS
) {
1871 PrintAndLogEx(WARNING
, "no tag found");
1878 // add UID (scan, uid)
1879 memcpy(req
+ reqlen
, uid
, sizeof(uid
));
1880 reqlen
+= sizeof(uid
);
1882 PrintAndLogEx(SUCCESS
, "Using UID... " _GREEN_("%s"), iso15693_sprintUID(NULL
, uid
));
1886 req
[reqlen
++] = (uint8_t)block
;
1887 memcpy(req
+ reqlen
, d
, sizeof(d
));
1888 reqlen
+= sizeof(d
);
1890 AddCrc15(req
, reqlen
);
1893 PrintAndLogEx(INFO
, "iso15693 writing to page %02d (0x%02X) | data [ %s ] ", block
, block
, sprint_hex(req
, reqlen
));
1895 int res
= hf_15_write_blk(verbose
, fast
, req
, reqlen
);
1896 if (res
== PM3_SUCCESS
)
1897 PrintAndLogEx(SUCCESS
, "Write ( " _GREEN_("ok") " )");
1899 PrintAndLogEx(FAILED
, "Write ( " _RED_("fail") " )");
1904 static int CmdHF15Restore(const char *Cmd
) {
1905 CLIParserContext
*ctx
;
1906 CLIParserInit(&ctx
, "hf 15 restore",
1907 "This command restore the contents of a dump file onto a ISO-15693 tag",
1909 "hf 15 restore -*\n"
1910 "hf 15 restore -u E011223344556677 -f hf-15-my-dump.bin"
1913 void *argtable
[6 + 5] = {};
1914 uint8_t arglen
= arg_add_default(argtable
);
1915 argtable
[arglen
++] = arg_str0("f", "file", "<fn>", "filename of dump"),
1916 argtable
[arglen
++] = arg_int0("r", "retry", "<dec>", "number of retries (def 3)"),
1917 argtable
[arglen
++] = arg_int0(NULL
, "bs", "<dec>", "block size (def 4)"),
1918 argtable
[arglen
++] = arg_lit0("v", "verbose", "verbose output");
1919 argtable
[arglen
++] = arg_param_end
;
1920 CLIExecWithReturn(ctx
, Cmd
, argtable
, true);
1924 CLIGetHexWithReturn(ctx
, 1, uid
, &uidlen
);
1925 bool unaddressed
= arg_get_lit(ctx
, 2);
1926 bool scan
= arg_get_lit(ctx
, 3);
1927 int fast
= (arg_get_lit(ctx
, 4) == false);
1928 bool add_option
= arg_get_lit(ctx
, 5);
1931 char filename
[FILE_PATH_SIZE
] = {0};
1932 CLIParamStrToBuf(arg_get_str(ctx
, 6), (uint8_t *)filename
, FILE_PATH_SIZE
, &fnlen
);
1933 int retries
= arg_get_int_def(ctx
, 7, 3);
1934 int blocksize
= arg_get_int_def(ctx
, 8, 4);
1935 bool verbose
= arg_get_lit(ctx
, 9);
1939 if ((scan
+ unaddressed
+ uidlen
) > 1) {
1940 PrintAndLogEx(WARNING
, "Select only one option /scan/unaddress/uid");
1944 PrintAndLogEx(WARNING
, "please provide a filename");
1948 // default fallback to scan for tag.
1949 // overriding unaddress parameter :)
1954 // request to be sent to device/card
1955 uint16_t flags
= arg_get_raw_flag(uidlen
, unaddressed
, scan
, add_option
);
1956 uint8_t req
[17] = {flags
, ISO15693_WRITEBLOCK
};
1957 // enforce, since we are writing
1958 req
[0] |= ISO15_REQ_OPTION
;
1959 uint16_t reqlen
= 2;
1961 if (unaddressed
== false) {
1963 if (getUID(false, uid
) != PM3_SUCCESS
) {
1964 PrintAndLogEx(WARNING
, "no tag found");
1971 // add UID (scan, uid)
1972 memcpy(req
+ reqlen
, uid
, sizeof(uid
));
1973 reqlen
+= sizeof(uid
);
1975 PrintAndLogEx(SUCCESS
, "Using UID... " _GREEN_("%s"), iso15693_sprintUID(NULL
, uid
));
1977 PrintAndLogEx(SUCCESS
, "Using unaddressed mode");
1979 PrintAndLogEx(INFO
, "Using block size... %d", blocksize
);
1981 // 4bytes * 256 blocks. Should be enough..
1982 uint8_t *data
= NULL
;
1984 int res
= PM3_SUCCESS
;
1985 DumpFileType_t dftype
= getfiletype(filename
);
1988 res
= loadFile_safe(filename
, ".bin", (void **)&data
, &datalen
);
1992 res
= loadFileEML_safe(filename
, (void **)&data
, &datalen
);
1996 data
= calloc(4 * 256, sizeof(uint8_t));
1998 PrintAndLogEx(WARNING
, "Fail, cannot allocate memory");
2001 res
= loadFileJSON(filename
, (void *)data
, 256 * 4, &datalen
, NULL
);
2005 PrintAndLogEx(ERR
, "Error: Only BIN/JSON/EML formats allowed");
2011 if (res
!= PM3_SUCCESS
) {
2016 if ((datalen
% blocksize
) != 0) {
2017 PrintAndLogEx(WARNING
, "datalen %zu isn't dividable with blocksize %d", datalen
, blocksize
);
2022 PrintAndLogEx(INFO
, "restoring data blocks");
2023 PrintAndLogEx(INFO
, "." NOLF
);
2026 int retval
= PM3_SUCCESS
;
2029 while (bytes
< datalen
) {
2031 req
[reqlen
+ 1] = i
;
2032 // copy over the data to the request
2033 memcpy(req
+ reqlen
+ 1, data
+ bytes
, blocksize
);
2034 AddCrc15(req
, reqlen
+ 1 + blocksize
);
2037 for (tried
= 0; tried
< retries
; tried
++) {
2039 retval
= hf_15_write_blk(verbose
, fast
, req
, (reqlen
+ 1 + blocksize
+ 2));
2040 if (retval
== PM3_SUCCESS
) {
2041 PrintAndLogEx(NORMAL
, "." NOLF
);
2047 if (tried
>= retries
) {
2049 PrintAndLogEx(NORMAL
, "");
2050 PrintAndLogEx(FAILED
, "restore failed. Too many retries.");
2058 PrintAndLogEx(NORMAL
, "");
2059 PrintAndLogEx(INFO
, "done");
2060 PrintAndLogEx(HINT
, "try `" _YELLOW_("hf 15 dump") "` to read your card to verify");
2065 * Commandline handling: HF15 CMD CSETUID
2066 * Set UID for magic Chinese card
2068 static int CmdHF15CSetUID(const char *Cmd
) {
2070 CLIParserContext
*ctx
;
2071 CLIParserInit(&ctx
, "hf 15 csetuid",
2072 "Set UID for magic Chinese card (only works with such cards)\n",
2073 "hf 15 csetuid -u E011223344556677");
2075 void *argtable
[] = {
2077 arg_str1("u", "uid", "<8b hex>", "UID eg E011223344556677"),
2080 CLIExecWithReturn(ctx
, Cmd
, argtable
, false);
2087 CLIGetHexWithReturn(ctx
, 1, payload
.uid
, &uidlen
);
2091 PrintAndLogEx(WARNING
, "UID must include 16 HEX symbols got ");
2095 if (payload
.uid
[0] != 0xE0) {
2096 PrintAndLogEx(WARNING
, "UID must begin with the byte " _YELLOW_("E0"));
2100 PrintAndLogEx(SUCCESS
, "reverse input UID " _YELLOW_("%s"), iso15693_sprintUID(NULL
, payload
.uid
));
2102 PrintAndLogEx(INFO
, "getting current card details...");
2103 uint8_t carduid
[8] = {0x00};
2104 if (getUID(false, carduid
) != PM3_SUCCESS
) {
2105 PrintAndLogEx(FAILED
, "no tag found");
2109 PrintAndLogEx(INFO
, "updating tag uid...");
2111 PacketResponseNG resp
;
2112 clearCommandBuffer();
2113 SendCommandNG(CMD_HF_ISO15693_CSETUID
, (uint8_t *)&payload
, sizeof(payload
));
2114 if (WaitForResponseTimeout(CMD_HF_ISO15693_CSETUID
, &resp
, 2000) == false) {
2115 PrintAndLogEx(WARNING
, "timeout while waiting for reply");
2120 PrintAndLogEx(INFO
, "getting updated card details...");
2122 if (getUID(false, carduid
) != PM3_SUCCESS
) {
2123 PrintAndLogEx(FAILED
, "no tag found");
2127 // reverse cardUID to compare
2128 uint8_t revuid
[8] = {0};
2130 while (i
< sizeof(revuid
)) {
2131 revuid
[i
] = carduid
[7 - i
];
2135 if (memcmp(revuid
, payload
.uid
, 8) != 0) {
2136 PrintAndLogEx(FAILED
, "setting new UID (" _RED_("failed") ")");
2139 PrintAndLogEx(SUCCESS
, "setting new UID (" _GREEN_("ok") ")");
2144 static int CmdHF15SlixDisable(const char *Cmd
) {
2146 CLIParserContext
*ctx
;
2147 CLIParserInit(&ctx
, "hf 15 slixdisable",
2148 "Disable privacy mode on SLIX ISO-15693 tag",
2149 "hf 15 slixdisable -p 0F0F0F0F");
2151 void *argtable
[] = {
2153 arg_str1("p", "pwd", "<hex>", "password, 8 hex bytes"),
2156 CLIExecWithReturn(ctx
, Cmd
, argtable
, false);
2161 CLIGetHexWithReturn(ctx
, 1, payload
.pwd
, &pwdlen
);
2164 PrintAndLogEx(INFO
, "Trying to disabling privacy mode using password " _GREEN_("%s")
2165 , sprint_hex_inrow(payload
.pwd
, sizeof(payload
.pwd
))
2168 PacketResponseNG resp
;
2169 clearCommandBuffer();
2170 SendCommandNG(CMD_HF_ISO15693_SLIX_L_DISABLE_PRIVACY
, (uint8_t *)&payload
, sizeof(payload
));
2171 if (WaitForResponseTimeout(CMD_HF_ISO15693_SLIX_L_DISABLE_PRIVACY
, &resp
, 2000) == false) {
2172 PrintAndLogEx(WARNING
, "timeout while waiting for reply");
2177 switch (resp
.status
) {
2178 case PM3_ETIMEOUT
: {
2179 PrintAndLogEx(WARNING
, "no tag found");
2182 case PM3_EWRONGANSWER
: {
2183 PrintAndLogEx(WARNING
, "password was not accepted");
2187 PrintAndLogEx(SUCCESS
, "privacy mode is now disabled ( " _GREEN_("ok") " ) ");
2194 static command_t CommandTable
[] = {
2195 {"-----------", CmdHF15Help
, AlwaysAvailable
, "--------------------- " _CYAN_("General") " ---------------------"},
2196 {"help", CmdHF15Help
, AlwaysAvailable
, "This help"},
2197 {"list", CmdHF15List
, AlwaysAvailable
, "List ISO-15693 history"},
2198 {"demod", CmdHF15Demod
, AlwaysAvailable
, "Demodulate ISO-15693 from tag"},
2199 {"dump", CmdHF15Dump
, IfPm3Iso15693
, "Read all memory pages of an ISO-15693 tag, save to file"},
2200 {"info", CmdHF15Info
, IfPm3Iso15693
, "Tag information"},
2201 {"sniff", CmdHF15Sniff
, IfPm3Iso15693
, "Sniff ISO-15693 traffic"},
2202 {"raw", CmdHF15Raw
, IfPm3Iso15693
, "Send raw hex data to tag"},
2203 {"rdbl", CmdHF15Readblock
, IfPm3Iso15693
, "Read a block"},
2204 {"rdmulti", CmdHF15Readmulti
, IfPm3Iso15693
, "Reads multiple blocks"},
2205 {"reader", CmdHF15Reader
, IfPm3Iso15693
, "Act like an ISO-15693 reader"},
2206 {"restore", CmdHF15Restore
, IfPm3Iso15693
, "Restore from file to all memory pages of an ISO-15693 tag"},
2207 {"samples", CmdHF15Samples
, IfPm3Iso15693
, "Acquire samples as reader (enables carrier, sends inquiry)"},
2208 {"sim", CmdHF15Sim
, IfPm3Iso15693
, "Fake an ISO-15693 tag"},
2209 {"slixdisable", CmdHF15SlixDisable
, IfPm3Iso15693
, "Disable privacy mode on SLIX ISO-15693 tag"},
2210 {"wrbl", CmdHF15Write
, IfPm3Iso15693
, "Write a block"},
2211 {"-----------", CmdHF15Help
, IfPm3Iso15693
, "----------------------- " _CYAN_("afi") " -----------------------"},
2212 {"findafi", CmdHF15FindAfi
, IfPm3Iso15693
, "Brute force AFI of an ISO-15693 tag"},
2213 {"writeafi", CmdHF15WriteAfi
, IfPm3Iso15693
, "Writes the AFI on an ISO-15693 tag"},
2214 {"writedsfid", CmdHF15WriteDsfid
, IfPm3Iso15693
, "Writes the DSFID on an ISO-15693 tag"},
2215 {"-----------", CmdHF15Help
, IfPm3Iso15693
, "----------------------- " _CYAN_("magic") " -----------------------"},
2216 {"csetuid", CmdHF15CSetUID
, IfPm3Iso15693
, "Set UID for magic card"},
2217 {NULL
, NULL
, NULL
, NULL
}
2220 static int CmdHF15Help(const char *Cmd
) {
2221 (void)Cmd
; // Cmd is not used so far
2222 CmdsHelp(CommandTable
);
2226 int CmdHF15(const char *Cmd
) {
2227 clearCommandBuffer();
2228 return CmdsParse(CommandTable
, Cmd
);