]> git.zerfleddert.de Git - proxmark3-svn/blame - client/cmdhficlass.c
Moved iclass crc to be based on a lookup table
[proxmark3-svn] / client / cmdhficlass.c
CommitLineData
cee5a30d 1//-----------------------------------------------------------------------------
2// Copyright (C) 2010 iZsh <izsh at fail0verflow.com>, Hagen Fritsch
3// Copyright (C) 2011 Gerhard de Koning Gans
26c0d833 4// Copyright (C) 2014 Midnitesnake & Andy Davies & Martin Holst Swende
cee5a30d 5//
6// This code is licensed to you under the terms of the GNU GPL, version 2 or,
7// at your option, any later version. See the LICENSE.txt file for the text of
8// the license.
9//-----------------------------------------------------------------------------
10// High frequency iClass commands
11//-----------------------------------------------------------------------------
12
13#include <stdio.h>
14#include <stdlib.h>
15#include <string.h>
9f6e9d15 16#include <sys/stat.h>
cee5a30d 17#include "iso14443crc.h" // Can also be used for iClass, using 0xE012 as CRC-type
18#include "data.h"
28fdb04f 19//#include "proxusb.h"
902cb3c0 20#include "proxmark3.h"
cee5a30d 21#include "ui.h"
22#include "cmdparser.h"
23#include "cmdhficlass.h"
24#include "common.h"
14006804 25#include "util.h"
17cba269 26#include "cmdmain.h"
a66fca86
AD
27#include "loclass/des.h"
28#include "loclass/cipherutils.h"
29#include "loclass/cipher.h"
30#include "loclass/ikeys.h"
3ad48540
MHS
31#include "loclass/elite_crack.h"
32#include "loclass/fileutils.h"
cee5a30d 33
34static int CmdHelp(const char *Cmd);
35
17cba269
MHS
36int xorbits_8(uint8_t val)
37{
3ad48540
MHS
38 uint8_t res = val ^ (val >> 1); //1st pass
39 res = res ^ (res >> 1); // 2nd pass
40 res = res ^ (res >> 2); // 3rd pass
41 res = res ^ (res >> 4); // 4th pass
42 return res & 1;
17cba269
MHS
43}
44
c8dd9b09
MHS
45#define ICLASS_CMD_ACTALL 0x0A
46#define ICLASS_CMD_IDENTIFY 0x0C
47#define ICLASS_CMD_READ 0x0C
48
49#define ICLASS_CMD_SELECT 0x81
50#define ICLASS_CMD_PAGESEL 0x84
51#define ICLASS_CMD_READCHECK 0x88
52#define ICLASS_CMD_CHECK 0x05
53#define ICLASS_CMD_SOF 0x0F
54#define ICLASS_CMD_HALT 0x00
55
56
2e9d4b3f
MHS
57void explain(char *exp, size_t size, uint8_t* cmd, uint8_t cmdsize)
58{
59
c8dd9b09
MHS
60 if(cmdsize > 1 && cmd[0] == ICLASS_CMD_READ)
61 {
62 snprintf(exp,size,"READ(%d)",cmd[1]);
63 return;
64 }
65
2e9d4b3f
MHS
66 switch(cmd[0])
67 {
c8dd9b09
MHS
68 case ICLASS_CMD_ACTALL: snprintf(exp,size,"ACTALL"); break;
69 case ICLASS_CMD_IDENTIFY: snprintf(exp,size,"IDENTIFY"); break;
70 case ICLASS_CMD_SELECT: snprintf(exp,size,"SELECT"); break;
71 case ICLASS_CMD_PAGESEL: snprintf(exp,size,"PAGESEL"); break;
72 case ICLASS_CMD_READCHECK: snprintf(exp,size,"READCHECK"); break;
73 case ICLASS_CMD_CHECK: snprintf(exp,size,"CHECK"); break;
74 case ICLASS_CMD_SOF: snprintf(exp,size,"SOF"); break;
75 case ICLASS_CMD_HALT: snprintf(exp,size,"HALT"); break;
76 default: snprintf(exp,size,"?"); break;
2e9d4b3f
MHS
77 }
78 return;
79}
80
cee5a30d 81int CmdHFiClassList(const char *Cmd)
17cba269 82{
4c3de57a 83 PrintAndLog("Deprecated command, use 'hf list iclass' instead");
17cba269
MHS
84 return 0;
85}
86
cee5a30d 87int CmdHFiClassSnoop(const char *Cmd)
88{
89 UsbCommand c = {CMD_SNOOP_ICLASS};
90 SendCommand(&c);
91 return 0;
92}
6116c796 93#define NUM_CSNS 15
1e262141 94int CmdHFiClassSim(const char *Cmd)
95{
96 uint8_t simType = 0;
97 uint8_t CSN[8] = {0, 0, 0, 0, 0, 0, 0, 0};
98
17cba269
MHS
99 if (strlen(Cmd)<1) {
100 PrintAndLog("Usage: hf iclass sim [0 <CSN>] | x");
101 PrintAndLog(" options");
102 PrintAndLog(" 0 <CSN> simulate the given CSN");
103 PrintAndLog(" 1 simulate default CSN");
104 PrintAndLog(" 2 iterate CSNs, gather MACs");
1e262141 105 PrintAndLog(" sample: hf iclass sim 0 031FEC8AF7FF12E0");
17cba269 106 PrintAndLog(" sample: hf iclass sim 2");
1e262141 107 return 0;
108 }
109
110 simType = param_get8(Cmd, 0);
17cba269
MHS
111
112 if(simType == 0)
113 {
114 if (param_gethex(Cmd, 1, CSN, 16)) {
115 PrintAndLog("A CSN should consist of 16 HEX symbols");
116 return 1;
117 }
118 PrintAndLog("--simtype:%02x csn:%s", simType, sprint_hex(CSN, 8));
119
120 }
77abe781 121 if(simType > 2)
17cba269
MHS
122 {
123 PrintAndLog("Undefined simptype %d", simType);
124 return 1;
1e262141 125 }
17cba269 126 uint8_t numberOfCSNs=0;
1e262141 127
9f6e9d15
MHS
128 if(simType == 2)
129 {
6116c796 130 UsbCommand c = {CMD_SIMULATE_TAG_ICLASS, {simType,NUM_CSNS}};
9f6e9d15 131 UsbCommand resp = {0};
17cba269 132
6116c796 133 /*uint8_t csns[8 * NUM_CSNS] = {
77abe781
MHS
134 0x00,0x0B,0x0F,0xFF,0xF7,0xFF,0x12,0xE0 ,
135 0x00,0x13,0x94,0x7e,0x76,0xff,0x12,0xe0 ,
136 0x2a,0x99,0xac,0x79,0xec,0xff,0x12,0xe0 ,
137 0x17,0x12,0x01,0xfd,0xf7,0xff,0x12,0xe0 ,
138 0xcd,0x56,0x01,0x7c,0x6f,0xff,0x12,0xe0 ,
139 0x4b,0x5e,0x0b,0x72,0xef,0xff,0x12,0xe0 ,
140 0x00,0x73,0xd8,0x75,0x58,0xff,0x12,0xe0 ,
141 0x0c,0x90,0x32,0xf3,0x5d,0xff,0x12,0xe0 };
6116c796
MHS
142*/
143
144 uint8_t csns[8*NUM_CSNS] = {
145 0x00, 0x0B, 0x0F, 0xFF, 0xF7, 0xFF, 0x12, 0xE0,
146 0x00, 0x04, 0x0E, 0x08, 0xF7, 0xFF, 0x12, 0xE0,
147 0x00, 0x09, 0x0D, 0x05, 0xF7, 0xFF, 0x12, 0xE0,
148 0x00, 0x0A, 0x0C, 0x06, 0xF7, 0xFF, 0x12, 0xE0,
149 0x00, 0x0F, 0x0B, 0x03, 0xF7, 0xFF, 0x12, 0xE0,
150 0x00, 0x08, 0x0A, 0x0C, 0xF7, 0xFF, 0x12, 0xE0,
151 0x00, 0x0D, 0x09, 0x09, 0xF7, 0xFF, 0x12, 0xE0,
152 0x00, 0x0E, 0x08, 0x0A, 0xF7, 0xFF, 0x12, 0xE0,
153 0x00, 0x03, 0x07, 0x17, 0xF7, 0xFF, 0x12, 0xE0,
154 0x00, 0x3C, 0x06, 0xE0, 0xF7, 0xFF, 0x12, 0xE0,
155 0x00, 0x01, 0x05, 0x1D, 0xF7, 0xFF, 0x12, 0xE0,
156 0x00, 0x02, 0x04, 0x1E, 0xF7, 0xFF, 0x12, 0xE0,
157 0x00, 0x07, 0x03, 0x1B, 0xF7, 0xFF, 0x12, 0xE0,
158 0x00, 0x00, 0x02, 0x24, 0xF7, 0xFF, 0x12, 0xE0,
159 0x00, 0x05, 0x01, 0x21, 0xF7, 0xFF, 0x12, 0xE0 };
160
161 memcpy(c.d.asBytes, csns, 8*NUM_CSNS);
9f6e9d15
MHS
162
163 SendCommand(&c);
164 if (!WaitForResponseTimeout(CMD_ACK, &resp, -1)) {
165 PrintAndLog("Command timed out");
166 return 0;
167 }
1e262141 168
77abe781 169 uint8_t num_mac_responses = resp.arg[1];
6116c796 170 PrintAndLog("Mac responses: %d MACs obtained (should be %d)", num_mac_responses,NUM_CSNS);
9f6e9d15 171
6116c796 172 size_t datalen = NUM_CSNS*24;
9f6e9d15
MHS
173 /*
174 * Now, time to dump to file. We'll use this format:
77abe781 175 * <8-byte CSN><8-byte CC><4 byte NR><4 byte MAC>....
9f6e9d15 176 * So, it should wind up as
77abe781
MHS
177 * 8 * 24 bytes.
178 *
179 * The returndata from the pm3 is on the following format
180 * <4 byte NR><4 byte MAC>
181 * CC are all zeroes, CSN is the same as was sent in
9f6e9d15 182 **/
77abe781
MHS
183 void* dump = malloc(datalen);
184 memset(dump,0,datalen);//<-- Need zeroes for the CC-field
9f6e9d15 185 uint8_t i = 0;
6116c796 186 for(i = 0 ; i < NUM_CSNS ; i++)
9f6e9d15 187 {
77abe781
MHS
188 memcpy(dump+i*24, csns+i*8,8); //CSN
189 //8 zero bytes here...
190 //Then comes NR_MAC (eight bytes from the response)
191 memcpy(dump+i*24+16,resp.d.asBytes+i*8,8);
1e262141 192
9f6e9d15
MHS
193 }
194 /** Now, save to dumpfile **/
77abe781
MHS
195 saveFile("iclass_mac_attack", "bin", dump,datalen);
196 free(dump);
9f6e9d15
MHS
197 }else
198 {
199 UsbCommand c = {CMD_SIMULATE_TAG_ICLASS, {simType,numberOfCSNs}};
200 memcpy(c.d.asBytes, CSN, 8);
201 SendCommand(&c);
202 }
1e262141 203
1e262141 204 return 0;
205}
206
207int CmdHFiClassReader(const char *Cmd)
208{
aa41c605 209 UsbCommand c = {CMD_READER_ICLASS, {0}};
1e262141 210 SendCommand(&c);
aa41c605
MHS
211 UsbCommand resp;
212 while(!ukbhit()){
213 if (WaitForResponseTimeout(CMD_ACK,&resp,4500)) {
214 uint8_t isOK = resp.arg[0] & 0xff;
215 uint8_t * data = resp.d.asBytes;
216
217 PrintAndLog("isOk:%02x", isOK);
2e9d4b3f
MHS
218 if( isOK == 0){
219 //Aborted
220 PrintAndLog("Quitting...");
221 return 0;
222 }
aa41c605
MHS
223 if(isOK > 0)
224 {
225 PrintAndLog("CSN: %s",sprint_hex(data,8));
226 }
227 if(isOK >= 1)
228 {
229 PrintAndLog("CC: %s",sprint_hex(data+8,8));
230 }else{
231 PrintAndLog("No CC obtained");
232 }
233 } else {
234 PrintAndLog("Command execute timeout");
235 }
236 }
1e262141 237
c3963755 238 return 0;
239}
240
241int CmdHFiClassReader_Replay(const char *Cmd)
242{
243 uint8_t readerType = 0;
244 uint8_t MAC[4]={0x00, 0x00, 0x00, 0x00};
245
246 if (strlen(Cmd)<1) {
247 PrintAndLog("Usage: hf iclass replay <MAC>");
248 PrintAndLog(" sample: hf iclass replay 00112233");
249 return 0;
250 }
251
252 if (param_gethex(Cmd, 0, MAC, 8)) {
253 PrintAndLog("MAC must include 8 HEX symbols");
254 return 1;
255 }
256
257 UsbCommand c = {CMD_READER_ICLASS_REPLAY, {readerType}};
258 memcpy(c.d.asBytes, MAC, 4);
259 SendCommand(&c);
1e262141 260
261 return 0;
262}
263
a66fca86
AD
264int CmdHFiClassReader_Dump(const char *Cmd)
265{
266 uint8_t readerType = 0;
267 uint8_t MAC[4]={0x00,0x00,0x00,0x00};
268 uint8_t KEY[8]={0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
269 uint8_t CSN[8]={0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
270 uint8_t CCNR[12]={0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
fecd8202 271 //uint8_t CC_temp[8]={0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
a66fca86 272 uint8_t div_key[8]={0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
9b82de75
MHS
273 uint8_t keytable[128] = {0};
274 int elite = 0;
275 uint8_t *used_key;
276 int i;
fecd8202 277 if (strlen(Cmd)<1)
278 {
9b82de75
MHS
279 PrintAndLog("Usage: hf iclass dump <Key> [e]");
280 PrintAndLog(" Key - A 16 byte master key");
281 PrintAndLog(" e - If 'e' is specified, the key is interpreted as the 16 byte");
282 PrintAndLog(" Custom Key (KCus), which can be obtained via reader-attack");
283 PrintAndLog(" See 'hf iclass sim 2'. This key should be on iclass-format");
fecd8202 284 PrintAndLog(" sample: hf iclass dump 0011223344556677");
9b82de75
MHS
285
286
a66fca86
AD
287 return 0;
288 }
289
fecd8202 290 if (param_gethex(Cmd, 0, KEY, 16))
291 {
a66fca86
AD
292 PrintAndLog("KEY must include 16 HEX symbols");
293 return 1;
294 }
9b82de75
MHS
295
296 if (param_getchar(Cmd, 1) == 'e')
297 {
298 PrintAndLog("Elite switch on");
299 elite = 1;
300
301 //calc h2
302 hash2(KEY, keytable);
9e28ee9f 303 printarr_human_readable("keytable", keytable, 128);
9b82de75
MHS
304
305 }
306
0eea34a2
MHS
307 UsbCommand resp;
308 uint8_t key_sel[8] = {0};
309 uint8_t key_sel_p[8] = { 0 };
310
311 //HACK -- Below is for testing without access to a tag
0eea34a2 312 uint8_t fake_dummy_test = false;
8e976839
MHS
313 if(fake_dummy_test)
314 {
315 uint8_t xdata[16] = {0x01,0x02,0x03,0x04,0xF7,0xFF,0x12,0xE0, //CSN from http://www.proxmark.org/forum/viewtopic.php?pid=11230#p11230
316 0xFE,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF}; // Just a random CC. Would be good to add a real testcase here
317 memcpy(resp.d.asBytes,xdata, 16);
318 resp.arg[0] = 2;
319 }
320
0eea34a2
MHS
321 //End hack
322
9b82de75 323
aa41c605 324 UsbCommand c = {CMD_READER_ICLASS, {0}};
c8dd9b09 325 c.arg[0] = FLAG_ICLASS_READER_ONLY_ONCE| FLAG_ICLASS_READER_GET_CC;
0eea34a2
MHS
326 if(!fake_dummy_test)
327 SendCommand(&c);
fecd8202 328
26c0d833 329
0eea34a2
MHS
330
331 if (fake_dummy_test || WaitForResponseTimeout(CMD_ACK,&resp,4500)) {
26c0d833
MHS
332 uint8_t isOK = resp.arg[0] & 0xff;
333 uint8_t * data = resp.d.asBytes;
334
26c0d833
MHS
335 memcpy(CSN,data,8);
336 memcpy(CCNR,data+8,8);
3ad48540 337
26c0d833 338 PrintAndLog("isOk:%02x", isOK);
a66fca86 339
aa41c605 340 if(isOK > 0)
26c0d833
MHS
341 {
342 PrintAndLog("CSN: %s",sprint_hex(CSN,8));
343 }
9b82de75 344 if(isOK > 1)
26c0d833 345 {
9b82de75
MHS
346 if(elite)
347 {
9b82de75
MHS
348 //Get the key index (hash1)
349 uint8_t key_index[8] = {0};
350
351 hash1(CSN, key_index);
352 printvar("hash1", key_index,8);
353 for(i = 0; i < 8 ; i++)
354 key_sel[i] = keytable[key_index[i]] & 0xFF;
0eea34a2 355 PrintAndLog("Pre-fortified 'permuted' HS key that would be needed by an iclass reader to talk to above CSN:");
9b82de75
MHS
356 printvar("k_sel", key_sel,8);
357 //Permute from iclass format to standard format
358 permutekey_rev(key_sel,key_sel_p);
359 used_key = key_sel_p;
360 }else{
9e28ee9f
MHS
361 //Perhaps this should also be permuted to std format?
362 // Something like the code below? I have no std system
363 // to test this with /Martin
364
365 //uint8_t key_sel_p[8] = { 0 };
366 //permutekey_rev(KEY,key_sel_p);
367 //used_key = key_sel_p;
368
9b82de75
MHS
369 used_key = KEY;
370
371 }
0eea34a2
MHS
372
373 PrintAndLog("Pre-fortified key that would be needed by the OmniKey reader to talk to above CSN:");
9b82de75
MHS
374 printvar("Used key",used_key,8);
375 diversifyKey(CSN,used_key, div_key);
0eea34a2 376 PrintAndLog("Hash0, a.k.a diversified key, that is computed using Ksel and stored in the card (Block 3):");
9b82de75 377 printvar("Div key", div_key, 8);
9e28ee9f 378 printvar("CC_NR:",CCNR,12);
74a38802 379 doMAC(CCNR,12,div_key, MAC);
9b82de75
MHS
380 printvar("MAC", MAC, 4);
381
26c0d833
MHS
382 UsbCommand d = {CMD_READER_ICLASS_REPLAY, {readerType}};
383 memcpy(d.d.asBytes, MAC, 4);
0eea34a2 384 if(!fake_dummy_test) SendCommand(&d);
26c0d833
MHS
385
386 }else{
387 PrintAndLog("Failed to obtain CC! Aborting");
388 }
389 } else {
390 PrintAndLog("Command execute timeout");
391 }
1e262141 392
393 return 0;
394}
395
fecd8202 396int CmdHFiClass_iso14443A_write(const char *Cmd)
397{
398 uint8_t readerType = 0;
399 uint8_t MAC[4]={0x00,0x00,0x00,0x00};
400 uint8_t KEY[8]={0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
401 uint8_t CSN[8]={0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
402 uint8_t CCNR[12]={0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
fecd8202 403 uint8_t div_key[8]={0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
3ad48540 404
fecd8202 405 uint8_t blockNo=0;
406 uint8_t bldata[8]={0};
407
408 if (strlen(Cmd)<3)
409 {
410 PrintAndLog("Usage: hf iclass write <Key> <Block> <Data>");
411 PrintAndLog(" sample: hf iclass write 0011223344556677 10 AAAAAAAAAAAAAAAA");
412 return 0;
413 }
414
415 if (param_gethex(Cmd, 0, KEY, 16))
416 {
417 PrintAndLog("KEY must include 16 HEX symbols");
418 return 1;
419 }
420
421 blockNo = param_get8(Cmd, 1);
422 if (blockNo>32)
423 {
424 PrintAndLog("Error: Maximum number of blocks is 32 for iClass 2K Cards!");
425 return 1;
426 }
427 if (param_gethex(Cmd, 2, bldata, 8))
428 {
429 PrintAndLog("Block data must include 8 HEX symbols");
430 return 1;
431 }
432
aa41c605 433 UsbCommand c = {CMD_ICLASS_ISO14443A_WRITE, {0}};
fecd8202 434 SendCommand(&c);
fecd8202 435 UsbCommand resp;
3ad48540 436
fecd8202 437 if (WaitForResponseTimeout(CMD_ACK,&resp,4500)) {
438 uint8_t isOK = resp.arg[0] & 0xff;
439 uint8_t * data = resp.d.asBytes;
440
441 memcpy(CSN,data,8);
442 memcpy(CCNR,data+8,8);
443 PrintAndLog("DEBUG: %s",sprint_hex(CSN,8));
444 PrintAndLog("DEBUG: %s",sprint_hex(CCNR,8));
445 PrintAndLog("isOk:%02x", isOK);
446 } else {
447 PrintAndLog("Command execute timeout");
448 }
3ad48540
MHS
449
450 diversifyKey(CSN,KEY, div_key);
451
fecd8202 452 PrintAndLog("Div Key: %s",sprint_hex(div_key,8));
74a38802 453 doMAC(CCNR, 12,div_key, MAC);
fecd8202 454
3ad48540
MHS
455 UsbCommand c2 = {CMD_ICLASS_ISO14443A_WRITE, {readerType,blockNo}};
456 memcpy(c2.d.asBytes, bldata, 8);
457 memcpy(c2.d.asBytes+8, MAC, 4);
458 SendCommand(&c2);
a66fca86 459
fecd8202 460 if (WaitForResponseTimeout(CMD_ACK,&resp,1500)) {
461 uint8_t isOK = resp.arg[0] & 0xff;
462 uint8_t * data = resp.d.asBytes;
463
464 if (isOK)
465 PrintAndLog("isOk:%02x data:%s", isOK, sprint_hex(data, 4));
466 else
467 PrintAndLog("isOk:%02x", isOK);
468 } else {
469 PrintAndLog("Command execute timeout");
470 }
a66fca86
AD
471 return 0;
472}
473
c3963755 474
cee5a30d 475static command_t CommandTable[] =
476{
fecd8202 477 {"help", CmdHelp, 1, "This help"},
4c3de57a 478 {"list", CmdHFiClassList, 0, "[Deprecated] List iClass history"},
fecd8202 479 {"snoop", CmdHFiClassSnoop, 0, "Eavesdrop iClass communication"},
480 {"sim", CmdHFiClassSim, 0, "Simulate iClass tag"},
481 {"reader",CmdHFiClassReader, 0, "Read an iClass tag"},
482 {"replay",CmdHFiClassReader_Replay, 0, "Read an iClass tag via Reply Attack"},
483 {"dump", CmdHFiClassReader_Dump, 0, "Authenticate and Dump iClass tag"},
484 {"write", CmdHFiClass_iso14443A_write, 0, "Authenticate and Write iClass block"},
cee5a30d 485 {NULL, NULL, 0, NULL}
486};
487
488int CmdHFiClass(const char *Cmd)
489{
490 CmdsParse(CommandTable, Cmd);
491 return 0;
492}
493
494int CmdHelp(const char *Cmd)
495{
496 CmdsHelp(CommandTable);
497 return 0;
498}
Impressum, Datenschutz