HitagS Improvements (#721)
[proxmark3-svn] / client / cmdlfhitag.c
CommitLineData
db09cb3a 1//-----------------------------------------------------------------------------
2// Copyright (C) 2012 Roel Verdult
3//
4// This code is licensed to you under the terms of the GNU GPL, version 2 or,
5// at your option, any later version. See the LICENSE.txt file for the text of
6// the license.
7//-----------------------------------------------------------------------------
8// Low frequency Hitag support
9//-----------------------------------------------------------------------------
10
ad939de5 11#include "cmdlfhitag.h"
12
db09cb3a 13#include <stdio.h>
14#include <stdlib.h>
15#include <string.h>
ad939de5 16#include "comms.h"
db09cb3a 17#include "ui.h"
18#include "cmdparser.h"
19#include "common.h"
20#include "util.h"
1f065e1d 21#include "parity.h"
db09cb3a 22#include "hitag2.h"
4e12287d 23#include "hitagS.h"
902cb3c0 24#include "cmdmain.h"
db09cb3a 25
26static int CmdHelp(const char *Cmd);
27
47e18126 28size_t nbytes(size_t nbits) {
29 return (nbits/8)+((nbits%8)>0);
30}
31
db09cb3a 32int CmdLFHitagList(const char *Cmd)
33{
f71f4deb 34 uint8_t *got = malloc(USB_CMD_DATA_SIZE);
f71f4deb 35 // Query for the actual size of the trace
36 UsbCommand response;
babca445 37 GetFromBigBuf(got, USB_CMD_DATA_SIZE, 0, &response, -1, false);
f71f4deb 38 uint16_t traceLen = response.arg[2];
39 if (traceLen > USB_CMD_DATA_SIZE) {
40 uint8_t *p = realloc(got, traceLen);
41 if (p == NULL) {
42 PrintAndLog("Cannot allocate memory for trace");
43 free(got);
44 return 2;
45 }
46 got = p;
babca445 47 GetFromBigBuf(got, traceLen, 0, NULL, -1, false);
f71f4deb 48 }
49
50 PrintAndLog("recorded activity (TraceLen = %d bytes):");
51 PrintAndLog(" ETU :nbits: who bytes");
52 PrintAndLog("---------+-----+----+-----------");
db09cb3a 53
7b6e3205 54 int j;
f71f4deb 55 int i = 0;
56 int prev = -1;
57 int len = strlen(Cmd);
b915fda3 58
f71f4deb 59 char filename[FILE_PATH_SIZE] = { 0x00 };
60 FILE* pf = NULL;
b915fda3 61
f71f4deb 62 if (len > FILE_PATH_SIZE)
63 len = FILE_PATH_SIZE;
64 memcpy(filename, Cmd, len);
b915fda3 65
f71f4deb 66 if (strlen(filename) > 0) {
67 if ((pf = fopen(filename,"wb")) == NULL) {
68 PrintAndLog("Error: Could not open file [%s]",filename);
44964fd1 69 free(got);
f71f4deb 70 return 1;
71 }
b915fda3 72 }
db09cb3a 73
f71f4deb 74 for (;;) {
b915fda3 75
f71f4deb 76 if(i > traceLen) { break; }
77
78 bool isResponse;
79 int timestamp = *((uint32_t *)(got+i));
80 if (timestamp & 0x80000000) {
81 timestamp &= 0x7fffffff;
82 isResponse = 1;
83 } else {
84 isResponse = 0;
85 }
86
87 int parityBits = *((uint32_t *)(got+i+4));
88 // 4 bytes of additional information...
89 // maximum of 32 additional parity bit information
90 //
91 // TODO:
92 // at each quarter bit period we can send power level (16 levels)
93 // or each half bit period in 256 levels.
94
95 int bits = got[i+8];
7b6e3205 96 int len = nbytes(bits);
f71f4deb 97
98 if (len > 100) {
99 break;
100 }
101 if (i + len > traceLen) { break;}
102
103 uint8_t *frame = (got+i+9);
7b6e3205 104/*
105 int fillupBits = 8 - (bits % 8);
106 byte_t framefilled[bits+fillupBits];
107 byte_t* ff = framefilled;
108
109 int response_bit[200] = {0};
110 int z = 0;
111 for (int y = 0; y < len; y++) {
112 for (j = 0; j < 8; j++) {
113 response_bit[z] = 0;
114 if ((frame[y] & ((mask << 7) >> j)) != 0)
115 response_bit[z] = 1;
116 z++;
117 }
118 }
119 z = 0;
120 for (int y = 0; y < len; y++) {
121 ff[y] = (response_bit[z] << 7) | (response_bit[z + 1] << 6)
122 | (response_bit[z + 2] << 5) | (response_bit[z + 3] << 4)
123 | (response_bit[z + 4] << 3) | (response_bit[z + 5] << 2)
124 | (response_bit[z + 6] << 1) | response_bit[z + 7];
125 z += 8;
126 }
127*/
128
129
130
f71f4deb 131
132 // Break and stick with current result if buffer was not completely full
133 if (frame[0] == 0x44 && frame[1] == 0x44 && frame[3] == 0x44) { break; }
134
135 char line[1000] = "";
f71f4deb 136 for (j = 0; j < len; j++) {
f71f4deb 137 //if((parityBits >> (len - j - 1)) & 0x01) {
1f065e1d 138 if (isResponse && (oddparity8(frame[j]) != ((parityBits >> (len - j - 1)) & 0x01))) {
f71f4deb 139 sprintf(line+(j*4), "%02x! ", frame[j]);
7b6e3205 140 } else {
f71f4deb 141 sprintf(line+(j*4), "%02x ", frame[j]);
142 }
143 }
144
145 PrintAndLog(" +%7d: %3d: %s %s",
146 (prev < 0 ? 0 : (timestamp - prev)),
147 bits,
148 (isResponse ? "TAG" : " "),
149 line);
150
151 if (pf) {
152 fprintf(pf," +%7d: %3d: %s %s\n",
153 (prev < 0 ? 0 : (timestamp - prev)),
154 bits,
155 (isResponse ? "TAG" : " "),
156 line);
157 }
158
159 prev = timestamp;
160 i += (len + 9);
161 }
2d495a81 162
f71f4deb 163 if (pf) {
164 fclose(pf);
165 PrintAndLog("Recorded activity succesfully written to file: %s", filename);
166 }
97d582a6 167
f71f4deb 168 free(got);
169 return 0;
db09cb3a 170}
171
172int CmdLFHitagSnoop(const char *Cmd) {
173 UsbCommand c = {CMD_SNOOP_HITAG};
174 SendCommand(&c);
175 return 0;
176}
177
178int CmdLFHitagSim(const char *Cmd) {
b915fda3 179
db09cb3a 180 UsbCommand c = {CMD_SIMULATE_HITAG};
b915fda3 181 char filename[FILE_PATH_SIZE] = { 0x00 };
db09cb3a 182 FILE* pf;
183 bool tag_mem_supplied;
b915fda3 184 int len = strlen(Cmd);
185 if (len > FILE_PATH_SIZE) len = FILE_PATH_SIZE;
186 memcpy(filename, Cmd, len);
db09cb3a 187
188 if (strlen(filename) > 0) {
189 if ((pf = fopen(filename,"rb+")) == NULL) {
190 PrintAndLog("Error: Could not open file [%s]",filename);
191 return 1;
192 }
193 tag_mem_supplied = true;
44964fd1 194 if (fread(c.d.asBytes,1,48,pf) != 48) {
195 PrintAndLog("Error: File reading error");
196 fclose(pf);
759c16b3 197 return 1;
44964fd1 198 }
db09cb3a 199 fclose(pf);
200 } else {
201 tag_mem_supplied = false;
202 }
203
204 // Does the tag comes with memory
205 c.arg[0] = (uint32_t)tag_mem_supplied;
206
207 SendCommand(&c);
208 return 0;
209}
210
211int CmdLFHitagReader(const char *Cmd) {
db09cb3a 212 UsbCommand c = {CMD_READER_HITAG};//, {param_get32ex(Cmd,0,0,10),param_get32ex(Cmd,1,0,16),param_get32ex(Cmd,2,0,16),param_get32ex(Cmd,3,0,16)}};
213 hitag_data* htd = (hitag_data*)c.d.asBytes;
214 hitag_function htf = param_get32ex(Cmd,0,0,10);
215
216 switch (htf) {
4e12287d
RS
217 case 01: { //RHTSF_CHALLENGE
218 c = (UsbCommand){ CMD_READ_HITAG_S };
219 num_to_bytes(param_get32ex(Cmd,1,0,16),4,htd->auth.NrAr);
220 num_to_bytes(param_get32ex(Cmd,2,0,16),4,htd->auth.NrAr+4);
7b6e3205 221 c.arg[1] = param_get64ex(Cmd,3,0,0); //firstpage
222 c.arg[2] = param_get64ex(Cmd,4,0,0); //tag mode
4e12287d
RS
223 } break;
224 case 02: { //RHTSF_KEY
225 c = (UsbCommand){ CMD_READ_HITAG_S };
226 num_to_bytes(param_get64ex(Cmd,1,0,16),6,htd->crypto.key);
7b6e3205 227 c.arg[1] = param_get64ex(Cmd,2,0,0); //firstpage
228 c.arg[2] = param_get64ex(Cmd,3,0,0); //tag mode
229 } break;
230 case 03: { //RHTSF_CHALLENGE BLOCK
231 c = (UsbCommand){ CMD_READ_HITAG_S_BLK };
232 num_to_bytes(param_get32ex(Cmd,1,0,16),4,htd->auth.NrAr);
233 num_to_bytes(param_get32ex(Cmd,2,0,16),4,htd->auth.NrAr+4);
234 c.arg[1] = param_get64ex(Cmd,3,0,0); //firstpage
235 c.arg[2] = param_get64ex(Cmd,4,0,0); //tag mode
236 } break;
237 case 04: { //RHTSF_KEY BLOCK
238 c = (UsbCommand){ CMD_READ_HITAG_S_BLK };
239 num_to_bytes(param_get64ex(Cmd,1,0,16),6,htd->crypto.key);
240 c.arg[1] = param_get64ex(Cmd,2,0,0); //firstpage
241 c.arg[2] = param_get64ex(Cmd,3,0,0); //tag mode
4e12287d 242 } break;
db09cb3a 243 case RHT2F_PASSWORD: {
244 num_to_bytes(param_get32ex(Cmd,1,0,16),4,htd->pwd.password);
245 } break;
246 case RHT2F_AUTHENTICATE: {
247 num_to_bytes(param_get32ex(Cmd,1,0,16),4,htd->auth.NrAr);
248 num_to_bytes(param_get32ex(Cmd,2,0,16),4,htd->auth.NrAr+4);
249 } break;
bde10a50 250 case RHT2F_CRYPTO: {
251 num_to_bytes(param_get64ex(Cmd,1,0,16),6,htd->crypto.key);
f86d6b55 252 // num_to_bytes(param_get32ex(Cmd,2,0,16),4,htd->auth.NrAr+4);
bde10a50 253 } break;
db09cb3a 254 case RHT2F_TEST_AUTH_ATTEMPTS: {
255 // No additional parameters needed
256 } break;
f86d6b55 257 case RHT2F_UID_ONLY: {
258 // No additional parameters needed
259 } break;
db09cb3a 260 default: {
f86d6b55 261 PrintAndLog("\nError: unkown reader function %d",htf);
262 PrintAndLog("");
263 PrintAndLog("Usage: hitag reader <Reader Function #>");
264 PrintAndLog("Reader Functions:");
ab4da50d 265 PrintAndLog(" HitagS (0*)");
7b6e3205 266 PrintAndLog(" 01 <nr> <ar> (Challenge) <firstPage> <tagmode> read all pages from a Hitag S tag");
267 PrintAndLog(" 02 <key> (set to 0 if no authentication is needed) <firstPage> <tagmode> read all pages from a Hitag S tag");
268 PrintAndLog(" 03 <nr> <ar> (Challenge) <firstPage> <tagmode> read all blocks from a Hitag S tag");
269 PrintAndLog(" 04 <key> (set to 0 if no authentication is needed) <firstPage> <tagmode> read all blocks from a Hitag S tag");
270 PrintAndLog(" Valid tagmodes are 0=STANDARD, 1=ADVANCED, 2=FAST_ADVANCED (default is ADVANCED)");
ab4da50d 271 PrintAndLog(" Hitag1 (1*)");
272 PrintAndLog(" Hitag2 (2*)");
273 PrintAndLog(" 21 <password> (password mode)");
274 PrintAndLog(" 22 <nr> <ar> (authentication)");
275 PrintAndLog(" 23 <key> (authentication) key is in format: ISK high + ISK low");
276 PrintAndLog(" 25 (test recorded authentications)");
f86d6b55 277 PrintAndLog(" 26 just read UID");
db09cb3a 278 return 1;
279 } break;
280 }
281
282 // Copy the hitag2 function into the first argument
283 c.arg[0] = htf;
284
f86d6b55 285 // Send the command to the proxmark
217cfb6b 286 clearCommandBuffer();
f86d6b55 287 SendCommand(&c);
ab4da50d 288
f86d6b55 289 UsbCommand resp;
290 WaitForResponse(CMD_ACK,&resp);
291
292 // Check the return status, stored in the first argument
293 if (resp.arg[0] == false) return 1;
294
295 uint32_t id = bytes_to_num(resp.d.asBytes,4);
296
297 if (htf == RHT2F_UID_ONLY){
298 PrintAndLog("Valid Hitag2 tag found - UID: %08x",id);
299 } else {
300 char filename[256];
301 FILE* pf = NULL;
302
303 sprintf(filename,"%08x_%04x.ht2",id,(rand() & 0xffff));
304 if ((pf = fopen(filename,"wb")) == NULL) {
305 PrintAndLog("Error: Could not open file [%s]",filename);
306 return 1;
307 }
308
309 // Write the 48 tag memory bytes to file and finalize
310 fwrite(resp.d.asBytes,1,48,pf);
311 fclose(pf);
312
313 PrintAndLog("Succesfully saved tag memory to [%s]",filename);
314 }
315
316
317 return 0;
db09cb3a 318}
319
4e12287d
RS
320
321int CmdLFHitagSimS(const char *Cmd) {
322 UsbCommand c = { CMD_SIMULATE_HITAG_S };
323 char filename[FILE_PATH_SIZE] = { 0x00 };
324 FILE* pf;
325 bool tag_mem_supplied;
326 int len = strlen(Cmd);
327 if (len > FILE_PATH_SIZE)
328 len = FILE_PATH_SIZE;
329 memcpy(filename, Cmd, len);
330
331 if (strlen(filename) > 0) {
332 if ((pf = fopen(filename, "rb+")) == NULL) {
333 PrintAndLog("Error: Could not open file [%s]", filename);
334 return 1;
335 }
336 tag_mem_supplied = true;
44964fd1 337 if (fread(c.d.asBytes, 1, 4*64, pf) != 4*64) {
4e12287d
RS
338 PrintAndLog("Error: File reading error");
339 fclose(pf);
340 return 1;
341 }
342 fclose(pf);
343 } else {
344 tag_mem_supplied = false;
345 }
346
347 // Does the tag comes with memory
348 c.arg[0] = (uint32_t) tag_mem_supplied;
349
350 SendCommand(&c);
351 return 0;
352}
353
354int CmdLFHitagCheckChallenges(const char *Cmd) {
355 UsbCommand c = { CMD_TEST_HITAGS_TRACES };
356 char filename[FILE_PATH_SIZE] = { 0x00 };
357 FILE* pf;
358 bool file_given;
359 int len = strlen(Cmd);
360 if (len > FILE_PATH_SIZE) len = FILE_PATH_SIZE;
361 memcpy(filename, Cmd, len);
362
363 if (strlen(filename) > 0) {
364 if ((pf = fopen(filename,"rb+")) == NULL) {
365 PrintAndLog("Error: Could not open file [%s]",filename);
366 return 1;
367 }
368 file_given = true;
44964fd1 369 if (fread(c.d.asBytes,1,8*60,pf) != 8*60) {
370 PrintAndLog("Error: File reading error");
371 fclose(pf);
4e12287d
RS
372 return 1;
373 }
374 fclose(pf);
375 } else {
376 file_given = false;
377 }
378
379 //file with all the challenges to try
380 c.arg[0] = (uint32_t)file_given;
7b6e3205 381 c.arg[1] = param_get64ex(Cmd,2,0,0); //get mode
4e12287d
RS
382
383 SendCommand(&c);
384 return 0;
385}
386
387
388int CmdLFHitagWP(const char *Cmd) {
389 UsbCommand c = { CMD_WR_HITAG_S };
390 hitag_data* htd = (hitag_data*)c.d.asBytes;
391 hitag_function htf = param_get32ex(Cmd,0,0,10);
392 switch (htf) {
393 case 03: { //WHTSF_CHALLENGE
394 num_to_bytes(param_get64ex(Cmd,1,0,16),8,htd->auth.NrAr);
395 c.arg[2]= param_get32ex(Cmd, 2, 0, 10);
396 num_to_bytes(param_get32ex(Cmd,3,0,16),4,htd->auth.data);
397 } break;
52244230
HJ
398 case 04:
399 case 24:
400 { //WHTSF_KEY
4e12287d
RS
401 num_to_bytes(param_get64ex(Cmd,1,0,16),6,htd->crypto.key);
402 c.arg[2]= param_get32ex(Cmd, 2, 0, 10);
403 num_to_bytes(param_get32ex(Cmd,3,0,16),4,htd->crypto.data);
404
405 } break;
406 default: {
407 PrintAndLog("Error: unkown writer function %d",htf);
408 PrintAndLog("Hitag writer functions");
409 PrintAndLog(" HitagS (0*)");
410 PrintAndLog(" 03 <nr,ar> (Challenge) <page> <byte0...byte3> write page on a Hitag S tag");
411 PrintAndLog(" 04 <key> (set to 0 if no authentication is needed) <page> <byte0...byte3> write page on a Hitag S tag");
412 PrintAndLog(" Hitag1 (1*)");
413 PrintAndLog(" Hitag2 (2*)");
52244230 414 PrintAndLog(" 24 <key> (set to 0 if no authentication is needed) <page> <byte0...byte3> write page on a Hitag S tag");
4e12287d
RS
415 return 1;
416 } break;
417 }
418 // Copy the hitag function into the first argument
419 c.arg[0] = htf;
420
421 // Send the command to the proxmark
422 SendCommand(&c);
423
424 UsbCommand resp;
425 WaitForResponse(CMD_ACK,&resp);
426
427 // Check the return status, stored in the first argument
428 if (resp.arg[0] == false) return 1;
429 return 0;
430}
431
432
3fe4ff4f 433static command_t CommandTable[] =
db09cb3a 434{
4e12287d
RS
435 {"help", CmdHelp, 1, "This help"},
436 {"list", CmdLFHitagList, 1, "<outfile> List Hitag trace history"},
437 {"reader", CmdLFHitagReader, 1, "Act like a Hitag Reader"},
438 {"sim", CmdLFHitagSim, 1, "<infile> Simulate Hitag transponder"},
439 {"snoop", CmdLFHitagSnoop, 1, "Eavesdrop Hitag communication"},
440 {"writer", CmdLFHitagWP, 1, "Act like a Hitag Writer" },
441 {"simS", CmdLFHitagSimS, 1, "<hitagS.hts> Simulate HitagS transponder" },
7b6e3205 442 {"checkChallenges", CmdLFHitagCheckChallenges, 1, "<challenges.cc> <tagmode> test all challenges" }, {
4e12287d 443 NULL,NULL, 0, NULL }
db09cb3a 444};
445
446int CmdLFHitag(const char *Cmd)
447{
3fe4ff4f 448 CmdsParse(CommandTable, Cmd);
db09cb3a 449 return 0;
450}
451
452int CmdHelp(const char *Cmd)
453{
3fe4ff4f 454 CmdsHelp(CommandTable);
db09cb3a 455 return 0;
456}
Impressum, Datenschutz