MIFARE Plus 4b UID: fix signature check
[RRG-proxmark3.git] / armsrc / iclass.c
blobec6578ded0efe3201cc6271c55a11786361d3241
1 //-----------------------------------------------------------------------------
2 // Copyright (C) Gerhard de Koning Gans - May 2008
3 // Contribution made during a security research at Radboud University Nijmegen
4 // Copyright (C) Proxmark3 contributors. See AUTHORS.md for details.
5 //
6 // This program is free software: you can redistribute it and/or modify
7 // it under the terms of the GNU General Public License as published by
8 // the Free Software Foundation, either version 3 of the License, or
9 // (at your option) any later version.
11 // This program is distributed in the hope that it will be useful,
12 // but WITHOUT ANY WARRANTY; without even the implied warranty of
13 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 // GNU General Public License for more details.
16 // See LICENSE.txt for the text of the license.
17 //-----------------------------------------------------------------------------
18 // Routines to support iClass.
19 //-----------------------------------------------------------------------------
20 #include "iclass.h"
22 #include "proxmark3_arm.h"
23 #include "cmd.h"
24 // Needed for CRC in emulation mode;
25 // same construction as in ISO 14443;
26 // different initial value (CRC_ICLASS)
27 #include "crc16.h"
28 #include "optimized_cipher.h"
30 #include "appmain.h"
31 #include "BigBuf.h"
32 #include "fpgaloader.h"
33 #include "string.h"
34 #include "util.h"
35 #include "dbprint.h"
36 #include "protocols.h"
37 #include "ticks.h"
38 #include "iso15693.h"
39 #include "iclass_cmd.h" // iclass_card_select_t struct
40 #include "i2c.h" // i2c defines (SIM module access)
42 uint8_t get_pagemap(const picopass_hdr_t *hdr) {
43 return (hdr->conf.fuses & (FUSE_CRYPT0 | FUSE_CRYPT1)) >> 3;
47 #ifndef ICLASS_16KS_SIZE
48 #define ICLASS_16KS_SIZE 0x100 * 8
49 #endif
52 * CARD TO READER
53 * in ISO15693-2 mode - Manchester
54 * in ISO 14443b - BPSK coding
56 * Timings:
57 * ISO 15693-2
58 * Tout = 330 µs, Tprog 1 = 4 to 15 ms, Tslot = 330 µs + (number of slots x 160 µs)
59 * ISO 14443a
60 * Tout = 100 µs, Tprog = 4 to 15 ms, Tslot = 100 µs+ (number of slots x 80 µs)
61 * ISO 14443b
62 Tout = 76 µs, Tprog = 4 to 15 ms, Tslot = 119 µs+ (number of slots x 150 µs)
65 * So for current implementation in ISO15693, its 330 µs from end of reader, to start of card.
68 //=============================================================================
69 // a `sniffer' for iClass communication
70 // Both sides of communication!
71 //=============================================================================
72 void SniffIClass(uint8_t jam_search_len, uint8_t *jam_search_string) {
73 SniffIso15693(jam_search_len, jam_search_string, true);
76 static void rotateCSN(const uint8_t *original_csn, uint8_t *rotated_csn) {
77 for (uint8_t i = 0; i < 8; i++) {
78 rotated_csn[i] = (original_csn[i] >> 3) | (original_csn[(i + 1) % 8] << 5);
82 // Encode SOF only
83 static void CodeIClassTagSOF(void) {
84 tosend_reset();
85 tosend_t *ts = get_tosend();
86 ts->buf[++ts->max] = 0x1D;
87 ts->max++;
91 * SOF comprises 3 parts;
92 * * An unmodulated time of 56.64 us
93 * * 24 pulses of 423.75 kHz (fc/32)
94 * * A logic 1, which starts with an unmodulated time of 18.88us
95 * followed by 8 pulses of 423.75kHz (fc/32)
98 * EOF comprises 3 parts:
99 * - A logic 0 (which starts with 8 pulses of fc/32 followed by an unmodulated
100 * time of 18.88us.
101 * - 24 pulses of fc/32
102 * - An unmodulated time of 56.64 us
105 * A logic 0 starts with 8 pulses of fc/32
106 * followed by an unmodulated time of 256/fc (~18,88us).
108 * A logic 0 starts with unmodulated time of 256/fc (~18,88us) followed by
109 * 8 pulses of fc/32 (also 18.88us)
111 * The mode FPGA_HF_SIMULATOR_MODULATE_424K_8BIT which we use to simulate tag,
112 * works like this.
113 * - A 1-bit input to the FPGA becomes 8 pulses on 423.5kHz (fc/32) (18.88us).
114 * - A 0-bit input to the FPGA becomes an unmodulated time of 18.88us
116 * In this mode
117 * SOF can be written as 00011101 = 0x1D
118 * EOF can be written as 10111000 = 0xb8
119 * logic 1 be written as 01 = 0x1
120 * logic 0 be written as 10 = 0x2
126 * @brief SimulateIClass simulates an iClass card.
127 * @param arg0 type of simulation
128 * - 0 uses the first 8 bytes in usb data as CSN
129 * - 2 "dismantling iclass"-attack. This mode iterates through all CSN's specified
130 * in the usb data. This mode collects MAC from the reader, in order to do an offline
131 * attack on the keys. For more info, see "dismantling iclass" and proxclone.com.
132 * - Other : Uses the default CSN (031fec8af7ff12e0)
133 * @param arg1 - number of CSN's contained in datain (applicable for mode 2 only)
134 * @param arg2
135 * @param datain
137 // turn off afterwards
138 void SimulateIClass(uint32_t arg0, uint32_t arg1, uint32_t arg2, uint8_t *datain) {
139 iclass_simulate(arg0, arg1, arg2, datain, NULL, NULL);
142 void iclass_simulate(uint8_t sim_type, uint8_t num_csns, bool send_reply, uint8_t *datain, uint8_t *dataout, uint16_t *dataoutlen) {
144 LEDsoff();
146 Iso15693InitTag();
148 clear_trace();
150 // only logg if we are called from the client.
151 set_tracing(send_reply);
153 //Use the emulator memory for SIM
154 uint8_t *emulator = BigBuf_get_EM_addr();
155 uint8_t mac_responses[PM3_CMD_DATA_SIZE] = { 0 };
157 if (sim_type == ICLASS_SIM_MODE_CSN) {
158 // Use the CSN from commandline
159 memcpy(emulator, datain, 8);
160 do_iclass_simulation(ICLASS_SIM_MODE_CSN, NULL);
162 } else if (sim_type == ICLASS_SIM_MODE_CSN_DEFAULT) {
163 //Default CSN
164 uint8_t csn[] = { 0x03, 0x1f, 0xec, 0x8a, 0xf7, 0xff, 0x12, 0xe0 };
165 // Use the CSN from commandline
166 memcpy(emulator, csn, 8);
167 do_iclass_simulation(ICLASS_SIM_MODE_CSN, NULL);
169 } else if (sim_type == ICLASS_SIM_MODE_READER_ATTACK) {
171 Dbprintf("going into attack mode, %d CSNS sent", num_csns);
172 // In this mode, a number of csns are within datain. We'll simulate each one, one at a time
173 // in order to collect MAC's from the reader. This can later be used in an offlne-attack
174 // in order to obtain the keys, as in the "dismantling iclass"-paper.
175 #define EPURSE_MAC_SIZE 16
176 int i = 0;
177 for (; i < num_csns && i * EPURSE_MAC_SIZE + 8 < PM3_CMD_DATA_SIZE; i++) {
179 memcpy(emulator, datain + (i * 8), 8);
181 if (do_iclass_simulation(ICLASS_SIM_MODE_EXIT_AFTER_MAC, mac_responses + i * EPURSE_MAC_SIZE)) {
183 if (dataoutlen)
184 *dataoutlen = i * EPURSE_MAC_SIZE;
186 // Button pressed
187 if (send_reply)
188 reply_old(CMD_ACK, CMD_HF_ICLASS_SIMULATE, i, 0, mac_responses, i * EPURSE_MAC_SIZE);
189 goto out;
192 if (dataoutlen)
193 *dataoutlen = i * EPURSE_MAC_SIZE;
195 if (send_reply)
196 reply_old(CMD_ACK, CMD_HF_ICLASS_SIMULATE, i, 0, mac_responses, i * EPURSE_MAC_SIZE);
198 } else if (sim_type == ICLASS_SIM_MODE_FULL) {
200 //This is 'full sim' mode, where we use the emulator storage for data.
201 //ie: BigBuf_get_EM_addr should be previously filled with data from the "eload" command
202 picopass_hdr_t *hdr = (picopass_hdr_t *)BigBuf_get_EM_addr();
203 uint8_t pagemap = get_pagemap(hdr);
204 if (pagemap == PICOPASS_NON_SECURE_PAGEMODE) {
205 do_iclass_simulation_nonsec();
206 } else {
207 do_iclass_simulation(ICLASS_SIM_MODE_FULL, NULL);
210 if (send_reply) {
211 reply_mix(CMD_ACK, CMD_HF_ICLASS_SIMULATE, 0, 0, NULL, 0);
214 } else if (sim_type == ICLASS_SIM_MODE_CONFIG_CARD) {
216 // config card
217 do_iclass_simulation(ICLASS_SIM_MODE_FULL, NULL);
218 // swap bin
220 } else if (sim_type == ICLASS_SIM_MODE_READER_ATTACK_KEYROLL) {
222 // This is the KEYROLL version of sim 2.
223 // the collected data (mac_response) is doubled out since we are trying to collect both keys in the keyroll process.
224 // Keyroll iceman 9 csns * 8 * 2 = 144
225 // keyroll CARL55 15csns * 8 * 2 = 15 * 8 * 2 = 240
226 Dbprintf("going into attack keyroll mode, %d CSNS sent", num_csns);
227 // In this mode, a number of csns are within datain. We'll simulate each one, one at a time
228 // in order to collect MAC's from the reader. This can later be used in an offlne-attack
229 // in order to obtain the keys, as in the "dismantling iclass"-paper.
231 // keyroll mode, reader swaps between old key and new key alternatively when fail a authentication.
232 // attack below is same as SIM 2, but we run the CSN twice to collected the mac for both keys.
233 int i = 0;
234 // The usb data is 512 bytes, fitting 65 8-byte CSNs in there. iceman fork uses 9 CSNS
235 for (; i < num_csns && i * EPURSE_MAC_SIZE + 8 < PM3_CMD_DATA_SIZE; i++) {
237 memcpy(emulator, datain + (i * 8), 8);
239 // keyroll 1
240 if (do_iclass_simulation(ICLASS_SIM_MODE_EXIT_AFTER_MAC, mac_responses + i * EPURSE_MAC_SIZE)) {
242 if (dataoutlen)
243 *dataoutlen = i * EPURSE_MAC_SIZE * 2;
245 if (send_reply)
246 reply_old(CMD_ACK, CMD_HF_ICLASS_SIMULATE, i * 2, 0, mac_responses, i * EPURSE_MAC_SIZE * 2);
248 // Button pressed
249 goto out;
252 // keyroll 2
253 if (do_iclass_simulation(ICLASS_SIM_MODE_EXIT_AFTER_MAC, mac_responses + (i + num_csns) * EPURSE_MAC_SIZE)) {
255 if (dataoutlen)
256 *dataoutlen = i * EPURSE_MAC_SIZE * 2;
258 if (send_reply)
259 reply_old(CMD_ACK, CMD_HF_ICLASS_SIMULATE, i * 2, 0, mac_responses, i * EPURSE_MAC_SIZE * 2);
261 // Button pressed
262 goto out;
266 if (dataoutlen)
267 *dataoutlen = i * EPURSE_MAC_SIZE * 2;
269 // double the amount of collected data.
270 if (send_reply)
271 reply_old(CMD_ACK, CMD_HF_ICLASS_SIMULATE, i * 2, 0, mac_responses, i * EPURSE_MAC_SIZE * 2);
273 } else {
274 // We may want a mode here where we hardcode the csns to use (from proxclone).
275 // That will speed things up a little, but not required just yet.
276 DbpString("the mode is not implemented, reserved for future use");
279 out:
280 if (dataout && dataoutlen)
281 memcpy(dataout, mac_responses, *dataoutlen);
283 switch_off();
284 BigBuf_free_keep_EM();
288 * Simulation assumes a SECURE PAGE simulation with authentication and application areas.
291 * @brief Does the actual simulation
292 * @param csn - csn to use
293 * @param breakAfterMacReceived if true, returns after reader MAC has been received.
295 int do_iclass_simulation(int simulationMode, uint8_t *reader_mac_buf) {
297 // free eventually allocated BigBuf memory
298 BigBuf_free_keep_EM();
300 uint16_t page_size = 32 * 8;
301 uint8_t current_page = 0;
303 // maintain cipher states for both credit and debit key for each page
304 State_t cipher_state_KD[8];
305 State_t cipher_state_KC[8];
306 State_t *cipher_state = &cipher_state_KD[0];
308 uint8_t *emulator = BigBuf_get_EM_addr();
309 uint8_t *csn = emulator;
311 // CSN followed by two CRC bytes
312 uint8_t anticoll_data[10] = { 0 };
313 uint8_t csn_data[10] = { 0 };
314 memcpy(csn_data, csn, sizeof(csn_data));
316 // Construct anticollision-CSN
317 rotateCSN(csn_data, anticoll_data);
319 // Compute CRC on both CSNs
320 AddCrc(anticoll_data, 8);
321 AddCrc(csn_data, 8);
323 uint8_t diversified_kd[8] = { 0 };
324 uint8_t diversified_kc[8] = { 0 };
325 uint8_t *diversified_key = diversified_kd;
327 // configuration block
328 uint8_t conf_block[10] = {0x12, 0xFF, 0xFF, 0xFF, 0x7F, 0x1F, 0xFF, 0x3C, 0x00, 0x00};
330 // e-Purse
331 uint8_t card_challenge_data[8] = { 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
333 // AIA
334 uint8_t aia_data[10] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00};
336 if (simulationMode == ICLASS_SIM_MODE_FULL) {
338 memcpy(conf_block, emulator + (8 * 1), 8); // blk 1
339 memcpy(card_challenge_data, emulator + (8 * 2), 8); // e-purse, blk 2
340 memcpy(diversified_kd, emulator + (8 * 3), 8); // Kd, blk 3
341 memcpy(diversified_kc, emulator + (8 * 4), 8); // Kc, blk 4
343 // (iceman) this only works for 2KS / 16KS tags.
344 // Use application data from block 5
345 memcpy(aia_data, emulator + (8 * 5), 8);
348 AddCrc(conf_block, 8);
349 AddCrc(aia_data, 8);
351 // set epurse of sim2,4 attack
352 if (reader_mac_buf != NULL) {
353 memcpy(reader_mac_buf, card_challenge_data, 8);
356 if ((conf_block[5] & 0x80) == 0x80) {
357 page_size = 256 * 8;
360 // From PicoPass DS:
361 // When the page is in personalization mode this bit is equal to 1.
362 // Once the application issuer has personalized and coded its dedicated areas, this bit must be set to 0:
363 // the page is then "in application mode".
364 bool personalization_mode = conf_block[7] & 0x80;
366 uint8_t block_wr_lock = conf_block[3];
368 // chip memory may be divided in 8 pages
369 uint8_t max_page = ((conf_block[4] & 0x10) == 0x10) ? 0 : 7;
371 // pre-calculate the cipher states, feeding it the CC
372 cipher_state_KD[0] = opt_doTagMAC_1(card_challenge_data, diversified_kd);
373 cipher_state_KC[0] = opt_doTagMAC_1(card_challenge_data, diversified_kc);
375 if (simulationMode == ICLASS_SIM_MODE_FULL) {
377 for (int i = 1; i < max_page; i++) {
379 uint8_t *epurse = emulator + (i * page_size) + (8 * 2);
380 uint8_t *kd = emulator + (i * page_size) + (8 * 3);
381 uint8_t *kc = emulator + (i * page_size) + (8 * 4);
383 cipher_state_KD[i] = opt_doTagMAC_1(epurse, kd);
384 cipher_state_KC[i] = opt_doTagMAC_1(epurse, kc);
388 // Anti-collision process:
389 // Reader 0a
390 // Tag 0f
391 // Reader 0c
392 // Tag anticoll. CSN
393 // Reader 81 anticoll. CSN
394 // Tag CSN
396 uint8_t *modulated_response = NULL;
397 int modulated_response_size;
398 uint8_t *trace_data = NULL;
399 int trace_data_size;
401 // Respond SOF -- takes 1 bytes
402 uint8_t *resp_sof = BigBuf_malloc(1);
403 int resp_sof_len;
405 // Anticollision CSN (rotated CSN)
406 // 22: Takes 2 bytes for SOF/EOF and 10 * 2 = 20 bytes (2 bytes/byte)
407 uint8_t *resp_anticoll = BigBuf_malloc(22);
408 int resp_anticoll_len;
410 // CSN (block 0)
411 // 22: Takes 2 bytes for SOF/EOF and 10 * 2 = 20 bytes (2 bytes/byte)
412 uint8_t *resp_csn = BigBuf_malloc(22);
413 int resp_csn_len;
415 // configuration (blk 1) PICOPASS 2ks
416 uint8_t *resp_conf = BigBuf_malloc(22);
417 int resp_conf_len;
419 // e-Purse (blk 2)
420 // 18: Takes 2 bytes for SOF/EOF and 8 * 2 = 16 bytes (2 bytes/bit)
421 uint8_t *resp_cc = BigBuf_malloc(18);
422 int resp_cc_len;
424 // Kd, Kc (blocks 3 and 4). Cannot be read. Always respond with 0xff bytes only
425 uint8_t *resp_ff = BigBuf_malloc(22);
426 int resp_ff_len;
427 uint8_t ff_data[10] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00};
428 AddCrc(ff_data, 8);
430 // Application Issuer Area (blk 5)
431 uint8_t *resp_aia = BigBuf_malloc(22);
432 int resp_aia_len;
434 // receive command
435 uint8_t *receivedCmd = BigBuf_malloc(MAX_FRAME_SIZE);
437 // Prepare card messages
438 tosend_t *ts = get_tosend();
440 // First card answer: SOF
441 CodeIClassTagSOF();
442 memcpy(resp_sof, ts->buf, ts->max);
443 resp_sof_len = ts->max;
445 // Anticollision CSN
446 CodeIso15693AsTag(anticoll_data, sizeof(anticoll_data));
447 memcpy(resp_anticoll, ts->buf, ts->max);
448 resp_anticoll_len = ts->max;
450 // CSN (block 0)
451 CodeIso15693AsTag(csn_data, sizeof(csn_data));
452 memcpy(resp_csn, ts->buf, ts->max);
453 resp_csn_len = ts->max;
455 // Configuration (block 1)
456 CodeIso15693AsTag(conf_block, sizeof(conf_block));
457 memcpy(resp_conf, ts->buf, ts->max);
458 resp_conf_len = ts->max;
460 // e-Purse (block 2)
461 CodeIso15693AsTag(card_challenge_data, sizeof(card_challenge_data));
462 memcpy(resp_cc, ts->buf, ts->max);
463 resp_cc_len = ts->max;
465 // Kd, Kc (blocks 3 and 4)
466 CodeIso15693AsTag(ff_data, sizeof(ff_data));
467 memcpy(resp_ff, ts->buf, ts->max);
468 resp_ff_len = ts->max;
470 // Application Issuer Area (block 5)
471 CodeIso15693AsTag(aia_data, sizeof(aia_data));
472 memcpy(resp_aia, ts->buf, ts->max);
473 resp_aia_len = ts->max;
475 //This is used for responding to READ-block commands or other data which is dynamically generated
476 //First the 'trace'-data, not encoded for FPGA
477 uint8_t *data_generic_trace = BigBuf_malloc(34); // 32 bytes data + 2byte CRC is max tag answer
479 //Then storage for the modulated data
480 //Each bit is doubled when modulated for FPGA, and we also have SOF and EOF (2 bytes)
481 uint8_t *data_response = BigBuf_malloc((34 * 2) + 3);
483 enum { IDLE, ACTIVATED, SELECTED, HALTED } chip_state = IDLE;
485 bool button_pressed = false;
486 uint8_t cmd, options, block;
487 int len, kc_attempt = 0;
488 bool exit_loop = false;
489 bool using_kc = false;
491 while (exit_loop == false) {
492 WDT_HIT();
494 // Now look at the reader command and provide appropriate responses
495 // default is no response:
496 modulated_response = NULL;
497 modulated_response_size = 0;
498 trace_data = NULL;
499 trace_data_size = 0;
501 uint32_t reader_eof_time = 0;
502 len = GetIso15693CommandFromReader(receivedCmd, MAX_FRAME_SIZE, &reader_eof_time);
503 if (len < 0) {
504 button_pressed = true;
505 exit_loop = true;
506 continue;
509 // extra response data
510 cmd = receivedCmd[0] & 0xF;
511 options = (receivedCmd[0] >> 4) & 0xFF;
512 block = receivedCmd[1];
514 if (cmd == ICLASS_CMD_ACTALL && len == 1) { // 0x0A
515 // Reader in anti collision phase
516 modulated_response = resp_sof;
517 modulated_response_size = resp_sof_len;
518 chip_state = ACTIVATED;
519 goto send;
521 } else if (cmd == ICLASS_CMD_READ_OR_IDENTIFY && len == 1) { // 0x0C
522 // Reader asks for anti collision CSN
523 if (chip_state == SELECTED || chip_state == ACTIVATED) {
524 modulated_response = resp_anticoll;
525 modulated_response_size = resp_anticoll_len;
526 trace_data = anticoll_data;
527 trace_data_size = sizeof(anticoll_data);
529 goto send;
531 } else if (cmd == ICLASS_CMD_SELECT && len == 9) {
532 // Reader selects anticollision CSN.
533 // Tag sends the corresponding real CSN
534 if (chip_state == ACTIVATED || chip_state == SELECTED) {
535 if (!memcmp(receivedCmd + 1, anticoll_data, 8)) {
536 modulated_response = resp_csn;
537 modulated_response_size = resp_csn_len;
538 trace_data = csn_data;
539 trace_data_size = sizeof(csn_data);
540 chip_state = SELECTED;
541 } else {
542 chip_state = IDLE;
544 } else if (chip_state == HALTED || chip_state == IDLE) {
545 // RESELECT with CSN
546 if (!memcmp(receivedCmd + 1, csn_data, 8)) {
547 modulated_response = resp_csn;
548 modulated_response_size = resp_csn_len;
549 trace_data = csn_data;
550 trace_data_size = sizeof(csn_data);
551 chip_state = SELECTED;
554 goto send;
557 } else if (cmd == ICLASS_CMD_READ_OR_IDENTIFY && len == 4) { // 0x0C
559 if (chip_state != SELECTED) {
560 goto send;
562 if (simulationMode == ICLASS_SIM_MODE_EXIT_AFTER_MAC) {
563 // provide defaults for blocks 0 ... 5
565 // block0,1,2,5 is always readable.
566 switch (block) {
567 case 0: { // csn (0c 00)
568 modulated_response = resp_csn;
569 modulated_response_size = resp_csn_len;
570 trace_data = csn_data;
571 trace_data_size = sizeof(csn_data);
572 goto send;
574 case 1: { // configuration (0c 01)
575 modulated_response = resp_conf;
576 modulated_response_size = resp_conf_len;
577 trace_data = conf_block;
578 trace_data_size = sizeof(conf_block);
579 goto send;
581 case 2: {// e-purse (0c 02)
582 modulated_response = resp_cc;
583 modulated_response_size = resp_cc_len;
584 trace_data = card_challenge_data;
585 trace_data_size = sizeof(card_challenge_data);
586 // set epurse of sim2,4 attack
587 if (reader_mac_buf != NULL) {
588 memcpy(reader_mac_buf, card_challenge_data, 8);
590 goto send;
592 case 3:
593 case 4: { // Kd, Kc, always respond with 0xff bytes
594 modulated_response = resp_ff;
595 modulated_response_size = resp_ff_len;
596 trace_data = ff_data;
597 trace_data_size = sizeof(ff_data);
598 goto send;
600 case 5: { // Application Issuer Area (0c 05)
601 modulated_response = resp_aia;
602 modulated_response_size = resp_aia_len;
603 trace_data = aia_data;
604 trace_data_size = sizeof(aia_data);
605 goto send;
607 } // switch
608 } else if (simulationMode == ICLASS_SIM_MODE_FULL) {
609 if (block == 3 || block == 4) { // Kd, Kc, always respond with 0xff bytes
610 modulated_response = resp_ff;
611 modulated_response_size = resp_ff_len;
612 trace_data = ff_data;
613 trace_data_size = sizeof(ff_data);
614 } else { // use data from emulator memory
615 memcpy(data_generic_trace, emulator + (current_page * page_size) + (block * 8), 8);
616 AddCrc(data_generic_trace, 8);
617 trace_data = data_generic_trace;
618 trace_data_size = 10;
619 CodeIso15693AsTag(trace_data, trace_data_size);
620 memcpy(data_response, ts->buf, ts->max);
621 modulated_response = data_response;
622 modulated_response_size = ts->max;
624 goto send;
627 } else if (cmd == ICLASS_CMD_READCHECK && block == 0x02 && len == 2) { // 0x88
628 // Read e-purse KD (88 02) KC (18 02)
629 if (chip_state != SELECTED) {
630 goto send;
633 // debit key
634 if (receivedCmd[0] == 0x88) {
635 cipher_state = &cipher_state_KD[current_page];
636 diversified_key = diversified_kd;
637 using_kc = false;
638 } else {
639 cipher_state = &cipher_state_KC[current_page];
640 diversified_key = diversified_kc;
641 using_kc = true;
644 modulated_response = resp_cc;
645 modulated_response_size = resp_cc_len;
646 trace_data = card_challenge_data;
647 trace_data_size = sizeof(card_challenge_data);
648 goto send;
650 } else if (cmd == ICLASS_CMD_CHECK && len == 9) { // 0x05
652 // Reader random and reader MAC!!!
653 if (chip_state != SELECTED) {
654 goto send;
657 if (simulationMode == ICLASS_SIM_MODE_FULL) {
658 // NR, from reader, is in receivedCmd +1
659 opt_doTagMAC_2(*cipher_state, receivedCmd + 1, data_generic_trace, diversified_key);
662 uint8_t _mac[4] = {0};
663 opt_doReaderMAC_2(*cipher_state, receivedCmd + 1, _mac, diversified_key);
665 if (_mac[0] != receivedCmd[5] || _mac[1] != receivedCmd[6] || _mac[2] != receivedCmd[7] || _mac[3] != receivedCmd[8]) {
666 Dbprintf("reader auth " _RED_("failed"));
667 Dbprintf("hf iclass lookup --csn %02x%02x%02x%02x%02x%02x%02x%02x --epurse %02x%02x%02x%02x%02x%02x%02x%02x --macs %02x%02x%02x%02x%02x%02x%02x%02x f iclass_default_keys.dic",
668 csn_data[0], csn_data[1], csn_data[2], csn_data[3], csn_data[4], csn_data[5], csn_data[6], csn_data[7],
669 card_challenge_data[0], card_challenge_data[1], card_challenge_data[2], card_challenge_data[3],
670 card_challenge_data[4], card_challenge_data[5], card_challenge_data[6], card_challenge_data[7],
671 receivedCmd[1], receivedCmd[2], receivedCmd[3], receivedCmd[4],
672 receivedCmd[5], receivedCmd[6], receivedCmd[7], receivedCmd[8]
675 goto send;
679 trace_data = data_generic_trace;
680 trace_data_size = 4;
681 CodeIso15693AsTag(trace_data, trace_data_size);
682 memcpy(data_response, ts->buf, ts->max);
683 modulated_response = data_response;
684 modulated_response_size = ts->max;
686 if (using_kc)
687 kc_attempt++;
689 } else {
690 // Not fullsim, we don't respond
691 chip_state = HALTED;
693 if (simulationMode == ICLASS_SIM_MODE_EXIT_AFTER_MAC) {
695 if (g_dbglevel == DBG_EXTENDED) {
696 Dbprintf("CSN: %02x %02x %02x %02x %02x %02x %02x %02x", csn[0], csn[1], csn[2], csn[3], csn[4], csn[5], csn[6], csn[7]);
697 Dbprintf("RDR: (len=%02d): %02x %02x %02x %02x %02x %02x %02x %02x %02x", len,
698 receivedCmd[0], receivedCmd[1], receivedCmd[2],
699 receivedCmd[3], receivedCmd[4], receivedCmd[5],
700 receivedCmd[6], receivedCmd[7], receivedCmd[8]);
701 } else {
702 Dbprintf("CSN: %02x .... %02x OK", csn[0], csn[7]);
704 if (reader_mac_buf != NULL) {
705 // save NR and MAC for sim 2,4
706 memcpy(reader_mac_buf + 8, receivedCmd + 1, 8);
708 exit_loop = true;
711 goto send;
713 } else if (cmd == ICLASS_CMD_HALT && options == 0 && len == 1) {
715 if (chip_state != SELECTED) {
716 goto send;
718 // Reader ends the session
719 modulated_response = resp_sof;
720 modulated_response_size = resp_sof_len;
721 chip_state = HALTED;
722 goto send;
724 } else if (simulationMode == ICLASS_SIM_MODE_FULL && cmd == ICLASS_CMD_READ4 && len == 4) { // 0x06
726 if (chip_state != SELECTED) {
727 goto send;
729 //Read block
730 memcpy(data_generic_trace, emulator + (current_page * page_size) + (block * 8), 32);
731 AddCrc(data_generic_trace, 32);
732 trace_data = data_generic_trace;
733 trace_data_size = 34;
734 CodeIso15693AsTag(trace_data, trace_data_size);
735 memcpy(data_response, ts->buf, ts->max);
736 modulated_response = data_response;
737 modulated_response_size = ts->max;
738 goto send;
740 } else if (cmd == ICLASS_CMD_UPDATE && (len == 12 || len == 14)) {
742 // We're expected to respond with the data+crc, exactly what's already in the receivedCmd
743 // receivedCmd is now UPDATE 1b | ADDRESS 1b | DATA 8b | Signature 4b or CRC 2b
744 if (chip_state != SELECTED) {
745 goto send;
747 // is chip in ReadOnly (RO)
748 if ((block_wr_lock & 0x80) == 0) goto send;
750 if (block == 12 && (block_wr_lock & 0x40) == 0) goto send;
751 if (block == 11 && (block_wr_lock & 0x20) == 0) goto send;
752 if (block == 10 && (block_wr_lock & 0x10) == 0) goto send;
753 if (block == 9 && (block_wr_lock & 0x08) == 0) goto send;
754 if (block == 8 && (block_wr_lock & 0x04) == 0) goto send;
755 if (block == 7 && (block_wr_lock & 0x02) == 0) goto send;
756 if (block == 6 && (block_wr_lock & 0x01) == 0) goto send;
758 if (block == 2) { // update e-purse
759 memcpy(card_challenge_data, receivedCmd + 2, 8);
760 CodeIso15693AsTag(card_challenge_data, sizeof(card_challenge_data));
761 memcpy(resp_cc, ts->buf, ts->max);
762 resp_cc_len = ts->max;
763 cipher_state_KD[current_page] = opt_doTagMAC_1(card_challenge_data, diversified_kd);
764 cipher_state_KC[current_page] = opt_doTagMAC_1(card_challenge_data, diversified_kc);
765 if (simulationMode == ICLASS_SIM_MODE_FULL) {
766 memcpy(emulator + (current_page * page_size) + (8 * 2), card_challenge_data, 8);
768 } else if (block == 3) { // update Kd
769 for (int i = 0; i < 8; i++) {
770 if (personalization_mode) {
771 diversified_kd[i] = receivedCmd[2 + i];
772 } else {
773 diversified_kd[i] ^= receivedCmd[2 + i];
776 cipher_state_KD[current_page] = opt_doTagMAC_1(card_challenge_data, diversified_kd);
777 if (simulationMode == ICLASS_SIM_MODE_FULL) {
778 memcpy(emulator + (current_page * page_size) + (8 * 3), diversified_kd, 8);
780 } else if (block == 4) { // update Kc
781 for (int i = 0; i < 8; i++) {
782 if (personalization_mode) {
783 diversified_kc[i] = receivedCmd[2 + i];
784 } else {
785 diversified_kc[i] ^= receivedCmd[2 + i];
788 cipher_state_KC[current_page] = opt_doTagMAC_1(card_challenge_data, diversified_kc);
789 if (simulationMode == ICLASS_SIM_MODE_FULL) {
790 memcpy(emulator + (current_page * page_size) + (8 * 4), diversified_kc, 8);
792 } else if (simulationMode == ICLASS_SIM_MODE_FULL) {
793 // update emulator memory
794 memcpy(emulator + (current_page * page_size) + (8 * block), receivedCmd + 2, 8);
797 memcpy(data_generic_trace, receivedCmd + 2, 8);
798 AddCrc(data_generic_trace, 8);
799 trace_data = data_generic_trace;
800 trace_data_size = 10;
801 CodeIso15693AsTag(trace_data, trace_data_size);
802 memcpy(data_response, ts->buf, ts->max);
803 modulated_response = data_response;
804 modulated_response_size = ts->max;
805 goto send;
807 } else if (cmd == ICLASS_CMD_PAGESEL && len == 4) { // 0x84
808 // Pagesel,
809 // - enables to select a page in the selected chip memory and return its configuration block
810 // Chips with a single page will not answer to this command
811 // Otherwise, we should answer 8bytes (conf block 1) + 2bytes CRC
812 if (chip_state != SELECTED) {
813 goto send;
816 if (simulationMode == ICLASS_SIM_MODE_FULL && max_page > 0) {
818 // if on 2k, always ignore 3msb, & 0x1F)
819 uint8_t page = receivedCmd[1] & 0x1F;
820 if (page > max_page) {
821 goto send;
824 current_page = page;
826 memcpy(data_generic_trace, emulator + (current_page * page_size) + (8 * 1), 8);
827 memcpy(diversified_kd, emulator + (current_page * page_size) + (8 * 3), 8);
828 memcpy(diversified_kc, emulator + (current_page * page_size) + (8 * 4), 8);
830 cipher_state = &cipher_state_KD[current_page];
832 personalization_mode = data_generic_trace[7] & 0x80;
833 block_wr_lock = data_generic_trace[3];
835 AddCrc(data_generic_trace, 8);
837 trace_data = data_generic_trace;
838 trace_data_size = 10;
840 CodeIso15693AsTag(trace_data, trace_data_size);
841 memcpy(data_response, ts->buf, ts->max);
842 modulated_response = data_response;
843 modulated_response_size = ts->max;
845 goto send;
847 } else if (cmd == ICLASS_CMD_DETECT) { // 0x0F
848 // not supported yet, ignore
849 // } else if (cmd == 0x26 && len == 5) {
850 // standard ISO15693 INVENTORY command. Ignore.
851 } else {
852 // Never seen this command before
853 if (g_dbglevel >= DBG_EXTENDED)
854 print_result("Unhandled command received ", receivedCmd, len);
857 send:
859 A legit tag has about 330us delay between reader EOT and tag SOF.
861 if (modulated_response_size > 0) {
862 uint32_t response_time = reader_eof_time + DELAY_ICLASS_VCD_TO_VICC_SIM;
863 TransmitTo15693Reader(modulated_response, modulated_response_size, &response_time, 0, false);
864 LogTrace_ISO15693(trace_data, trace_data_size, response_time * 32, (response_time * 32) + (modulated_response_size * 32 * 64), NULL, false);
867 if (chip_state == HALTED) {
868 uint32_t wait_time = GetCountSspClk() + ICLASS_READER_TIMEOUT_ACTALL;
869 while (GetCountSspClk() < wait_time) {};
872 // CC attack
873 // wait to trigger the reader bug, then wait 1000ms
874 if (kc_attempt > 3) {
875 uint32_t wait_time = GetCountSspClk() + (16000 * 100);
876 while (GetCountSspClk() < wait_time) {};
877 kc_attempt = 0;
878 exit_loop = true;
882 LEDsoff();
884 if (button_pressed)
885 DbpString("button pressed");
887 return button_pressed;
890 int do_iclass_simulation_nonsec(void) {
891 // free eventually allocated BigBuf memory
892 BigBuf_free_keep_EM();
894 uint16_t page_size = 32 * 8;
895 uint8_t current_page = 0;
897 uint8_t *emulator = BigBuf_get_EM_addr();
898 uint8_t *csn = emulator;
900 // CSN followed by two CRC bytes
901 uint8_t anticoll_data[10] = { 0 };
902 uint8_t csn_data[10] = { 0 };
903 memcpy(csn_data, csn, sizeof(csn_data));
905 // Construct anticollision-CSN
906 rotateCSN(csn_data, anticoll_data);
908 // Compute CRC on both CSNs
909 AddCrc(anticoll_data, 8);
910 AddCrc(csn_data, 8);
912 // configuration block
913 uint8_t conf_block[10] = {0x12, 0xFF, 0xFF, 0xFF, 0x7F, 0x1F, 0xFF, 0x3C, 0x00, 0x00};
915 // AIA
916 uint8_t aia_data[10] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00};
918 memcpy(conf_block, emulator + (8 * 1), 8);
919 memcpy(aia_data, emulator + (8 * 2), 8);
921 AddCrc(conf_block, 8);
922 AddCrc(aia_data, 8);
924 if ((conf_block[5] & 0x80) == 0x80) {
925 page_size = 256 * 8;
928 // chip memory may be divided in 8 pages
929 uint8_t max_page = ((conf_block[4] & 0x10) == 0x10) ? 0 : 7;
931 // Anti-collision process:
932 // Reader 0a
933 // Tag 0f
934 // Reader 0c
935 // Tag anticoll. CSN
936 // Reader 81 anticoll. CSN
937 // Tag CSN
939 uint8_t *modulated_response = NULL;
940 int modulated_response_size = 0;
941 uint8_t *trace_data = NULL;
942 int trace_data_size = 0;
944 // Respond SOF -- takes 1 bytes
945 uint8_t *resp_sof = BigBuf_malloc(2);
946 int resp_sof_len;
948 // Anticollision CSN (rotated CSN)
949 // 22: Takes 2 bytes for SOF/EOF and 10 * 2 = 20 bytes (2 bytes/byte)
950 uint8_t *resp_anticoll = BigBuf_malloc(28);
951 int resp_anticoll_len;
953 // CSN
954 // 22: Takes 2 bytes for SOF/EOF and 10 * 2 = 20 bytes (2 bytes/byte)
955 uint8_t *resp_csn = BigBuf_malloc(28);
956 int resp_csn_len;
958 // configuration (blk 1) PICOPASS 2ks
959 uint8_t *resp_conf = BigBuf_malloc(28);
960 int resp_conf_len;
962 // Application Issuer Area (blk 5)
963 uint8_t *resp_aia = BigBuf_malloc(28);
964 int resp_aia_len;
966 // receive command
967 uint8_t *receivedCmd = BigBuf_malloc(MAX_FRAME_SIZE);
969 // Prepare card messages
970 tosend_t *ts = get_tosend();
971 ts->max = 0;
973 // First card answer: SOF
974 CodeIClassTagSOF();
975 memcpy(resp_sof, ts->buf, ts->max);
976 resp_sof_len = ts->max;
978 // Anticollision CSN
979 CodeIso15693AsTag(anticoll_data, sizeof(anticoll_data));
980 memcpy(resp_anticoll, ts->buf, ts->max);
981 resp_anticoll_len = ts->max;
983 // CSN (block 0)
984 CodeIso15693AsTag(csn_data, sizeof(csn_data));
985 memcpy(resp_csn, ts->buf, ts->max);
986 resp_csn_len = ts->max;
988 // Configuration (block 1)
989 CodeIso15693AsTag(conf_block, sizeof(conf_block));
990 memcpy(resp_conf, ts->buf, ts->max);
991 resp_conf_len = ts->max;
993 // Application Issuer Area (block 2)
994 CodeIso15693AsTag(aia_data, sizeof(aia_data));
995 memcpy(resp_aia, ts->buf, ts->max);
996 resp_aia_len = ts->max;
998 //This is used for responding to READ-block commands or other data which is dynamically generated
999 //First the 'trace'-data, not encoded for FPGA
1000 uint8_t *data_generic_trace = BigBuf_malloc(32 + 2); // 32 bytes data + 2byte CRC is max tag answer
1002 //Then storage for the modulated data
1003 //Each bit is doubled when modulated for FPGA, and we also have SOF and EOF (2 bytes)
1004 uint8_t *data_response = BigBuf_malloc((32 + 2) * 2 + 2);
1006 enum { IDLE, ACTIVATED, SELECTED, HALTED } chip_state = IDLE;
1008 bool button_pressed = false;
1009 uint8_t cmd, options, block;
1010 int len;
1012 bool exit_loop = false;
1013 while (exit_loop == false) {
1014 WDT_HIT();
1016 uint32_t reader_eof_time = 0;
1017 len = GetIso15693CommandFromReader(receivedCmd, MAX_FRAME_SIZE, &reader_eof_time);
1018 if (len < 0) {
1019 button_pressed = true;
1020 exit_loop = true;
1021 continue;
1024 // Now look at the reader command and provide appropriate responses
1025 // default is no response:
1026 modulated_response = NULL;
1027 modulated_response_size = 0;
1028 trace_data = NULL;
1029 trace_data_size = 0;
1031 // extra response data
1032 cmd = receivedCmd[0] & 0xF;
1033 options = (receivedCmd[0] >> 4) & 0xFF;
1034 block = receivedCmd[1];
1036 if (cmd == ICLASS_CMD_ACTALL && len == 1) { // 0x0A
1037 // Reader in anti collision phase
1038 if (chip_state != HALTED) {
1039 modulated_response = resp_sof;
1040 modulated_response_size = resp_sof_len;
1041 chip_state = ACTIVATED;
1043 goto send;
1045 } else if (cmd == ICLASS_CMD_READ_OR_IDENTIFY && len == 1) { // 0x0C
1046 // Reader asks for anti collision CSN
1047 if (chip_state == SELECTED || chip_state == ACTIVATED) {
1048 modulated_response = resp_anticoll;
1049 modulated_response_size = resp_anticoll_len;
1050 trace_data = anticoll_data;
1051 trace_data_size = sizeof(anticoll_data);
1053 goto send;
1055 } else if (cmd == ICLASS_CMD_SELECT && len == 9) {
1056 // Reader selects anticollision CSN.
1057 // Tag sends the corresponding real CSN
1058 if (chip_state == ACTIVATED || chip_state == SELECTED) {
1059 if (!memcmp(receivedCmd + 1, anticoll_data, 8)) {
1060 modulated_response = resp_csn;
1061 modulated_response_size = resp_csn_len;
1062 trace_data = csn_data;
1063 trace_data_size = sizeof(csn_data);
1064 chip_state = SELECTED;
1065 } else {
1066 chip_state = IDLE;
1068 } else if (chip_state == HALTED) {
1069 // RESELECT with CSN
1070 if (!memcmp(receivedCmd + 1, csn_data, 8)) {
1071 modulated_response = resp_csn;
1072 modulated_response_size = resp_csn_len;
1073 trace_data = csn_data;
1074 trace_data_size = sizeof(csn_data);
1075 chip_state = SELECTED;
1078 goto send;
1081 } else if (cmd == ICLASS_CMD_READ_OR_IDENTIFY && len == 4) { // 0x0C
1083 if (chip_state != SELECTED) {
1084 goto send;
1087 switch (block) {
1088 case 0: { // csn (0c 00)
1089 modulated_response = resp_csn;
1090 modulated_response_size = resp_csn_len;
1091 trace_data = csn_data;
1092 trace_data_size = sizeof(csn_data);
1093 goto send;
1095 case 1: { // configuration (0c 01)
1096 modulated_response = resp_conf;
1097 modulated_response_size = resp_conf_len;
1098 trace_data = conf_block;
1099 trace_data_size = sizeof(conf_block);
1100 goto send;
1102 case 2: { // Application Issuer Area (0c 02)
1103 modulated_response = resp_aia;
1104 modulated_response_size = resp_aia_len;
1105 trace_data = aia_data;
1106 trace_data_size = sizeof(aia_data);
1107 goto send;
1109 default : {
1110 memcpy(data_generic_trace, emulator + (block << 3), 8);
1111 AddCrc(data_generic_trace, 8);
1112 trace_data = data_generic_trace;
1113 trace_data_size = 10;
1114 CodeIso15693AsTag(trace_data, trace_data_size);
1115 memcpy(data_response, ts->buf, ts->max);
1116 modulated_response = data_response;
1117 modulated_response_size = ts->max;
1118 goto send;
1120 } // swith
1122 } else if (cmd == ICLASS_CMD_READCHECK) { // 0x88
1123 goto send;
1125 } else if (cmd == ICLASS_CMD_CHECK && len == 9) { // 0x05
1126 goto send;
1128 } else if (cmd == ICLASS_CMD_HALT && options == 0 && len == 1) {
1130 if (chip_state != SELECTED) {
1131 goto send;
1133 // Reader ends the session
1134 modulated_response = resp_sof;
1135 modulated_response_size = resp_sof_len;
1136 chip_state = HALTED;
1137 goto send;
1139 } else if (cmd == ICLASS_CMD_READ4 && len == 4) { // 0x06
1141 if (chip_state != SELECTED) {
1142 goto send;
1144 //Read block
1145 memcpy(data_generic_trace, emulator + (current_page * page_size) + (block * 8), 8 * 4);
1146 AddCrc(data_generic_trace, 8 * 4);
1147 trace_data = data_generic_trace;
1148 trace_data_size = 34;
1149 CodeIso15693AsTag(trace_data, trace_data_size);
1150 memcpy(data_response, ts->buf, ts->max);
1151 modulated_response = data_response;
1152 modulated_response_size = ts->max;
1153 goto send;
1155 } else if (cmd == ICLASS_CMD_UPDATE && (len == 12 || len == 14)) {
1157 // We're expected to respond with the data+crc, exactly what's already in the receivedCmd
1158 // receivedCmd is now UPDATE 1b | ADDRESS 1b | DATA 8b | Signature 4b or CRC 2b
1159 if (chip_state != SELECTED) {
1160 goto send;
1163 // update emulator memory
1164 memcpy(emulator + (current_page * page_size) + (8 * block), receivedCmd + 2, 8);
1166 memcpy(data_generic_trace, receivedCmd + 2, 8);
1167 AddCrc(data_generic_trace, 8);
1168 trace_data = data_generic_trace;
1169 trace_data_size = 10;
1170 CodeIso15693AsTag(trace_data, trace_data_size);
1171 memcpy(data_response, ts->buf, ts->max);
1172 modulated_response = data_response;
1173 modulated_response_size = ts->max;
1174 goto send;
1176 } else if (cmd == ICLASS_CMD_PAGESEL && len == 4) { // 0x84
1177 // Pagesel,
1178 // - enables to select a page in the selected chip memory and return its configuration block
1179 // Chips with a single page will not answer to this command
1180 // Otherwise, we should answer 8bytes (conf block 1) + 2bytes CRC
1181 if (chip_state != SELECTED) {
1182 goto send;
1185 if (max_page > 0) {
1187 current_page = receivedCmd[1];
1189 memcpy(data_generic_trace, emulator + (current_page * page_size) + (8 * 1), 8);
1190 AddCrc(data_generic_trace, 8);
1191 trace_data = data_generic_trace;
1192 trace_data_size = 10;
1194 CodeIso15693AsTag(trace_data, trace_data_size);
1195 memcpy(data_response, ts->buf, ts->max);
1196 modulated_response = data_response;
1197 modulated_response_size = ts->max;
1199 goto send;
1201 // } else if(cmd == ICLASS_CMD_DETECT) { // 0x0F
1202 // } else if (cmd == 0x26 && len == 5) {
1203 // standard ISO15693 INVENTORY command. Ignore.
1204 } else {
1205 // Never seen this command before
1206 if (g_dbglevel >= DBG_EXTENDED)
1207 print_result("Unhandled command received ", receivedCmd, len);
1210 send:
1212 A legit tag has about 330us delay between reader EOT and tag SOF.
1214 if (modulated_response_size > 0) {
1215 uint32_t response_time = reader_eof_time + DELAY_ICLASS_VCD_TO_VICC_SIM;
1216 TransmitTo15693Reader(modulated_response, modulated_response_size, &response_time, 0, false);
1217 LogTrace_ISO15693(trace_data, trace_data_size, response_time * 32, (response_time * 32) + (modulated_response_size * 32 * 64), NULL, false);
1221 LEDsoff();
1223 if (button_pressed)
1224 DbpString("button pressed");
1226 return button_pressed;
1230 // THE READER CODE
1231 void iclass_send_as_reader(uint8_t *frame, int len, uint32_t *start_time, uint32_t *end_time, bool shallow_mod) {
1232 CodeIso15693AsReader(frame, len);
1233 tosend_t *ts = get_tosend();
1234 TransmitTo15693Tag(ts->buf, ts->max, start_time, shallow_mod);
1235 *end_time = *start_time + (32 * ((8 * ts->max) - 4)); // subtract the 4 padding bits after EOF
1236 LogTrace_ISO15693(frame, len, (*start_time * 4), (*end_time * 4), NULL, true);
1239 static bool iclass_send_cmd_with_retries(uint8_t *cmd, size_t cmdsize, uint8_t *resp, size_t max_resp_size,
1240 uint8_t expected_size, uint8_t tries, uint32_t *start_time,
1241 uint16_t timeout, uint32_t *eof_time, bool shallow_mod) {
1243 uint16_t resp_len = 0;
1244 while (tries-- > 0) {
1246 iclass_send_as_reader(cmd, cmdsize, start_time, eof_time, shallow_mod);
1248 if (resp == NULL) {
1249 return true;
1252 int res = GetIso15693AnswerFromTag(resp, max_resp_size, timeout, eof_time, false, true, &resp_len);
1253 if (res == PM3_SUCCESS && expected_size == resp_len) {
1254 return true;
1257 // Timed out waiting for the tag to reply, but perhaps the tag did hear the command and is attempting to reply
1258 // So wait long enough for the tag to encode it's reply plus required frame delays on each side before retrying
1259 // And then double it, because in practice it seems to make it much more likely to succeed
1260 // Response time calculation from expected_size lifted from GetIso15693AnswerFromTag
1261 *start_time = *eof_time + ((DELAY_ICLASS_VICC_TO_VCD_READER + DELAY_ISO15693_VCD_TO_VICC_READER + (expected_size * 8 * 8 * 16)) * 2);
1263 return false;
1267 * @brief Talks to an iclass tag, sends the commands to get CSN and CC.
1268 * @param card_data where the CSN, CONFIG, CC are stored for return
1269 * 8 bytes csn + 8 bytes config + 8 bytes CC
1270 * @return false = fail
1271 * true = Got all.
1273 static bool select_iclass_tag_ex(picopass_hdr_t *hdr, bool use_credit_key, uint32_t *eof_time, uint8_t *status, bool shallow_mod) {
1275 static uint8_t act_all[] = { ICLASS_CMD_ACTALL };
1276 static uint8_t identify[] = { ICLASS_CMD_READ_OR_IDENTIFY, 0x00, 0x73, 0x33 };
1277 static uint8_t read_conf[] = { ICLASS_CMD_READ_OR_IDENTIFY, 0x01, 0xfa, 0x22 };
1278 uint8_t select[] = { 0x80 | ICLASS_CMD_SELECT, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
1279 uint8_t read_aia[] = { ICLASS_CMD_READ_OR_IDENTIFY, 0x05, 0xde, 0x64};
1280 uint8_t read_check_cc[] = { 0x80 | ICLASS_CMD_READCHECK, 0x02 };
1281 uint8_t resp[ICLASS_BUFFER_SIZE] = {0};
1283 // Bit 4: K.If this bit equals to one, the READCHECK will use the Credit Key (Kc); if equals to zero, Debit Key (Kd) will be used
1284 // bit 7: parity.
1285 if (use_credit_key)
1286 read_check_cc[0] = 0x10 | ICLASS_CMD_READCHECK;
1288 // wakeup
1289 uint32_t start_time = GetCountSspClk();
1290 iclass_send_as_reader(act_all, 1, &start_time, eof_time, shallow_mod);
1291 int res;
1292 uint16_t resp_len = 0;
1293 res = GetIso15693AnswerFromTag(resp, sizeof(resp), ICLASS_READER_TIMEOUT_ACTALL, eof_time, false, true, &resp_len);
1294 if (res != PM3_SUCCESS)
1295 return false;
1297 // send Identify
1298 start_time = *eof_time + DELAY_ICLASS_VICC_TO_VCD_READER;
1299 iclass_send_as_reader(identify, 1, &start_time, eof_time, shallow_mod);
1301 // expect a 10-byte response here, 8 byte anticollision-CSN and 2 byte CRC
1302 res = GetIso15693AnswerFromTag(resp, sizeof(resp), ICLASS_READER_TIMEOUT_OTHERS, eof_time, false, true, &resp_len);
1303 if (res != PM3_SUCCESS || resp_len != 10)
1304 return false;
1306 // copy the Anti-collision CSN to our select-packet
1307 memcpy(&select[1], resp, 8);
1309 // select the card
1310 start_time = *eof_time + DELAY_ICLASS_VICC_TO_VCD_READER;
1311 iclass_send_as_reader(select, sizeof(select), &start_time, eof_time, shallow_mod);
1313 // expect a 10-byte response here, 8 byte CSN and 2 byte CRC
1314 res = GetIso15693AnswerFromTag(resp, sizeof(resp), ICLASS_READER_TIMEOUT_OTHERS, eof_time, false, true, &resp_len);
1315 if (res != PM3_SUCCESS || resp_len != 10)
1316 return false;
1318 // save CSN
1319 memcpy(hdr->csn, resp, sizeof(hdr->csn));
1321 // card selected, now read config (block1) (only 8 bytes no CRC)
1322 start_time = *eof_time + DELAY_ICLASS_VICC_TO_VCD_READER;
1323 iclass_send_as_reader(read_conf, sizeof(read_conf), &start_time, eof_time, shallow_mod);
1325 // expect a 8-byte response here
1326 res = GetIso15693AnswerFromTag(resp, sizeof(resp), ICLASS_READER_TIMEOUT_OTHERS, eof_time, false, true, &resp_len);
1327 if (res != PM3_SUCCESS || resp_len != 10)
1328 return false;
1330 // save CONF
1331 memcpy((uint8_t *)&hdr->conf, resp, sizeof(hdr->conf));
1333 if (status)
1334 *status |= (FLAG_ICLASS_CSN | FLAG_ICLASS_CONF);
1336 uint8_t pagemap = get_pagemap(hdr);
1337 if (pagemap != PICOPASS_NON_SECURE_PAGEMODE) {
1339 // read App Issuer Area block 5
1340 start_time = *eof_time + DELAY_ICLASS_VICC_TO_VCD_READER;
1341 iclass_send_as_reader(read_aia, sizeof(read_aia), &start_time, eof_time, shallow_mod);
1343 // expect a 10-byte response here
1344 res = GetIso15693AnswerFromTag(resp, sizeof(resp), ICLASS_READER_TIMEOUT_OTHERS, eof_time, false, true, &resp_len);
1345 if (res != PM3_SUCCESS || resp_len != 10)
1346 return false;
1348 if (status) {
1349 *status |= FLAG_ICLASS_AIA;
1350 memcpy(hdr->app_issuer_area, resp, sizeof(hdr->app_issuer_area));
1353 // card selected, now read e-purse (cc) (block2) (only 8 bytes no CRC)
1354 start_time = *eof_time + DELAY_ICLASS_VICC_TO_VCD_READER;
1355 iclass_send_as_reader(read_check_cc, sizeof(read_check_cc), &start_time, eof_time, shallow_mod);
1357 // expect a 8-byte response here
1358 res = GetIso15693AnswerFromTag(resp, sizeof(resp), ICLASS_READER_TIMEOUT_OTHERS, eof_time, false, true, &resp_len);
1359 if (res != PM3_SUCCESS || resp_len != 8)
1360 return false;
1362 memcpy(hdr->epurse, resp, sizeof(hdr->epurse));
1364 if (status)
1365 *status |= FLAG_ICLASS_CC;
1367 } else {
1369 // on NON_SECURE_PAGEMODE cards, AIA is on block2..
1371 // read App Issuer Area block 2
1372 read_aia[1] = 0x02;
1373 read_aia[2] = 0x61;
1374 read_aia[3] = 0x10;
1376 start_time = *eof_time + DELAY_ICLASS_VICC_TO_VCD_READER;
1377 iclass_send_as_reader(read_aia, sizeof(read_aia), &start_time, eof_time, shallow_mod);
1379 // expect a 10-byte response here
1380 res = GetIso15693AnswerFromTag(resp, sizeof(resp), ICLASS_READER_TIMEOUT_OTHERS, eof_time, false, true, &resp_len);
1381 if (res != PM3_SUCCESS || resp_len != 10)
1382 return false;
1384 if (status) {
1385 *status |= FLAG_ICLASS_AIA;
1386 memcpy(hdr->epurse, resp, sizeof(hdr->epurse));
1390 return true;
1393 bool select_iclass_tag(picopass_hdr_t *hdr, bool use_credit_key, uint32_t *eof_time, bool shallow_mod) {
1394 uint8_t result = 0;
1395 return select_iclass_tag_ex(hdr, use_credit_key, eof_time, &result, shallow_mod);
1398 // Reader iClass Anticollission
1399 // turn off afterwards
1400 void ReaderIClass(uint8_t flags) {
1402 // flag to use credit key
1403 bool use_credit_key = ((flags & FLAG_ICLASS_READER_CREDITKEY) == FLAG_ICLASS_READER_CREDITKEY);
1404 bool shallow_mod = (flags & FLAG_ICLASS_READER_SHALLOW_MOD);
1406 if ((flags & FLAG_ICLASS_READER_INIT) == FLAG_ICLASS_READER_INIT) {
1407 Iso15693InitReader();
1410 if ((flags & FLAG_ICLASS_READER_CLEARTRACE) == FLAG_ICLASS_READER_CLEARTRACE) {
1411 clear_trace();
1415 uint8_t res = 0;
1416 uint32_t eof_time = 0;
1417 picopass_hdr_t hdr = {0};
1419 if (select_iclass_tag_ex(&hdr, use_credit_key, &eof_time, &res, shallow_mod) == false) {
1420 reply_ng(CMD_HF_ICLASS_READER, PM3_ERFTRANS, NULL, 0);
1421 goto out;
1424 // Page mapping for secure mode
1425 // 0 : CSN
1426 // 1 : Configuration
1427 // 2 : e-purse
1428 // 3 : kd / debit / aa2 (write-only)
1429 // 4 : kc / credit / aa1 (write-only)
1430 // 5 : AIA, Application issuer area
1432 // Page mapping for non secure mode
1433 // 0 : CSN
1434 // 1 : Configuration
1435 // 2 : AIA, Application issuer area
1437 // Return to client, e 6 * 8 bytes of data.
1438 // with 0xFF:s in block 3 and 4.
1440 iclass_card_select_resp_t payload = {
1441 .status = res
1443 memcpy(&payload.header.hdr, &hdr, sizeof(picopass_hdr_t));
1445 reply_ng(CMD_HF_ICLASS_READER, PM3_SUCCESS, (uint8_t *)&payload, sizeof(iclass_card_select_resp_t));
1447 out:
1448 switch_off();
1451 bool authenticate_iclass_tag(iclass_auth_req_t *payload, picopass_hdr_t *hdr, uint32_t *start_time, uint32_t *eof_time, uint8_t *mac_out) {
1453 uint8_t cmd_check[9] = { ICLASS_CMD_CHECK };
1454 uint8_t mac[4] = {0};
1455 uint8_t resp_auth[4] = {0};
1456 uint8_t ccnr[12] = {0};
1458 uint8_t *pmac = mac;
1459 if (mac_out)
1460 pmac = mac_out;
1462 memcpy(ccnr, hdr->epurse, sizeof(hdr->epurse));
1464 if (payload->use_replay) {
1466 memcpy(pmac, payload->key + 4, 4);
1467 memcpy(cmd_check + 1, payload->key, 8);
1469 } else {
1471 uint8_t div_key[8] = {0};
1472 if (payload->use_raw)
1473 memcpy(div_key, payload->key, 8);
1474 else
1475 iclass_calc_div_key(hdr->csn, payload->key, div_key, payload->use_elite);
1477 if (payload->use_credit_key)
1478 memcpy(hdr->key_c, div_key, sizeof(hdr->key_c));
1479 else
1480 memcpy(hdr->key_d, div_key, sizeof(hdr->key_d));
1482 opt_doReaderMAC(ccnr, div_key, pmac);
1484 // copy MAC to check command (readersignature)
1485 cmd_check[5] = pmac[0];
1486 cmd_check[6] = pmac[1];
1487 cmd_check[7] = pmac[2];
1488 cmd_check[8] = pmac[3];
1490 return iclass_send_cmd_with_retries(cmd_check, sizeof(cmd_check), resp_auth, sizeof(resp_auth), 4, 2, start_time, ICLASS_READER_TIMEOUT_OTHERS, eof_time, payload->shallow_mod);
1494 /* this function works on the following assumptions.
1495 * - one select first, to get CSN / CC (e-purse)
1496 * - calculate before diversified keys and precalc mac based on CSN/KEY.
1497 * - data in contains of diversified keys, mac
1498 * - key loop only test one type of authtication key. Ie two calls needed
1499 * to cover debit and credit key. (AA1/AA2)
1501 void iClass_Authentication_fast(iclass_chk_t *p) {
1502 // sanitation
1503 if (p == NULL) {
1504 reply_ng(CMD_HF_ICLASS_CHKKEYS, PM3_ESOFT, NULL, 0);
1505 return;
1508 bool shallow_mod = p->shallow_mod;
1510 uint8_t check[9] = { ICLASS_CMD_CHECK };
1511 uint8_t resp[ICLASS_BUFFER_SIZE] = {0};
1512 uint8_t readcheck_cc[] = { 0x80 | ICLASS_CMD_READCHECK, 0x02 };
1514 if (p->use_credit_key)
1515 readcheck_cc[0] = 0x10 | ICLASS_CMD_READCHECK;
1517 // select card / e-purse
1518 picopass_hdr_t hdr = {0};
1519 iclass_premac_t *keys = p->items;
1521 LED_A_ON();
1523 // fresh start
1524 switch_off();
1525 SpinDelay(20);
1526 Iso15693InitReader();
1528 bool isOK = false;
1530 uint32_t start_time = 0, eof_time = 0;
1531 if (select_iclass_tag(&hdr, p->use_credit_key, &eof_time, shallow_mod) == false)
1532 goto out;
1534 start_time = eof_time + DELAY_ICLASS_VICC_TO_VCD_READER;
1536 // since select_iclass_tag call sends s readcheck, we start with sending first response.
1537 uint16_t checked = 0;
1539 // Keychunk loop
1540 uint8_t i = 0;
1541 for (i = 0; i < p->count; i++) {
1543 // Allow button press / usb cmd to interrupt device
1544 if (checked == 1000) {
1545 if (BUTTON_PRESS() || data_available()) goto out;
1546 checked = 0;
1548 ++checked;
1550 WDT_HIT();
1551 LED_B_ON();
1553 // copy MAC to check command (readersignature)
1554 check[5] = keys[i].mac[0];
1555 check[6] = keys[i].mac[1];
1556 check[7] = keys[i].mac[2];
1557 check[8] = keys[i].mac[3];
1559 // expect 4bytes, 3 retries times..
1560 isOK = iclass_send_cmd_with_retries(check, sizeof(check), resp, sizeof(resp), 4, 2, &start_time, ICLASS_READER_TIMEOUT_OTHERS, &eof_time, shallow_mod);
1561 if (isOK)
1562 goto out;
1564 start_time = eof_time + DELAY_ICLASS_VICC_TO_VCD_READER;
1565 // Auth Sequence MUST begin with reading e-purse. (block2)
1566 // Card selected, now read e-purse (cc) (block2) (only 8 bytes no CRC)
1567 iclass_send_as_reader(readcheck_cc, sizeof(readcheck_cc), &start_time, &eof_time, shallow_mod);
1568 LED_B_OFF();
1571 out:
1572 // send keyindex.
1573 reply_ng(CMD_HF_ICLASS_CHKKEYS, (isOK) ? PM3_SUCCESS : PM3_ESOFT, (uint8_t *)&i, sizeof(i));
1574 switch_off();
1577 // Tries to read block.
1578 // retries 3times.
1579 // reply 8 bytes block
1580 bool iclass_read_block(uint16_t blockno, uint8_t *data, uint32_t *start_time, uint32_t *eof_time, bool shallow_mod) {
1581 uint8_t resp[10];
1582 uint8_t c[] = {ICLASS_CMD_READ_OR_IDENTIFY, blockno, 0x00, 0x00};
1583 AddCrc(c + 1, 1);
1584 bool isOK = iclass_send_cmd_with_retries(c, sizeof(c), resp, sizeof(resp), 10, 2, start_time, ICLASS_READER_TIMEOUT_OTHERS, eof_time, shallow_mod);
1585 if (isOK)
1586 memcpy(data, resp, 8);
1587 return isOK;
1590 // turn off afterwards
1591 // send in authentication needed data, if to use auth.
1592 // reply 8 bytes block if send_reply (for client)
1593 void iClass_ReadBlock(uint8_t *msg) {
1595 iclass_auth_req_t *payload = (iclass_auth_req_t *)msg;
1596 bool shallow_mod = payload->shallow_mod;
1598 iclass_readblock_resp_t response = { .isOK = true };
1599 memset(response.data, 0, sizeof(response.data));
1601 uint8_t cmd_read[] = {ICLASS_CMD_READ_OR_IDENTIFY, payload->blockno, 0x00, 0x00};
1602 AddCrc(cmd_read + 1, 1);
1604 Iso15693InitReader();
1606 // select tag.
1607 uint32_t eof_time = 0;
1608 picopass_hdr_t hdr = {0};
1609 bool res = select_iclass_tag(&hdr, payload->use_credit_key, &eof_time, shallow_mod);
1610 if (res == false) {
1611 if (payload->send_reply) {
1612 response.isOK = res;
1613 reply_ng(CMD_HF_ICLASS_READBL, PM3_ETIMEOUT, (uint8_t *)&response, sizeof(response));
1615 goto out;
1618 uint32_t start_time = eof_time + DELAY_ICLASS_VICC_TO_VCD_READER;
1620 // authenticate
1621 if (payload->do_auth) {
1623 res = authenticate_iclass_tag(payload, &hdr, &start_time, &eof_time, NULL);
1624 if (res == false) {
1625 if (payload->send_reply) {
1626 response.isOK = res;
1627 reply_ng(CMD_HF_ICLASS_READBL, PM3_ETIMEOUT, (uint8_t *)&response, sizeof(response));
1629 goto out;
1633 start_time = eof_time + DELAY_ICLASS_VICC_TO_VCD_READER;
1635 // read data
1636 uint8_t resp[10];
1637 res = iclass_send_cmd_with_retries(cmd_read, sizeof(cmd_read), resp, sizeof(resp), 10, 3, &start_time, ICLASS_READER_TIMEOUT_OTHERS, &eof_time, shallow_mod);
1638 if (res) {
1639 memcpy(response.data, resp, sizeof(response.data));
1640 if (payload->send_reply) {
1641 reply_ng(CMD_HF_ICLASS_READBL, PM3_SUCCESS, (uint8_t *)&response, sizeof(response));
1643 } else {
1644 if (payload->send_reply) {
1645 response.isOK = res;
1646 reply_ng(CMD_HF_ICLASS_READBL, PM3_ETIMEOUT, (uint8_t *)&response, sizeof(response));
1650 out:
1651 switch_off();
1654 // Dump command seems to dump a block related portion of card memory.
1655 // I suppose it will need to do an authentatication to AA1, read its blocks by calling this.
1656 // then authenticate AA2, and read those blocks by calling this.
1657 // By the looks at it only 2K cards is supported, or first page dumps on larger cards.
1658 // turn off afterwards
1659 void iClass_Dump(uint8_t *msg) {
1661 BigBuf_free();
1663 iclass_dump_req_t *cmd = (iclass_dump_req_t *)msg;
1664 iclass_auth_req_t *req = &cmd->req;
1665 bool shallow_mod = req->shallow_mod;
1667 uint8_t *dataout = BigBuf_malloc(ICLASS_16KS_SIZE);
1668 if (dataout == NULL) {
1669 DbpString("fail to allocate memory");
1670 if (req->send_reply) {
1671 reply_ng(CMD_HF_ICLASS_DUMP, PM3_EMALLOC, NULL, 0);
1673 switch_off();
1674 return;
1676 memset(dataout, 0xFF, ICLASS_16KS_SIZE);
1678 Iso15693InitReader();
1680 // select tag.
1681 uint32_t eof_time = 0;
1682 picopass_hdr_t hdr = {0};
1683 memset(&hdr, 0xff, sizeof(picopass_hdr_t));
1685 bool res = select_iclass_tag(&hdr, req->use_credit_key, &eof_time, shallow_mod);
1686 if (res == false) {
1687 if (req->send_reply) {
1688 reply_ng(CMD_HF_ICLASS_DUMP, PM3_ETIMEOUT, NULL, 0);
1690 switch_off();
1691 return;
1694 uint32_t start_time = eof_time + DELAY_ICLASS_VICC_TO_VCD_READER;
1696 // authenticate
1697 if (req->do_auth) {
1698 res = authenticate_iclass_tag(req, &hdr, &start_time, &eof_time, NULL);
1699 if (res == false) {
1700 if (req->send_reply) {
1701 reply_ng(CMD_HF_ICLASS_DUMP, PM3_ETIMEOUT, NULL, 0);
1703 switch_off();
1704 return;
1708 start_time = eof_time + DELAY_ICLASS_VICC_TO_VCD_READER;
1710 bool dumpsuccess = true;
1712 // main read loop
1713 uint16_t i;
1714 for (i = cmd->start_block; i <= cmd->end_block; i++) {
1716 uint8_t resp[10];
1717 uint8_t c[] = {ICLASS_CMD_READ_OR_IDENTIFY, i, 0x00, 0x00};
1718 AddCrc(c + 1, 1);
1720 res = iclass_send_cmd_with_retries(c, sizeof(c), resp, sizeof(resp), 10, 3, &start_time, ICLASS_READER_TIMEOUT_OTHERS, &eof_time, shallow_mod);
1721 if (res) {
1722 memcpy(dataout + (8 * i), resp, 8);
1723 } else {
1724 Dbprintf("failed to read block %u ( 0x%02x)", i, i);
1725 dumpsuccess = false;
1729 switch_off();
1731 // copy diversified key back.
1732 if (req->do_auth) {
1733 if (req->use_credit_key)
1734 memcpy(dataout + (8 * 4), hdr.key_c, 8);
1735 else
1736 memcpy(dataout + (8 * 3), hdr.key_d, 8);
1739 if (req->send_reply) {
1740 struct p {
1741 bool isOK;
1742 uint16_t block_cnt;
1743 uint32_t bb_offset;
1744 } PACKED response;
1746 response.isOK = dumpsuccess;
1747 response.block_cnt = i - cmd->start_block;
1748 response.bb_offset = dataout - BigBuf_get_addr();
1749 reply_ng(CMD_HF_ICLASS_DUMP, PM3_SUCCESS, (uint8_t *)&response, sizeof(response));
1752 BigBuf_free();
1755 static bool iclass_writeblock_ext(uint8_t blockno, uint8_t *data, uint8_t *mac, bool use_mac, bool shallow_mod) {
1757 // write command: cmd, 1 blockno, 8 data, 4 mac
1758 uint8_t write[14] = { 0x80 | ICLASS_CMD_UPDATE, blockno };
1759 uint8_t write_len = 14;
1760 memcpy(write + 2, data, 8);
1762 if (use_mac) {
1763 memcpy(write + 10, mac, 4);
1764 } else {
1765 AddCrc(write + 1, 9);
1766 write_len -= 2;
1769 uint8_t resp[10] = {0};
1770 uint32_t eof_time = 0, start_time = 0;
1771 bool isOK = iclass_send_cmd_with_retries(write, write_len, resp, sizeof(resp), 10, 3, &start_time, ICLASS_READER_TIMEOUT_UPDATE, &eof_time, shallow_mod);
1772 if (isOK == false) {
1773 return false;
1776 if (blockno == 2) {
1777 // check response. e-purse update swaps first and second half
1778 if (memcmp(data + 4, resp, 4) || memcmp(data, resp + 4, 4)) {
1779 return false;
1781 } else if (blockno == 3 || blockno == 4) {
1782 // check response. Key updates always return 0xffffffffffffffff
1783 uint8_t all_ff[8] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
1784 if (memcmp(all_ff, resp, 8)) {
1785 return false;
1787 } else {
1788 // check response. All other updates return unchanged data
1789 if (memcmp(data, resp, 8)) {
1790 return false;
1794 return true;
1797 // turn off afterwards
1798 void iClass_WriteBlock(uint8_t *msg) {
1800 LED_A_ON();
1802 iclass_writeblock_req_t *payload = (iclass_writeblock_req_t *)msg;
1803 bool shallow_mod = payload->req.shallow_mod;
1805 uint8_t write[14] = { 0x80 | ICLASS_CMD_UPDATE, payload->req.blockno };
1806 uint8_t write_len = 14;
1808 Iso15693InitReader();
1810 // select tag.
1811 uint32_t eof_time = 0;
1812 picopass_hdr_t hdr = {0};
1813 bool res = select_iclass_tag(&hdr, payload->req.use_credit_key, &eof_time, shallow_mod);
1814 if (res == false) {
1815 goto out;
1818 uint32_t start_time = eof_time + DELAY_ICLASS_VICC_TO_VCD_READER;
1820 uint8_t mac[4] = {0};
1822 // authenticate
1823 if (payload->req.do_auth) {
1825 res = authenticate_iclass_tag(&payload->req, &hdr, &start_time, &eof_time, mac);
1826 if (res == false) {
1827 goto out;
1831 // new block data
1832 memcpy(write + 2, payload->data, 8);
1834 uint8_t pagemap = get_pagemap(&hdr);
1835 if (pagemap == PICOPASS_NON_SECURE_PAGEMODE) {
1836 // Unsecured tags uses CRC16, but don't include the UPDATE operation code
1837 // byte0 = update op
1838 // byte1 = block no
1839 // byte2..9 = new block data
1840 AddCrc(write + 1, 9);
1841 write_len -= 2;
1842 } else {
1844 if (payload->req.use_replay) {
1845 memcpy(write + 10, payload->mac, sizeof(payload->mac));
1846 } else {
1847 // Secure tags uses MAC
1848 uint8_t wb[9];
1849 wb[0] = payload->req.blockno;
1850 memcpy(wb + 1, payload->data, 8);
1852 if (payload->req.use_credit_key)
1853 doMAC_N(wb, sizeof(wb), hdr.key_c, mac);
1854 else
1855 doMAC_N(wb, sizeof(wb), hdr.key_d, mac);
1857 memcpy(write + 10, mac, sizeof(mac));
1861 start_time = eof_time + DELAY_ICLASS_VICC_TO_VCD_READER;
1863 uint8_t resp[10] = {0};
1865 uint8_t tries = 3;
1866 while (tries-- > 0) {
1868 iclass_send_as_reader(write, write_len, &start_time, &eof_time, shallow_mod);
1870 if (tearoff_hook() == PM3_ETEAROFF) { // tearoff occurred
1871 res = false;
1872 switch_off();
1873 if (payload->req.send_reply) {
1874 reply_ng(CMD_HF_ICLASS_WRITEBL, PM3_ETEAROFF, (uint8_t *)&res, sizeof(bool));
1876 return;
1877 } else {
1879 uint16_t resp_len = 0;
1880 int res2 = GetIso15693AnswerFromTag(resp, sizeof(resp), ICLASS_READER_TIMEOUT_UPDATE, &eof_time, false, true, &resp_len);
1881 if (res2 == PM3_SUCCESS && resp_len == 10) {
1882 res = true;
1883 break;
1888 if (tries == 0) {
1889 res = false;
1890 goto out;
1893 // verify write
1894 if ((pagemap != PICOPASS_NON_SECURE_PAGEMODE) && (payload->req.blockno == 2)) {
1895 // check response. e-purse update swaps first and second half
1896 if (memcmp(payload->data + 4, resp, 4) || memcmp(payload->data, resp + 4, 4)) {
1897 res = false;
1898 goto out;
1900 } else if ((pagemap != PICOPASS_NON_SECURE_PAGEMODE) && (payload->req.blockno == 3 || payload->req.blockno == 4)) {
1901 // check response. Key updates always return 0xffffffffffffffff
1902 uint8_t all_ff[8] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
1903 if (memcmp(all_ff, resp, sizeof(all_ff))) {
1904 res = false;
1905 goto out;
1907 } else {
1908 // check response. All other updates return unchanged data
1909 if (memcmp(payload->data, resp, 8)) {
1910 res = false;
1911 goto out;
1915 out:
1916 switch_off();
1918 if (payload->req.send_reply) {
1919 reply_ng(CMD_HF_ICLASS_WRITEBL, PM3_SUCCESS, (uint8_t *)&res, sizeof(bool));
1923 void iclass_credit_epurse(iclass_credit_epurse_t *payload) {
1925 LED_A_ON();
1927 bool shallow_mod = payload->req.shallow_mod;
1929 Iso15693InitReader();
1931 // select tag.
1932 uint32_t eof_time = 0;
1933 picopass_hdr_t hdr = {0};
1934 uint8_t res = select_iclass_tag(&hdr, payload->req.use_credit_key, &eof_time, shallow_mod);
1935 if (res == false) {
1936 goto out;
1939 uint32_t start_time = eof_time + DELAY_ICLASS_VICC_TO_VCD_READER;
1941 uint8_t mac[4] = {0};
1943 // authenticate
1944 if (payload->req.do_auth) {
1946 res = authenticate_iclass_tag(&payload->req, &hdr, &start_time, &eof_time, mac);
1947 if (res == false) {
1948 goto out;
1952 start_time = eof_time + DELAY_ICLASS_VICC_TO_VCD_READER;
1954 uint8_t cmd_read[] = {ICLASS_CMD_READ_OR_IDENTIFY, payload->req.blockno, 0x00, 0x00};
1955 AddCrc(cmd_read + 1, 1);
1957 uint8_t epurse[10];
1958 res = iclass_send_cmd_with_retries(cmd_read, sizeof(cmd_read), epurse, sizeof(epurse), 10, 3, &start_time, ICLASS_READER_TIMEOUT_OTHERS, &eof_time, shallow_mod);
1959 if (!res) {
1960 switch_off();
1961 if (payload->req.send_reply) {
1962 reply_ng(CMD_HF_ICLASS_CREDIT_EPURSE, PM3_ETIMEOUT, (uint8_t *)&res, sizeof(uint8_t));
1964 return;
1967 uint8_t write[14] = { 0x80 | ICLASS_CMD_UPDATE, payload->req.blockno };
1968 uint8_t write_len = 14;
1970 uint8_t epurse_offset = 0;
1971 const uint8_t empty_epurse[] = {0xff, 0xff, 0xff, 0xff};
1972 if (memcmp(epurse, empty_epurse, 4) == 0) {
1973 // epurse data in stage 2
1974 epurse_offset = 4;
1977 memcpy(epurse + epurse_offset, payload->epurse, 4);
1979 // blank out debiting value as per the first step of the crediting procedure
1980 epurse[epurse_offset + 0] = 0xFF;
1981 epurse[epurse_offset + 1] = 0xFF;
1983 // initial epurse write for credit
1984 memcpy(write + 2, epurse, 8);
1986 doMAC_N(write + 1, 9, payload->req.use_credit_key ? hdr.key_c : hdr.key_d, mac);
1987 memcpy(write + 10, mac, sizeof(mac));
1989 start_time = eof_time + DELAY_ICLASS_VICC_TO_VCD_READER;
1991 uint8_t resp[10] = {0};
1993 uint8_t tries = 3;
1994 while (tries-- > 0) {
1996 iclass_send_as_reader(write, write_len, &start_time, &eof_time, shallow_mod);
1998 if (tearoff_hook() == PM3_ETEAROFF) { // tearoff occurred
1999 res = false;
2000 switch_off();
2001 if (payload->req.send_reply)
2002 reply_ng(CMD_HF_ICLASS_CREDIT_EPURSE, PM3_ETEAROFF, (uint8_t *)&res, sizeof(uint8_t));
2003 return;
2004 } else {
2006 uint16_t resp_len = 0;
2007 int res2 = GetIso15693AnswerFromTag(resp, sizeof(resp), ICLASS_READER_TIMEOUT_UPDATE, &eof_time, false, true, &resp_len);
2008 if (res2 == PM3_SUCCESS && resp_len == 10) {
2009 res = true;
2010 break;
2015 if (tries == 0) {
2016 res = false;
2017 goto out;
2020 // check response. e-purse update swaps first and second half
2021 if (memcmp(write + 2 + 4, resp, 4) || memcmp(write + 2, resp + 4, 4)) {
2022 res = false;
2023 goto out;
2026 // new epurse write
2027 // epurse offset is now flipped after the first write
2028 epurse_offset ^= 4;
2029 memcpy(resp + epurse_offset, payload->epurse, 4);
2030 memcpy(write + 2, resp, 8);
2032 doMAC_N(write + 1, 9, payload->req.use_credit_key ? hdr.key_c : hdr.key_d, mac);
2033 memcpy(write + 10, mac, sizeof(mac));
2035 start_time = eof_time + DELAY_ICLASS_VICC_TO_VCD_READER;
2037 tries = 3;
2038 while (tries-- > 0) {
2040 iclass_send_as_reader(write, write_len, &start_time, &eof_time, shallow_mod);
2042 if (tearoff_hook() == PM3_ETEAROFF) { // tearoff occurred
2043 res = false;
2044 switch_off();
2045 if (payload->req.send_reply)
2046 reply_ng(CMD_HF_ICLASS_CREDIT_EPURSE, PM3_ETEAROFF, (uint8_t *)&res, sizeof(uint8_t));
2047 return;
2048 } else {
2050 uint16_t resp_len = 0;
2051 int res2 = GetIso15693AnswerFromTag(resp, sizeof(resp), ICLASS_READER_TIMEOUT_UPDATE, &eof_time, false, true, &resp_len);
2052 if (res2 == PM3_SUCCESS && resp_len == 10) {
2053 res = true;
2054 break;
2059 if (tries == 0) {
2060 res = false;
2061 goto out;
2064 // check response. e-purse update swaps first and second half
2065 if (memcmp(write + 2 + 4, resp, 4) || memcmp(write + 2, resp + 4, 4)) {
2066 res = false;
2067 goto out;
2070 out:
2071 switch_off();
2073 if (payload->req.send_reply)
2074 reply_ng(CMD_HF_ICLASS_CREDIT_EPURSE, PM3_SUCCESS, (uint8_t *)&res, sizeof(uint8_t));
2077 void iClass_Restore(iclass_restore_req_t *msg) {
2079 // sanitation
2080 if (msg == NULL) {
2081 reply_ng(CMD_HF_ICLASS_RESTORE, PM3_ESOFT, NULL, 0);
2082 return;
2085 if (msg->item_cnt == 0) {
2086 if (msg->req.send_reply) {
2087 reply_ng(CMD_HF_ICLASS_RESTORE, PM3_ESOFT, NULL, 0);
2089 return;
2092 bool shallow_mod = msg->req.shallow_mod;
2094 LED_A_ON();
2095 Iso15693InitReader();
2097 uint16_t written = 0;
2098 uint32_t eof_time = 0;
2099 picopass_hdr_t hdr = {0};
2101 // select
2102 bool res = select_iclass_tag(&hdr, msg->req.use_credit_key, &eof_time, shallow_mod);
2103 if (res == false) {
2104 goto out;
2107 // authenticate
2108 uint8_t mac[4] = {0};
2109 uint32_t start_time = eof_time + DELAY_ICLASS_VICC_TO_VCD_READER;
2111 // authenticate
2112 if (msg->req.do_auth) {
2113 res = authenticate_iclass_tag(&msg->req, &hdr, &start_time, &eof_time, mac);
2114 if (res == false) {
2115 goto out;
2119 // main loop
2120 bool use_mac;
2121 for (uint8_t i = 0; i < msg->item_cnt; i++) {
2123 iclass_restore_item_t item = msg->blocks[i];
2125 uint8_t pagemap = get_pagemap(&hdr);
2126 if (pagemap == PICOPASS_NON_SECURE_PAGEMODE) {
2127 // Unsecured tags uses CRC16
2128 use_mac = false;
2129 } else {
2130 // Secure tags uses MAC
2131 use_mac = true;
2132 uint8_t wb[9] = {0};
2133 wb[0] = item.blockno;
2134 memcpy(wb + 1, item.data, 8);
2136 if (msg->req.use_credit_key)
2137 doMAC_N(wb, sizeof(wb), hdr.key_c, mac);
2138 else
2139 doMAC_N(wb, sizeof(wb), hdr.key_d, mac);
2142 // data + mac
2143 if (iclass_writeblock_ext(item.blockno, item.data, mac, use_mac, shallow_mod)) {
2144 Dbprintf("Write block [%3d/0x%02X] " _GREEN_("successful"), item.blockno, item.blockno);
2145 written++;
2146 } else {
2147 Dbprintf("Write block [%3d/0x%02X] " _RED_("failed"), item.blockno, item.blockno);
2151 out:
2153 switch_off();
2154 if (msg->req.send_reply) {
2155 int isOK = (written == msg->item_cnt) ? PM3_SUCCESS : PM3_ESOFT;
2156 reply_ng(CMD_HF_ICLASS_RESTORE, isOK, NULL, 0);
2160 static void generate_single_key_block_inverted_opt(const uint8_t *startingKey, uint32_t index, uint8_t *keyBlock) {
2162 uint8_t bits_index = index / 16383;
2163 uint8_t ending_bits[] = { //all possible 70 combinations of 4x0 and 4x1 as key ending bits
2164 0x0F, 0x17, 0x1B, 0x1D, 0x1E, 0x27, 0x2B, 0x2D, 0x2E, 0x33,
2165 0x35, 0x36, 0x39, 0x3A, 0x3C, 0x47, 0x4B, 0x4D, 0x4E, 0x53,
2166 0x55, 0x56, 0x59, 0x5A, 0x5C, 0x63, 0x65, 0x66, 0x69, 0x6A,
2167 0x6C, 0x71, 0x72, 0x74, 0x78, 0x87, 0x8B, 0x8D, 0x8E, 0x93,
2168 0x95, 0x96, 0x99, 0x9A, 0x9C, 0xA3, 0xA5, 0xA6, 0xA9, 0xAA,
2169 0xAC, 0xB1, 0xB2, 0xB4, 0xB8, 0xC3, 0xC5, 0xC6, 0xC9, 0xCA,
2170 0xCC, 0xD1, 0xD2, 0xD4, 0xD8, 0xE1, 0xE2, 0xE4, 0xE8, 0xF0
2173 uint8_t binary_endings[8]; // Array to store binary values for each ending bit
2174 // Extract each bit from the ending_bits[k] and store it in binary_endings
2175 uint8_t ending = ending_bits[bits_index];
2176 for (int i = 7; i >= 0; i--) {
2177 binary_endings[i] = ending & 1;
2178 ending >>= 1;
2181 uint8_t binary_mids[8]; // Array to store the 2-bit chunks of index
2182 // Iterate over the 16-bit integer and store 2 bits at a time in the result array
2183 for (int i = 0; i < 8; i++) {
2184 // Shift and mask to get 2 bits and store them as an 8-bit value
2185 binary_mids[7 - i] = (index >> (i * 2)) & 0x03; // 0x03 is a mask for 2 bits (binary 11)
2187 memcpy(keyBlock, startingKey, PICOPASS_BLOCK_SIZE);
2189 // Start from the second byte, index 1 as we're never gonna touch the first byte
2190 for (int i = 1; i < PICOPASS_BLOCK_SIZE; i++) {
2191 // Clear the last bit of the current byte (AND with 0xFE)
2192 keyBlock[i] &= 0xF8;
2193 // Set the last bit to the corresponding value from binary_endings (OR with binary_endings[i])
2194 keyBlock[i] |= ((binary_mids[i] & 0x03) << 1) | (binary_endings[i] & 0x01);
2198 void iClass_Recover(iclass_recover_req_t *msg) {
2200 bool shallow_mod = false;
2201 uint8_t zero_key[PICOPASS_BLOCK_SIZE] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
2202 uint8_t genkeyblock[PICOPASS_BLOCK_SIZE] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
2203 uint32_t index = msg->index;
2204 int bits_found = -1;
2205 bool recovered = false;
2206 bool completed = false;
2207 uint8_t div_key2[8] = {0};
2208 uint32_t eof_time = 0;
2209 uint32_t start_time = 0;
2210 uint8_t read_check_cc[] = { 0x80 | ICLASS_CMD_READCHECK, 0x18 }; //block 24
2211 read_check_cc[0] = 0x10 | ICLASS_CMD_READCHECK; //use credit key
2212 uint8_t read_check_cc2[] = { 0x80 | ICLASS_CMD_READCHECK, 0x02 }; //block 2 -> to check Kd macs
2214 /* iclass_mac_table is a series of weak macs, those weak macs correspond to the different combinations of the last 3 bits of each key byte. */
2216 static uint8_t iclass_mac_table[8][8] = { //Reference weak macs table
2217 { 0x00, 0x00, 0x00, 0x00, 0xBF, 0x5D, 0x67, 0x7F }, //Expected mac when last 3 bits of each byte are: 000
2218 { 0x00, 0x00, 0x00, 0x00, 0x10, 0xED, 0x6F, 0x11 }, //Expected mac when last 3 bits of each byte are: 001
2219 { 0x00, 0x00, 0x00, 0x00, 0x53, 0x35, 0x42, 0x0F }, //Expected mac when last 3 bits of each byte are: 010
2220 { 0x00, 0x00, 0x00, 0x00, 0xAB, 0x47, 0x4D, 0xA0 }, //Expected mac when last 3 bits of each byte are: 011
2221 { 0x00, 0x00, 0x00, 0x00, 0xF6, 0xCF, 0x43, 0x36 }, //Expected mac when last 3 bits of each byte are: 100
2222 { 0x00, 0x00, 0x00, 0x00, 0x59, 0x7F, 0x4B, 0x58 }, //Expected mac when last 3 bits of each byte are: 101
2223 { 0x00, 0x00, 0x00, 0x00, 0x1A, 0xA7, 0x66, 0x46 }, //Expected mac when last 3 bits of each byte are: 110
2224 { 0x00, 0x00, 0x00, 0x00, 0xE2, 0xD5, 0x69, 0xE9 } //Expected mac when last 3 bits of each byte are: 111
2227 LED_A_ON();
2228 DbpString(_RED_("Interrupting this process will render the card unusable!"));
2229 memcpy(div_key2, msg->nfa, 8);
2231 //START LOOP
2232 uint32_t loops = 1;
2234 while (bits_found == -1) {
2235 bool card_select = false;
2236 bool card_auth = false;
2237 int reinit_tentatives = 0;
2238 uint8_t original_mac[8] = {0};
2239 uint16_t resp_len = 0;
2240 int res2;
2241 uint8_t resp[10] = {0};
2242 uint8_t mac1[4] = {0};
2243 uint8_t mac2[4] = {0};
2244 picopass_hdr_t hdr = {0};
2245 bool res = false;
2247 while (!card_select || !card_auth) {
2248 Iso15693InitReader(); //has to be at the top as it starts tracing
2249 if (!msg->debug) {
2250 set_tracing(false); //disable tracing to prevent crashes - set to true for debugging
2251 } else {
2252 if (loops == 1) {
2253 clear_trace(); //if we're debugging better to clear the trace but do it only on the first loop
2256 if (msg->test) {
2257 Dbprintf(_YELLOW_("*Cycled Reader*") " ----------------- TEST Index - Loops: "_YELLOW_("%3d / %3d") " --------------*", loops, msg->loop);
2258 } else {
2259 Dbprintf(_YELLOW_("*Cycled Reader*") " ----------------- Index: "_RED_("%3d")" Loops: "_YELLOW_("%3d / %3d") " --------------*", index, loops, msg->loop);
2261 //Step0 Card Select Routine
2262 eof_time = 0; //reset eof time
2263 res = select_iclass_tag(&hdr, false, &eof_time, shallow_mod);
2264 if (res == false) {
2265 DbpString(_RED_("Unable to select card after reader cycle! Retrying..."));
2266 } else {
2267 DbpString(_GREEN_("Card selected successfully!"));
2268 card_select = true;
2271 //Step1 Authenticate with AA1 using trace
2272 if (card_select) {
2273 memcpy(original_mac, msg->req.key, 8);
2274 start_time = eof_time + DELAY_ICLASS_VICC_TO_VCD_READER;
2275 res = authenticate_iclass_tag(&msg->req, &hdr, &start_time, &eof_time, mac1);
2276 if (res == false) {
2277 DbpString(_RED_("Unable to authenticate on AA1 using macs! Retrying..."));
2278 } else {
2279 DbpString(_GREEN_("AA1 authentication with macs successful!"));
2280 card_auth = true;
2283 if (!card_auth || !card_select) {
2284 reinit_tentatives++;
2285 switch_off();
2287 if (reinit_tentatives == 5) {
2288 DbpString(_RED_("Unable to select or authenticate with card multiple times! Stopping."));
2289 goto out;
2293 //Step2 Privilege Escalation: attempt to read AA2 with credentials for AA1
2294 uint8_t blockno = 24;
2295 uint8_t cmd_read[] = {ICLASS_CMD_READ_OR_IDENTIFY, blockno, 0x00, 0x00};
2296 AddCrc(cmd_read + 1, 1);
2297 int priv_esc_tries = 0;
2298 bool priv_esc = false;
2299 while (!priv_esc) {
2300 //The privilege escalation is done with a readcheck and not just a normal read!
2301 iclass_send_as_reader(read_check_cc, sizeof(read_check_cc), &start_time, &eof_time, shallow_mod);
2302 // expect a 8-byte response here
2303 res2 = GetIso15693AnswerFromTag(resp, sizeof(resp), ICLASS_READER_TIMEOUT_OTHERS, &eof_time, false, true, &resp_len);
2304 if (res2 != PM3_SUCCESS || resp_len != 8) {
2305 DbpString(_YELLOW_("Privilege Escalation -> ")_RED_("Read failed! Trying again..."));
2306 priv_esc_tries++;
2307 } else {
2308 DbpString(_YELLOW_("Privilege Escalation -> ")_GREEN_("Response OK!"));
2309 priv_esc = true;
2311 if (priv_esc_tries == 5) {
2312 DbpString(_RED_("Unable to complete privilege escalation! Stopping."));
2313 goto out;
2317 //Step3 Calculate New Key (Optimised Algo V2)
2318 generate_single_key_block_inverted_opt(zero_key, index, genkeyblock);
2319 if (msg->test) {
2320 memcpy(genkeyblock, zero_key, PICOPASS_BLOCK_SIZE);
2323 //Step4 Calculate New Mac
2325 uint8_t wb[9] = {0};
2326 blockno = 3;
2327 wb[0] = blockno;
2328 memcpy(wb + 1, genkeyblock, 8);
2329 doMAC_N(wb, sizeof(wb), div_key2, mac2);
2330 bool use_mac = true;
2331 bool written = false;
2332 bool write_error = false;
2333 while (written == false && write_error == false) {
2334 //Step5 Perform Write
2335 if (iclass_writeblock_ext(blockno, genkeyblock, mac2, use_mac, shallow_mod)) {
2336 DbpString("Wrote key: ");
2337 Dbhexdump(8, genkeyblock, false);
2339 //Reset cypher state
2340 iclass_send_as_reader(read_check_cc2, sizeof(read_check_cc2), &start_time, &eof_time, shallow_mod);
2341 res2 = GetIso15693AnswerFromTag(resp, sizeof(resp), ICLASS_READER_TIMEOUT_OTHERS, &eof_time, false, true, &resp_len);
2342 //try to authenticate with the original mac to verify the write happened
2343 memcpy(msg->req.key, original_mac, 8);
2344 res = authenticate_iclass_tag(&msg->req, &hdr, &start_time, &eof_time, mac1);
2345 if (msg->test) {
2346 if (res != true) {
2347 DbpString(_RED_("*** CARD EPURSE IS SILENT! RISK OF BRICKING! DO NOT EXECUTE KEY UPDATES! SCAN IT ON READER FOR EPURSE UPDATE, COLLECT NEW TRACES AND TRY AGAIN! ***"));
2348 goto out;
2349 } else {
2350 DbpString(_GREEN_("*** CARD EPURSE IS LOUD! OK TO ATTEMPT KEY RETRIEVAL! RUN AGAIN WITH -notest ***"));
2351 completed = true;
2352 goto out;
2354 } else {
2355 if (res != true) {
2356 DbpString("Write Operation : "_GREEN_("VERIFIED! Card Key Updated!"));
2357 written = true;
2358 } else {
2359 DbpString("Write Operation : "_RED_("FAILED! Card Key is the Original. Retrying..."));
2360 write_error = true;
2365 if (!write_error) {
2366 //Step6 Perform 8 authentication attempts + 1 to verify if we found the weak key
2367 for (int i = 0; i < 8 ; ++i) {
2368 iclass_send_as_reader(read_check_cc2, sizeof(read_check_cc2), &start_time, &eof_time, shallow_mod);
2369 res2 = GetIso15693AnswerFromTag(resp, sizeof(resp), ICLASS_READER_TIMEOUT_OTHERS, &eof_time, false, true, &resp_len);
2370 //need to craft the authentication payload accordingly
2371 memcpy(msg->req.key, iclass_mac_table[i], 8);
2372 res = authenticate_iclass_tag(&msg->req, &hdr, &start_time, &eof_time, mac1); //mac1 here shouldn't matter
2373 if (res == true) {
2374 bits_found = i;
2375 DbpString(_RED_("--------------------------------------------------------"));
2376 Dbprintf("Decimal Value of last 3 bits: " _GREEN_("[%3d]"), bits_found);
2377 DbpString(_RED_("--------------------------------------------------------"));
2378 recovered = true;
2382 //regardless of bits being found, restore the original key and verify it
2383 bool reverted = false;
2384 uint8_t revert_retries = 0;
2385 while (!reverted) {
2386 //Regain privilege escalation with a readcheck
2387 iclass_send_as_reader(read_check_cc, sizeof(read_check_cc), &start_time, &eof_time, shallow_mod);
2388 res2 = GetIso15693AnswerFromTag(resp, sizeof(resp), ICLASS_READER_TIMEOUT_OTHERS, &eof_time, false, true, &resp_len);
2390 DbpString(_YELLOW_("Attempting to restore the original key. "));
2391 if (iclass_writeblock_ext(blockno, genkeyblock, mac2, use_mac, shallow_mod)) {
2392 DbpString("Restore of Original Key "_GREEN_("successful."));
2393 } else {
2394 DbpString("Restore of Original Key " _RED_("failed."));
2396 DbpString(_YELLOW_("Verifying Key Restore..."));
2397 //Do a readcheck first to reset the cypher state
2398 iclass_send_as_reader(read_check_cc2, sizeof(read_check_cc2), &start_time, &eof_time, shallow_mod);
2399 res2 = GetIso15693AnswerFromTag(resp, sizeof(resp), ICLASS_READER_TIMEOUT_OTHERS, &eof_time, false, true, &resp_len);
2401 //need to craft the authentication payload accordingly
2402 memcpy(msg->req.key, original_mac, 8);
2403 res = authenticate_iclass_tag(&msg->req, &hdr, &start_time, &eof_time, mac1);
2404 if (res == true) {
2405 DbpString("Restore of Original Key "_GREEN_("VERIFIED! Card is usable again."));
2406 reverted = true;
2407 if (recovered) {
2408 goto restore;
2410 } else {
2411 DbpString("Restore of Original Key "_RED_("VERIFICATION FAILED! Trying again..."));
2414 revert_retries++;
2415 if (revert_retries >= 7) { //must always be an odd number!
2416 Dbprintf(_RED_("Attempted to restore original key for %3d times and failed. Stopping. Card is likely unusable."), revert_retries);
2417 goto out;
2423 if (loops >= msg->loop) {
2424 completed = true;
2425 goto out;
2427 if (!write_error) { //if there was a write error, re-run the loop for the same key index
2428 loops++;
2429 index++;
2432 }//end while
2435 restore:
2436 ;//empty statement for compilation
2437 uint8_t partialkey[PICOPASS_BLOCK_SIZE] = {0};
2439 for (int i = 0; i < PICOPASS_BLOCK_SIZE; i++) {
2440 partialkey[i] = genkeyblock[i] ^ bits_found;
2443 //Print the 24 bits found from k1
2444 DbpString(_RED_("--------------------------------------------------------"));
2445 DbpString(_RED_("SUCCESS! Raw Key Partial Bytes: "));
2446 Dbhexdump(8, partialkey, false);
2447 DbpString(_RED_("--------------------------------------------------------"));
2448 switch_off();
2449 reply_ng(CMD_HF_ICLASS_RECOVER, PM3_SUCCESS, NULL, 0);
2452 out:
2454 switch_off();
2455 if (completed) {
2456 reply_ng(CMD_HF_ICLASS_RECOVER, PM3_EINVARG, NULL, 0);
2457 } else {
2458 reply_ng(CMD_HF_ICLASS_RECOVER, PM3_ESOFT, NULL, 0);