1 //----------------------------------------------------------------------------- 
   3 // This code is licensed to you under the terms of the GNU GPL, version 2 or, 
   4 // at your option, any later version. See the LICENSE.txt file for the text of 
   6 //----------------------------------------------------------------------------- 
   7 // Low frequency Presco tag commands 
   8 //----------------------------------------------------------------------------- 
  11 #include "cmdlfpresco.h" 
  12 static int CmdHelp(const char *Cmd
); 
  14 int usage_lf_presco_clone(void){ 
  15         PrintAndLog("clone a Presco tag to a T55x7 tag."); 
  16         PrintAndLog("Usage: lf presco clone d <Card-ID> H <hex-ID> <Q5>"); 
  17         PrintAndLog("Options :"); 
  18         PrintAndLog("  d <Card-ID>   : 9 digit presco card ID"); 
  19         PrintAndLog("  H <hex-ID>    : 8 digit hex card number"); 
  20         PrintAndLog("  <Q5>          : specify write to Q5 (t5555 instead of t55x7)"); 
  22         PrintAndLog("Sample  : lf presco clone d 123456789"); 
  26 int usage_lf_presco_sim(void) { 
  27         PrintAndLog("Enables simulation of presco card with specified card number."); 
  28         PrintAndLog("Simulation runs until the button is pressed or another USB command is issued."); 
  29         PrintAndLog("Per presco format, the card number is 9 digit number and can contain *# chars. Larger values are truncated."); 
  31         PrintAndLog("Usage:  lf presco sim d <Card-ID> or H <hex-ID>"); 
  32         PrintAndLog("Options :"); 
  33         PrintAndLog("  d <Card-ID>   : 9 digit presco card number"); 
  34         PrintAndLog("  H <hex-ID>    : 8 digit hex card number"); 
  36         PrintAndLog("Sample  : lf presco sim d 123456789"); 
  40 // convert base 12 ID to sitecode & usercode & 8 bit other unknown code 
  41 int GetWiegandFromPresco(const char *Cmd
, uint32_t *sitecode
, uint32_t *usercode
, uint32_t *fullcode
, bool *Q5
) { 
  44         bool hex 
= false, errors 
= false; 
  48         memset(id
, 0x00, sizeof(id
)); 
  50         while(param_getchar(Cmd
, cmdp
) != 0x00) { 
  51                 switch(param_getchar(Cmd
, cmdp
)) { 
  57                                 *fullcode 
= param_get32ex(Cmd
, cmdp
+1, 0, 16); 
  62                                 //param get string int param_getstr(const char *line, int paramnum, char * str) 
  63                                 stringlen 
= param_getstr(Cmd
, cmdp
+1, id
); 
  64                                 if (stringlen 
< 2) return -1; 
  73                                 PrintAndLog("Unknown parameter '%c'", param_getchar(Cmd
, cmdp
)); 
  80         if(cmdp 
== 0) errors 
= 1; 
  86                 for (int index 
=0; index 
< strlen(id
); ++index
) { 
  88                         // Get value from number string. 
  89                         if ( id
[index
] == '*' ) val 
= 10; 
  90                         if ( id
[index
] == '#')  val 
= 11;                
  91                         if ( id
[index
] >= 0x30 && id
[index
] <= 0x39 ) 
  92                                 val 
= id
[index
] - 0x30; 
  96                         // last digit is only added, not multipled. 
  97                         if ( index 
< strlen(id
)-1 )  
 102         *usercode 
= *fullcode 
& 0x0000FFFF; //% 65566 
 103         *sitecode 
= (*fullcode 
>> 24) & 0x000000FF;  // /= 16777216; 
 107 // calc not certain - intended to get bitstream for programming / sim 
 108 int GetPrescoBits(uint32_t fullcode
, uint8_t *prescoBits
) { 
 109         num_to_bytebits(0x10D00000, 32, prescoBits
); 
 110         num_to_bytebits(0x00000000, 32, prescoBits
+32); 
 111         num_to_bytebits(0x00000000, 32, prescoBits
+64); 
 112         num_to_bytebits(fullcode  
, 32, prescoBits
+96); 
 116 //see ASKDemod for what args are accepted 
 117 int CmdPrescoDemod(const char *Cmd
) { 
 119         //if (!ASKDemod(Cmd, false, false, 1)) { 
 120         if (!ASKDemod_ext("32 0 0", FALSE
, FALSE
, 1, &st
)) { 
 121                 if (g_debugMode
) PrintAndLog("DEBUG: Error Presco ASKDemod failed"); 
 124         size_t size 
= DemodBufferLen
; 
 125         //call lfdemod.c demod for Viking 
 126         int ans 
= PrescoDemod(DemodBuffer
, &size
); 
 130                                 PrintAndLog("DEBUG: Error - Presco: too few bits found"); 
 132                                 PrintAndLog("DEBUG: Error - Presco: preamble not found"); 
 134                                 PrintAndLog("DEBUG: Error - Presco: Size not correct: %d", size
); 
 136                                 PrintAndLog("DEBUG: Error - Presco: ans: %d", ans
); 
 140         setDemodBuf(DemodBuffer
, 128, ans
); 
 143         uint32_t raw1 
= bytebits_to_byte(DemodBuffer
, 32); 
 144         uint32_t raw2 
= bytebits_to_byte(DemodBuffer
+32, 32); 
 145         uint32_t raw3 
= bytebits_to_byte(DemodBuffer
+64, 32); 
 146         uint32_t raw4 
= bytebits_to_byte(DemodBuffer
+96, 32); 
 147         uint32_t cardid 
= raw4
; 
 148         PrintAndLog("Presco Tag Found: Card ID %08X, Raw: %08X%08X%08X%08X", cardid
, raw1
, raw2
, raw3
, raw4
); 
 150         uint32_t sitecode 
= 0, usercode 
= 0, fullcode 
= 0; 
 153         sprintf(cmd
, "H %08X", cardid
); 
 154         GetWiegandFromPresco(cmd
, &sitecode
, &usercode
, &fullcode
, &Q5
); 
 155         PrintAndLog("SiteCode %u, UserCode %u, FullCode, %08X", sitecode
, usercode
, fullcode
); 
 159 //see ASKDemod for what args are accepted 
 160 int CmdPrescoRead(const char *Cmd
) { 
 161         //      Presco Number: 123456789 --> Sitecode 30 | usercode 8665 
 165         // get samples silently 
 166         getSamples("20000", TRUE
); 
 167         // demod and output Presco ID    
 168         return CmdPrescoDemod(Cmd
); 
 171 // takes base 12 ID converts to hex 
 172 // Or takes 8 digit hex ID 
 173 int CmdPrescoClone(const char *Cmd
) { 
 176         uint32_t sitecode
=0, usercode
=0, fullcode
=0; 
 177         uint32_t blocks
[5] = {T55x7_MODULATION_MANCHESTER 
| T55x7_BITRATE_RF_32 
| 4<<T55x7_MAXBLOCK_SHIFT 
| T55x7_ST_TERMINATOR
, 0, 0, 0, 5}; 
 179         // get wiegand from printed number. 
 180         if (GetWiegandFromPresco(Cmd
, &sitecode
, &usercode
, &fullcode
, &Q5
) == -1) return usage_lf_presco_clone(); 
 183                 //t5555 (Q5) BITRATE = (RF-2)/2 (iceman) 
 184                 blocks
[0] = T5555_MODULATION_MANCHESTER 
| 32<<T5555_BITRATE_SHIFT 
| 4<<T5555_MAXBLOCK_SHIFT 
| T5555_ST_TERMINATOR
; 
 186         if ((sitecode 
& 0xFF) != sitecode
) { 
 188                 PrintAndLog("Facility-Code Truncated to 8-bits (Presco): %u", sitecode
); 
 191         if ((usercode 
& 0xFFFF) != usercode
) { 
 193                 PrintAndLog("Card Number Truncated to 16-bits (Presco): %u", usercode
); 
 196         blocks
[1] = 0x10D00000; //preamble 
 197         blocks
[2] = 0x00000000; 
 198         blocks
[3] = 0x00000000; 
 199         blocks
[4] = fullcode
; 
 201         PrintAndLog("Preparing to clone Presco to T55x7 with SiteCode: %u, UserCode: %u, FullCode: %08x", sitecode
, usercode
, fullcode
); 
 202         PrintAndLog("Blk | Data "); 
 203         PrintAndLog("----+------------"); 
 204         PrintAndLog(" 00 | 0x%08x", blocks
[0]); 
 205         PrintAndLog(" 01 | 0x%08x", blocks
[1]); 
 206         PrintAndLog(" 02 | 0x%08x", blocks
[2]); 
 207         PrintAndLog(" 03 | 0x%08x", blocks
[3]);  
 208         PrintAndLog(" 04 | 0x%08x", blocks
[4]);  
 211         UsbCommand c 
= {CMD_T55XX_WRITE_BLOCK
, {0,0,0}}; 
 213         for (int i
=4; i
>=0; i
--) { 
 214                 c
.arg
[0] = blocks
[i
]; 
 216                 clearCommandBuffer(); 
 218                 if (!WaitForResponseTimeout(CMD_ACK
, &resp
, 1000)){ 
 219                         PrintAndLog("Error occurred, device did not respond during write operation."); 
 226 // takes base 12 ID converts to hex 
 227 // Or takes 8 digit hex ID 
 228 int CmdPrescoSim(const char *Cmd
) { 
 229         uint32_t sitecode
=0, usercode
=0, fullcode
=0; 
 231         // get wiegand from printed number. 
 232         if (GetWiegandFromPresco(Cmd
, &sitecode
, &usercode
, &fullcode
, &Q5
) == -1) return usage_lf_presco_sim(); 
 234         uint8_t clk 
= 32, encoding 
= 1, separator 
= 1, invert 
= 0; 
 237         arg1 
= clk 
<< 8 | encoding
; 
 238         arg2 
= invert 
<< 8 | separator
; 
 240         PrintAndLog("Simulating Presco - SiteCode: %u, UserCode: %u, FullCode: %08X",sitecode
, usercode
, fullcode
); 
 242         UsbCommand c 
= {CMD_ASK_SIM_TAG
, {arg1
, arg2
, size
}}; 
 243         GetPrescoBits(fullcode
, c
.d
.asBytes
); 
 244         clearCommandBuffer(); 
 249 static command_t CommandTable
[] = { 
 250     {"help",    CmdHelp
,                1, "This help"}, 
 251         {"read",        CmdPrescoRead
,  0, "Attempt to read and Extract tag data"}, 
 252         {"clone",       CmdPrescoClone
, 0, "d <9 digit ID> or h <hex> [Q5] clone presco tag"}, 
 253         {"sim",         CmdPrescoSim
,   0, "d <9 digit ID> or h <hex> simulate presco tag"}, 
 254     {NULL
, NULL
, 0, NULL
} 
 257 int CmdLFPresco(const char *Cmd
) { 
 258         clearCommandBuffer(); 
 259     CmdsParse(CommandTable
, Cmd
); 
 263 int CmdHelp(const char *Cmd
) { 
 264     CmdsHelp(CommandTable
);