]> git.zerfleddert.de Git - proxmark3-svn/blame - client/cmdlfhid.c
update travis config (#662)
[proxmark3-svn] / client / cmdlfhid.c
CommitLineData
a553f267 1//-----------------------------------------------------------------------------
2// Copyright (C) 2010 iZsh <izsh at fail0verflow.com>
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//-----------------------------------------------------------------------------
b9957414 8// Low frequency HID commands (known)
ab20cc35
MF
9//
10// Useful resources:
11// RF interface, programming a T55x7 clone, 26-bit HID H10301 encoding:
12// http://www.proxmark.org/files/Documents/125%20kHz%20-%20HID/HID_format_example.pdf
13//
14// "Understanding Card Data Formats"
15// https://www.hidglobal.com/sites/default/files/hid-understanding_card_data_formats-wp-en.pdf
16//
17// "What Format Do You Need?"
18// https://www.hidglobal.com/sites/default/files/resource_files/hid-prox-br-en.pdf
a553f267 19//-----------------------------------------------------------------------------
20
ad939de5 21#include "cmdlfhid.h"
22
7fe9b0b7 23#include <stdio.h>
54a942b0 24#include <string.h>
ad939de5 25#include "comms.h"
7fe9b0b7 26#include "ui.h"
27#include "graph.h"
28#include "cmdparser.h"
6cd2eef4 29#include "cmddata.h" //for g_debugMode, demodbuff cmds
30#include "lfdemod.h" // for HIDdemodFSK
ab20cc35 31#include "parity.h" // for parity
1ee624fe 32#include "util.h" // for param_get8,32,64
7fe9b0b7 33
34static int CmdHelp(const char *Cmd);
6cd2eef4 35
ab20cc35 36/**
1ee624fe 37 * Packs an HID ID from component parts.
ab20cc35 38 *
1ee624fe 39 * This only works with 26, 34, 35, 37, and 48 bit card IDs.
ab20cc35
MF
40 *
41 * Returns false on invalid inputs.
42 */
1ee624fe 43bool pack_hid(/* out */ uint32_t *hi2, /* out */ uint32_t *hi, /* out */ uint32_t *lo, /* in */ const hid_info *info) {
44 uint32_t higher = 0, high = 0, low = 0;
ab20cc35
MF
45
46 switch (info->fmtLen) {
1ee624fe 47 case 26: // HID H10301
48 low |= (info->cardnum & 0xffff) << 1;
49 low |= (info->fc & 0xff) << 17;
ab20cc35 50
1ee624fe 51 if (info->parityValid) {
52 // Calculate parity
53 low |= oddparity32((low >> 1) & 0xfff) & 1;
54 low |= (evenparity32((low >> 13) & 0xfff) & 1) << 25;
55 }
ab20cc35
MF
56 break;
57
1ee624fe 58 case 34: // H10306
ab20cc35
MF
59 low |= (info->cardnum & 0xffff) << 1;
60 low |= (info->fc & 0x7fff) << 17;
61 high |= (info->fc & 0x8000) >> 15;
1ee624fe 62
63 if (info->parityValid) {
64 // Calculate parity
65 high |= (evenparity32((high & 0x00000001) ^ (low & 0xFFFE0000)) & 1) << 1;
66 low |= (oddparity32(low & 0x0001FFFE) & 1);
67 }
ab20cc35
MF
68 break;
69
1ee624fe 70 case 35: // (Corporate 1000 35-bit)
ab20cc35
MF
71 low |= (info->cardnum & 0xfffff) << 1;
72 low |= (info->fc & 0x7ff) << 21;
73 high |= (info->fc & 0x800) >> 11;
1ee624fe 74
75 if (info->parityValid) {
76 // Calculate parity
77 high |= (evenparity32((high & 0x00000001) ^ (low & 0xB6DB6DB6)) & 1) << 1;
78 low |= (oddparity32( (high & 0x00000003) ^ (low & 0x6DB6DB6C)) & 1);
79 high |= (oddparity32( (high & 0x00000003) ^ (low & 0xFFFFFFFF)) & 1) << 2;
80 }
ab20cc35
MF
81 break;
82
1ee624fe 83 case 37: //H10304
ab20cc35
MF
84 low |= (info->cardnum & 0x7ffff) << 1;
85 low |= (info->fc & 0xfff) << 20;
86 high |= (info->fc & 0xf000) >> 12;
1ee624fe 87
88 if (info->parityValid) {
89 // Calculate parity
90 high |= (evenparity32((high & 0x0000000F) ^ (low & 0xFFFC0000)) & 1) << 4;
91 low |= (oddparity32(low & 0x0007FFFE) & 1);
92 }
93 break;
94
95 case 48: // Corporate 1000 48-bit
96 low |= (info->cardnum & 0x7FFFFF) << 1;
97 low |= (info->fc & 0xff) << 24;
98 high |= (info->fc & 0x3FFF00) >> 8;
99
100 if (info->parityValid) {
101 // Calculate parity
102 high |= (evenparity32((high & 0x00001B6D) ^ (low & 0xB6DB6DB6)) & 1) << 14;
103 low |= (oddparity32( (high & 0x000036DB) ^ (low & 0x6DB6DB6C)) & 1);
104 high |= (oddparity32( (high & 0x00007FFF) ^ (low & 0xFFFFFFFF)) & 1) << 15;
105 }
ab20cc35
MF
106 break;
107
108 default:
109 // Invalid / unsupported length
110 return false;
111 }
1ee624fe 112
113 // Set the format length bits
114 if (info->fmtLen < 37) {
ab20cc35
MF
115 // Bit 37 is always set
116 high |= 0x20;
117
118 // Set the bit corresponding to the length.
1ee624fe 119 if (info->fmtLen < 32)
ab20cc35 120 low |= 1 << info->fmtLen;
1ee624fe 121 else
ab20cc35 122 high |= 1 << (info->fmtLen - 32);
1ee624fe 123
124 } else if (info->fmtLen > 37){
125 if (info->fmtLen < 64)
126 high |= 1 << (info->fmtLen - 32);
127 else
128 higher |= 1 << (info->fmtLen - 64);
ab20cc35 129 }
ab20cc35 130 // Return result only if successful.
1ee624fe 131 *hi2 = higher;
ab20cc35
MF
132 *hi = high;
133 *lo = low;
134 return true;
135}
136
ab20cc35 137/**
1ee624fe 138 * Unpacks an HID ID into its component parts.
ab20cc35 139 *
1ee624fe 140 * This only works with 26, 34, 35, 37, and 48 bit card IDs.
ab20cc35
MF
141 *
142 * Returns false on invalid inputs.
143 */
1ee624fe 144bool unpack_hid(hid_info *out, uint32_t hi2, uint32_t hi, uint32_t lo) {
145 memset(out, 0, sizeof(hid_info));
146 uint8_t fmtLen = 0;
147
148 uint32_t hFmt; // for calculating card length
149 if ((hi2 & 0x000FFFFF) > 0) { // > 64 bits
150 hFmt = hi2 & 0x000FFFFF;
151 fmtLen = 64;
152 } else if ((hi & 0xFFFFFFC0) > 0) { // < 63-38 bits
153 hFmt = hi & 0xFFFFFFC0;
154 fmtLen = 32;
155 } else if ((hi & 0x00000020) == 0) { // 37 bits
156 hFmt = 0;
157 fmtLen = 37;
158 } else if ((hi & 0x0000001F) > 0){ // 36-32 bits
159 hFmt = hi & 0x0000001F;
160 fmtLen = 32;
161 } else { // <32 bits
162 hFmt = lo;
163 fmtLen = 0;
164 }
ab20cc35 165
1ee624fe 166 while (hFmt > 1) {
167 hFmt >>= 1;
168 fmtLen++;
169 }
170 out->fmtLen = fmtLen;
171 switch (out->fmtLen) {
ab20cc35
MF
172 case 26: // HID H10301
173 out->cardnum = (lo >> 1) & 0xFFFF;
174 out->fc = (lo >> 17) & 0xFF;
175
176 if (g_debugMode) {
177 PrintAndLog("oddparity : input=%x, calculated=%d, provided=%d",
178 (lo >> 1) & 0xFFF, oddparity32((lo >> 1) & 0xFFF), lo & 1);
179 PrintAndLog("evenparity: input=%x, calculated=%d, provided=%d",
180 (lo >> 13) & 0xFFF, evenparity32((lo >> 13) & 0xFFF) & 1, (lo >> 25) & 1);
181 }
182
183 out->parityValid =
184 (oddparity32((lo >> 1) & 0xFFF) == (lo & 1)) &&
185 ((evenparity32((lo >> 13) & 0xFFF) & 1) == ((lo >> 25) & 1));
186 break;
187
1ee624fe 188 case 34: // HID H10306
ab20cc35
MF
189 out->cardnum = (lo >> 1) & 0xFFFF;
190 out->fc = ((hi & 1) << 15) | (lo >> 17);
1ee624fe 191 out->parityValid =
192 ((evenparity32((hi & 0x00000001) ^ (lo & 0xFFFE0000)) & 1) == ((hi >> 1) & 1)) &&
193 ((oddparity32(lo & 0x0001FFFE) & 1) == ((lo & 1)));
ab20cc35
MF
194 break;
195
1ee624fe 196 case 35: // HID Corporate 1000-35
ab20cc35
MF
197 out->cardnum = (lo >> 1) & 0xFFFFF;
198 out->fc = ((hi & 1) << 11) | (lo >> 21);
1ee624fe 199 out->parityValid =
200 (evenparity32((hi & 0x00000001) ^ (lo & 0xB6DB6DB6)) == ((hi >> 1) & 1)) &&
201 (oddparity32( (hi & 0x00000003) ^ (lo & 0x6DB6DB6C)) == ((lo >> 0) & 1)) &&
202 (oddparity32( (hi & 0x00000003) ^ (lo & 0xFFFFFFFF)) == ((hi >> 2) & 1));
203 if (g_debugMode) {
204 PrintAndLog("Parity check: calculated {%d, %d, %d}, provided {%d, %d, %d}",
205 evenparity32((hi & 0x00000001) ^ (lo & 0xB6DB6DB6)),
206 oddparity32( (hi & 0x00000003) ^ (lo & 0x6DB6DB6C)),
207 oddparity32( (hi & 0x00000003) ^ (lo & 0xFFFFFFFF)),
208 ((hi >> 1) & 1),
209 ((lo >> 0) & 1),
210 ((hi >> 2) & 1)
211 );
212 }
213 break;
214
215 case 37: // HID H10304
216 out->fmtLen = 37;
217 out->cardnum = (lo >> 1) & 0x7FFFF;
218 out->fc = ((hi & 0xF) << 12) | (lo >> 20);
219 out->parityValid =
220 (evenparity32((hi & 0x0000000F) ^ (lo & 0xFFFC0000)) == ((hi >> 4) & 1)) &&
221 (oddparity32( lo & 0x0007FFFE) == (lo & 1));
222 break;
223
224 case 48: // HID Corporate 1000-48
225 out->cardnum = (lo >> 1) & 0x7FFFFF; //Start 24, 23 length
226 out->fc = ((hi & 0x3FFF) << 8 ) | (lo >> 24); //Start 2, 22 length
227 out->parityValid =
228 (evenparity32((hi & 0x00001B6D) ^ (lo & 0xB6DB6DB6)) == ((hi >> 14) & 1)) &&
229 (oddparity32( (hi & 0x000036DB) ^ (lo & 0x6DB6DB6C)) == ((lo >> 0) & 1)) &&
230 (oddparity32( (hi & 0x00007FFF) ^ (lo & 0xFFFFFFFF)) == ((hi >> 15) & 1));
231 if (g_debugMode) {
232 PrintAndLog("Parity check: calculated {%d, %d, %d}, provided {%d, %d, %d}",
233 evenparity32((hi & 0x00001B6D) ^ (lo & 0xB6DB6DB6)),
234 oddparity32( (hi & 0x000036DB) ^ (lo & 0x6DB6DB6C)),
235 oddparity32( (hi & 0x00007FFF) ^ (lo & 0xFFFFFFFF)),
236 ((hi >> 14) & 1),
237 ((lo >> 0) & 1),
238 ((hi >> 15) & 1)
239 );
240 }
ab20cc35
MF
241 break;
242
243 default:
244 return false;
ab20cc35
MF
245 }
246 return true;
247}
248
ab20cc35 249/**
1ee624fe 250 * Converts a hex string to component "hi2", "hi" and "lo" 32-bit integers, one nibble
ab20cc35
MF
251 * at a time.
252 *
253 * Returns the number of nibbles (4 bits) entered.
254 */
1ee624fe 255int hexstring_to_int96(/* out */ uint32_t* hi2,/* out */ uint32_t* hi, /* out */ uint32_t* lo, const char* str) {
ab20cc35
MF
256 // TODO: Replace this with param_gethex when it supports arbitrary length
257 // inputs.
258 int n = 0, i = 0;
259
260 while (sscanf(&str[i++], "%1x", &n ) == 1) {
1ee624fe 261 *hi2 = (*hi2 << 4) | (*hi >> 28);
ab20cc35
MF
262 *hi = (*hi << 4) | (*lo >> 28);
263 *lo = (*lo << 4) | (n & 0xf);
264 }
265
266 return i - 1;
267}
268
6cd2eef4 269//by marshmellow (based on existing demod + holiman's refactor)
270//HID Prox demod - FSK RF/50 with preamble of 00011101 (then manchester encoded)
271//print full HID Prox ID and some bit format details if found
272int CmdFSKdemodHID(const char *Cmd)
7fe9b0b7 273{
6cd2eef4 274 //raw fsk demod no manchester decoding no start bit finding just get binary from wave
275 uint32_t hi2=0, hi=0, lo=0;
276
277 uint8_t BitStream[MAX_GRAPH_TRACE_LEN]={0};
278 size_t BitLen = getFromGraphBuf(BitStream);
279 if (BitLen==0) return 0;
280 //get binary from fsk wave
1c70664a 281 int waveIdx = 0;
282 int idx = HIDdemodFSK(BitStream,&BitLen,&hi2,&hi,&lo, &waveIdx);
6cd2eef4 283 if (idx<0){
284 if (g_debugMode){
285 if (idx==-1){
286 PrintAndLog("DEBUG: Just Noise Detected");
287 } else if (idx == -2) {
288 PrintAndLog("DEBUG: Error demoding fsk");
289 } else if (idx == -3) {
290 PrintAndLog("DEBUG: Preamble not found");
291 } else if (idx == -4) {
292 PrintAndLog("DEBUG: Error in Manchester data, SIZE: %d", BitLen);
293 } else {
294 PrintAndLog("DEBUG: Error demoding fsk %d", idx);
295 }
296 }
7fe9b0b7 297 return 0;
298 }
6cd2eef4 299 if (hi2==0 && hi==0 && lo==0) {
300 if (g_debugMode) PrintAndLog("DEBUG: Error - no values found");
301 return 0;
302 }
1ee624fe 303
304 hid_info card_info;
305 bool ret = unpack_hid(&card_info, (uint32_t)hi2, (uint32_t)hi, (uint32_t)lo);
306
307 if (hi2 != 0)
308 PrintAndLog("HID Prox TAG ID: %x%08x%08x (%d) - Format Len: %u bits - FC: %u - Card: %u",
309 (unsigned int) hi2, (unsigned int) hi, (unsigned int) lo, (unsigned int) (lo>>1) & 0xFFFF,
310 card_info.fmtLen, card_info.fc, card_info.cardnum);
311 else
ab20cc35
MF
312 PrintAndLog("HID Prox TAG ID: %x%08x (%d) - Format Len: %u bits - FC: %u - Card: %u",
313 (unsigned int) hi, (unsigned int) lo, (unsigned int) (lo>>1) & 0xFFFF,
314 card_info.fmtLen, card_info.fc, card_info.cardnum);
315
1ee624fe 316 if (card_info.fmtLen == 26 || card_info.fmtLen == 35 || card_info.fmtLen == 48) {
317 PrintAndLog("Parity: %s", card_info.parityValid ? "valid" : "invalid");
318 }
319 if (!ret) {
320 PrintAndLog("Invalid or unsupported tag length.");
7fe9b0b7 321 }
6cd2eef4 322 setDemodBuf(BitStream,BitLen,idx);
1c70664a 323 setClockGrid(50, waveIdx + (idx*50));
6cd2eef4 324 if (g_debugMode){
325 PrintAndLog("DEBUG: idx: %d, Len: %d, Printing Demod Buffer:", idx, BitLen);
326 printDemodBuff();
327 }
328 return 1;
7fe9b0b7 329}
6cd2eef4 330
331int CmdHIDReadFSK(const char *Cmd)
7fe9b0b7 332{
083ca3de 333 int findone=0;
ab20cc35 334 if(Cmd[0]=='1') findone=1;
7fe9b0b7 335 UsbCommand c={CMD_HID_DEMOD_FSK};
083ca3de 336 c.arg[0]=findone;
7fe9b0b7 337 SendCommand(&c);
338 return 0;
339}
340
341int CmdHIDSim(const char *Cmd)
38b20f75 342{
1ee624fe 343 uint32_t hi2 = 0, hi = 0, lo = 0;
344 hexstring_to_int96(&hi2, &hi, &lo, Cmd);
345 if (hi >= 0x40 || hi2 != 0) {
ab20cc35
MF
346 PrintAndLog("This looks like a long tag ID. Use 'lf simfsk' for long tags. Aborting!");
347 return 0;
348 }
38b20f75 349
ab20cc35
MF
350 PrintAndLog("Emulating tag with ID %x%08x", hi, lo);
351 PrintAndLog("Press pm3-button to abort simulation");
38b20f75 352
ab20cc35
MF
353 UsbCommand c = {CMD_HID_SIM_TAG, {hi, lo, 0}};
354 SendCommand(&c);
355 return 0;
38b20f75 356}
357
358int CmdHIDClone(const char *Cmd)
7fe9b0b7 359{
54a942b0 360 unsigned int hi2 = 0, hi = 0, lo = 0;
54a942b0 361 UsbCommand c;
1ee624fe 362 hexstring_to_int96(&hi2, &hi, &lo, Cmd);
363
364 if (hi >= 0x40 || hi2 != 0) {
54a942b0 365 PrintAndLog("Cloning tag with long ID %x%08x%08x", hi2, hi, lo);
54a942b0 366 c.d.asBytes[0] = 1;
1ee624fe 367 } else {
54a942b0 368 PrintAndLog("Cloning tag with ID %x%08x", hi, lo);
54a942b0 369 c.d.asBytes[0] = 0;
7fe9b0b7 370 }
38b20f75 371
372 c.cmd = CMD_HID_CLONE_TAG;
d16d20b1 373 c.arg[0] = hi2;
374 c.arg[1] = hi;
375 c.arg[2] = lo;
ec09b62d 376
ec09b62d 377 SendCommand(&c);
378 return 0;
379}
380
ab20cc35
MF
381
382int CmdHIDPack(const char *Cmd) {
1ee624fe 383 uint32_t hi2 = 0, hi = 0, lo = 0;
384
ab20cc35
MF
385 if (strlen(Cmd)<3) {
386 PrintAndLog("Usage: lf hid pack <length> <facility code (decimal)> <card number (decimal)>");
387 PrintAndLog(" sample: lf hid pack 26 123 4567");
388 return 0;
389 }
1ee624fe 390 uint8_t fmtLen = param_get8(Cmd, 0);
ab20cc35 391
1ee624fe 392 hid_info card_info;
393 card_info.fmtLen = fmtLen;
ab20cc35 394 card_info.fc = param_get32ex(Cmd, 1, 0, 10);
1ee624fe 395 card_info.cardnum = param_get64ex(Cmd, 2, 0, 10);
ab20cc35
MF
396 card_info.parityValid = true;
397
1ee624fe 398 bool ret = pack_hid(&hi2, &hi, &lo, &card_info);
ab20cc35 399 if (ret) {
1ee624fe 400 if (hi2 != 0) {
401 PrintAndLog("HID Prox TAG ID: %x%08x%08x (%d) - Format Len: %u bits - FC: %u - Card: %u",
402 (unsigned int) hi2, (unsigned int) hi, (unsigned int) lo, (unsigned int) (lo>>1) & 0xFFFF,
403 card_info.fmtLen, card_info.fc, card_info.cardnum);
404 } else {
405 PrintAndLog("HID Prox TAG ID: %x%08x (%d) - Format Len: %u bits - FC: %u - Card: %u",
406 (unsigned int) hi, (unsigned int) lo, (unsigned int) (lo>>1) & 0xFFFF,
407 card_info.fmtLen, card_info.fc, card_info.cardnum);
408 }
ab20cc35
MF
409 } else {
410 PrintAndLog("Invalid or unsupported tag length.");
411 }
412 return 0;
413}
414
415
416int CmdHIDUnpack(const char *Cmd)
417{
1ee624fe 418 uint32_t hi2 = 0, hi = 0, lo = 0;
ab20cc35
MF
419 if (strlen(Cmd)<1) {
420 PrintAndLog("Usage: lf hid unpack <ID>");
421 PrintAndLog(" sample: lf hid unpack 2006f623ae");
422 return 0;
423 }
424
1ee624fe 425 hexstring_to_int96(&hi2, &hi, &lo, Cmd);
426
427 hid_info card_info;
428 bool ret = unpack_hid(&card_info, hi2, hi, lo);
ab20cc35 429
1ee624fe 430 if (hi2 != 0) {
431 PrintAndLog("HID Prox TAG ID: %x%08x%08x (%d) - Format Len: %u bits - FC: %u - Card: %u",
432 (unsigned int) hi2, (unsigned int) hi, (unsigned int) lo, (unsigned int) (lo>>1) & 0xFFFF,
433 card_info.fmtLen, card_info.fc, card_info.cardnum);
434 } else {
435 PrintAndLog("HID Prox TAG ID: %x%08x (%d) - Format Len: %u bits - FC: %u - Card: %u",
436 (unsigned int) hi, (unsigned int) lo, (unsigned int) (lo>>1) & 0xFFFF,
437 card_info.fmtLen, card_info.fc, card_info.cardnum);
ab20cc35 438 }
1ee624fe 439 PrintAndLog("Parity: %s", card_info.parityValid ? "valid" : "invalid");
440
ab20cc35
MF
441 if (!ret) {
442 PrintAndLog("Invalid or unsupported tag length.");
443 }
444 return 0;
445}
446
447
7fe9b0b7 448static command_t CommandTable[] =
449{
450 {"help", CmdHelp, 1, "This help"},
6cd2eef4 451 {"demod", CmdFSKdemodHID, 1, "Demodulate HID Prox from GraphBuffer"},
452 {"read", CmdHIDReadFSK, 0, "['1'] Realtime HID FSK Read from antenna (option '1' for one tag only)"},
083ca3de 453 {"sim", CmdHIDSim, 0, "<ID> -- HID tag simulator"},
1ee624fe 454 {"clone", CmdHIDClone, 0, "<ID> -- Clone HID to T55x7 (tag must be in antenna)"},
455 {"pack", CmdHIDPack, 1, "<len> <fc> <num> -- packs an HID ID from its length, facility code and card number"},
456 {"unpack", CmdHIDUnpack, 1, "<ID> -- unpacks an HID ID to its length, facility code and card number"},
7fe9b0b7 457 {NULL, NULL, 0, NULL}
458};
459
460int CmdLFHID(const char *Cmd)
461{
462 CmdsParse(CommandTable, Cmd);
463 return 0;
464}
465
466int CmdHelp(const char *Cmd)
467{
468 CmdsHelp(CommandTable);
469 return 0;
470}
Impressum, Datenschutz