]> cvs.zerfleddert.de Git - proxmark3-svn/blobdiff - client/cmdlfpresco.c
Merge pull request #81 from mdp/fixguard
[proxmark3-svn] / client / cmdlfpresco.c
index 20b42bc1a7c473de2fb5cac4bee337b4a43c94c5..84b6f4a26fc25d6c40dc81afd287d025309eb27f 100644 (file)
@@ -13,12 +13,13 @@ static int CmdHelp(const char *Cmd);
 
 int usage_lf_presco_clone(void){
        PrintAndLog("clone a Presco tag to a T55x7 tag.");
-       PrintAndLog("Usage: lf presco clone <Card ID - 9 digits> <Q5>");
+       PrintAndLog("Usage: lf presco clone d <Card-ID> H <hex-ID> <Q5>");
        PrintAndLog("Options :");
-       PrintAndLog("  <Card Number>  : 9 digit presco card number");
-       //PrintAndLog("  <Q5>           : specify write to Q5 (t5555 instead of t55x7)");
+       PrintAndLog("  d <Card-ID>   : 9 digit presco card ID");
+       PrintAndLog("  H <hex-ID>    : 8 digit hex card number");
+       PrintAndLog("  <Q5>          : specify write to Q5 (t5555 instead of t55x7)");
        PrintAndLog("");
-       PrintAndLog("Sample  : lf presco clone 123456789");
+       PrintAndLog("Sample  : lf presco clone 123456789");
        return 0;
 }
 
@@ -27,78 +28,130 @@ int usage_lf_presco_sim(void) {
        PrintAndLog("Simulation runs until the button is pressed or another USB command is issued.");
        PrintAndLog("Per presco format, the card number is 9 digit number and can contain *# chars. Larger values are truncated.");
        PrintAndLog("");
-       PrintAndLog("Usage:  lf presco sim <Card-Number>");
+       PrintAndLog("Usage:  lf presco sim d <Card-ID> or H <hex-ID>");
        PrintAndLog("Options :");
-       PrintAndLog("  <Card Number>   : 9 digit presco card number");
+       PrintAndLog("  d <Card-ID>   : 9 digit presco card number");
+       PrintAndLog("  H <hex-ID>    : 8 digit hex card number");
        PrintAndLog("");
-       PrintAndLog("Sample  : lf presco sim 123456789");
+       PrintAndLog("Sample  : lf presco sim 123456789");
        return 0;
 }
 
-// calc checksum
-int GetWiegandFromPresco(const char *id, uint32_t *sitecode, uint32_t *usercode) {
+// convert base 12 ID to sitecode & usercode & 8 bit other unknown code
+int GetWiegandFromPresco(const char *Cmd, uint32_t *sitecode, uint32_t *usercode, uint32_t *fullcode, bool *Q5) {
        
        uint8_t val = 0;
-       for (int index =0; index < strlen(id); ++index) {
-               
-               // Get value from number string.
-               if ( id[index] == '*' ) val = 10;
-               if ( id[index] == '#')  val = 11;               
-               if ( id[index] >= 0x30 && id[index] <= 0x39 )
-                       val = id[index] - 0x30;
-               
-               *sitecode += val;
-               
-               // last digit is only added, not multipled.
-               if ( index < strlen(id)-1 ) 
-                       *sitecode *= 12;
+       bool hex = false, errors = false;
+       uint8_t cmdp = 0;
+       char id[11];
+       int stringlen = 0;
+       memset(id, 0x00, sizeof(id));
+       
+       while(param_getchar(Cmd, cmdp) != 0x00) {
+               switch(param_getchar(Cmd, cmdp)) {
+                       case 'h':
+                               return -1;
+                       case 'H':
+                               hex = true;
+                               //get hex
+                               *fullcode = param_get32ex(Cmd, cmdp+1, 0, 16);
+                               cmdp+=2;
+                               break;
+                       case 'P':
+                       case 'p':
+                               //param get string int param_getstr(const char *line, int paramnum, char * str)
+                               stringlen = param_getstr(Cmd, cmdp+1, id);
+                               if (stringlen < 2) return -1;
+                               cmdp+=2;
+                               break;
+                       case 'Q':
+                       case 'q':
+                               *Q5 = true;
+                               cmdp++;
+                               break;
+                       default:
+                               PrintAndLog("Unknown parameter '%c'", param_getchar(Cmd, cmdp));
+                               errors = 1;
+                               break;
+               }
+               if(errors) break;
        }
-       *usercode = *sitecode % 65536;
-       *sitecode /= 16777216;
-       return 0;
-}
+       // No args
+       if(cmdp == 0) errors = 1;
 
-int GetPrescoBits(uint32_t sitecode, uint32_t usercode, uint8_t        *prescoBits) {
-       uint8_t pre[66];
-       memset(pre, 0, sizeof(pre));
-       prescoBits[7]=1;
-       num_to_bytebits(26, 8, pre);
+       //Validations
+       if(errors) return -1;
 
-       uint8_t wiegand[24];
-       num_to_bytebits(sitecode, 8, wiegand);
-       num_to_bytebits(usercode, 16, wiegand+8);
+       if (!hex) {
+               for (int index =0; index < strlen(id); ++index) {
+               
+                       // Get value from number string.
+                       if ( id[index] == '*' ) val = 10;
+                       if ( id[index] == '#')  val = 11;               
+                       if ( id[index] >= 0x30 && id[index] <= 0x39 )
+                               val = id[index] - 0x30;
+                       
+                               *fullcode += val;
+                       
+                       // last digit is only added, not multipled.
+                       if ( index < strlen(id)-1 ) 
+                                       *fullcode *= 12;
+               }
+       }
 
-       wiegand_add_parity(pre+8, wiegand, 24);
-       size_t bitLen = addParity(pre, prescoBits+8, 66, 4, 1);
+       *usercode = *fullcode & 0x0000FFFF; //% 65566
+       *sitecode = (*fullcode >> 24) & 0x000000FF;  // /= 16777216;
+       return 0;
+}
 
-       if (bitLen != 88) return 0;
+// calc not certain - intended to get bitstream for programming / sim
+int GetPrescoBits(uint32_t fullcode, uint8_t *prescoBits) {
+       num_to_bytebits(0x10D00000, 32, prescoBits);
+       num_to_bytebits(0x00000000, 32, prescoBits+32);
+       num_to_bytebits(0x00000000, 32, prescoBits+64);
+       num_to_bytebits(fullcode  , 32, prescoBits+96);
        return 1;
 }
+
 //see ASKDemod for what args are accepted
 int CmdPrescoDemod(const char *Cmd) {
-       if (!ASKDemod(Cmd, false, false, 1)) {
-               if (g_debugMode) PrintAndLog("ASKDemod failed");
+       bool st = true;
+       if (!ASKDemod_ext("32 0 0 0 0 a", FALSE, FALSE, 1, &st)) {
+               if (g_debugMode) PrintAndLog("DEBUG: Error Presco ASKDemod failed");
                return 0;
        }
        size_t size = DemodBufferLen;
-       //call lfdemod.c demod for Viking
+       //call lfdemod.c demod for Presco
        int ans = PrescoDemod(DemodBuffer, &size);
        if (ans < 0) {
-               if (g_debugMode) PrintAndLog("Error Presco_Demod %d", ans);
+               if (g_debugMode){
+                       if (ans == -1)
+                               PrintAndLog("DEBUG: Error - Presco: too few bits found");
+                       else if (ans == -2)
+                               PrintAndLog("DEBUG: Error - Presco: preamble not found");
+                       else if (ans == -3)
+                               PrintAndLog("DEBUG: Error - Presco: Size not correct: %d", size);
+                       else
+                               PrintAndLog("DEBUG: Error - Presco: ans: %d", ans);
+               }
                return 0;
        }
-       //got a good demod
-       uint32_t raw1 = bytebits_to_byte(DemodBuffer+ans, 32);
-       uint32_t raw2 = bytebits_to_byte(DemodBuffer+ans+32, 32);
-       uint32_t cardid = bytebits_to_byte(DemodBuffer+ans+24, 32);
-       PrintAndLog("Presco Tag Found: Card ID %08X", cardid);
-       PrintAndLog("Raw: %08X%08X", raw1,raw2);
-       setDemodBuf(DemodBuffer+ans, 64, 0);
-       
-       // uint32_t sitecode = 0, usercode = 0;
-       // GetWiegandFromPresco(id, &sitecode, &usercode);
-       // PrintAndLog8("SiteCode %d  |  UserCode %d", sitecode, usercode);
+       setDemodBuf(DemodBuffer, 128, ans);
        
+       //got a good demod
+       uint32_t raw1 = bytebits_to_byte(DemodBuffer, 32);
+       uint32_t raw2 = bytebits_to_byte(DemodBuffer+32, 32);
+       uint32_t raw3 = bytebits_to_byte(DemodBuffer+64, 32);
+       uint32_t raw4 = bytebits_to_byte(DemodBuffer+96, 32);
+       uint32_t cardid = raw4;
+       PrintAndLog("Presco Tag Found: Card ID %08X, Raw: %08X%08X%08X%08X", cardid, raw1, raw2, raw3, raw4);
+
+       uint32_t sitecode = 0, usercode = 0, fullcode = 0;
+       bool Q5 = false;
+       char cmd[12] = {0};
+       sprintf(cmd, "H %08X", cardid);
+       GetWiegandFromPresco(cmd, &sitecode, &usercode, &fullcode, &Q5);
+       PrintAndLog("SiteCode %u, UserCode %u, FullCode, %08X", sitecode, usercode, fullcode);
        return 1;
 }
 
@@ -109,28 +162,26 @@ int CmdPrescoRead(const char *Cmd) {
        // read lf silently
        CmdLFRead("s");
        // get samples silently
-       getSamples("30000",false);
+       getSamples("12000", TRUE);
        // demod and output Presco ID   
        return CmdPrescoDemod(Cmd);
 }
 
+// takes base 12 ID converts to hex
+// Or takes 8 digit hex ID
 int CmdPrescoClone(const char *Cmd) {
 
-       char cmdp = param_getchar(Cmd, 0);
-       if (strlen(Cmd) == 0 || cmdp == 'h' || cmdp == 'H') return usage_lf_presco_clone();
-
-       uint32_t sitecode=0, usercode=0;
-       uint8_t bits[96];
-       uint8_t *bs = bits;
-       memset(bs,0,sizeof(bits));
-       uint32_t blocks[5] = {T55x7_MODULATION_MANCHESTER | T55x7_BITRATE_RF_32 | 4<<T55x7_MAXBLOCK_SHIFT | T55x7_ST_TERMINATOR, 0, 0, 0, 5};
+       bool Q5 = false;
+       uint32_t sitecode=0, usercode=0, fullcode=0;
+       uint32_t blocks[5] = {T55x7_MODULATION_MANCHESTER | T55x7_BITRATE_RF_32 | 4 << T55x7_MAXBLOCK_SHIFT | T55x7_ST_TERMINATOR, 0, 0, 0, 0};
        
-       if (param_getchar(Cmd, 3) == 'Q' || param_getchar(Cmd, 3) == 'q')
-               blocks[0] = T5555_MODULATION_MANCHESTER | 32<<T5555_BITRATE_SHIFT | 4<<T5555_MAXBLOCK_SHIFT | T5555_ST_TERMINATOR;
-
        // get wiegand from printed number.
-       GetWiegandFromPresco(Cmd, &sitecode, &usercode);
-       
+       if (GetWiegandFromPresco(Cmd, &sitecode, &usercode, &fullcode, &Q5) == -1) return usage_lf_presco_clone();
+
+       if (Q5)
+               //t5555 (Q5) BITRATE = (RF-2)/2 (iceman)
+               blocks[0] = T5555_MODULATION_MANCHESTER | ((32-2)>>1) << T5555_BITRATE_SHIFT | 4 << T5555_MAXBLOCK_SHIFT | T5555_ST_TERMINATOR;
+
        if ((sitecode & 0xFF) != sitecode) {
                sitecode &= 0xFF;
                PrintAndLog("Facility-Code Truncated to 8-bits (Presco): %u", sitecode);
@@ -141,17 +192,12 @@ int CmdPrescoClone(const char *Cmd) {
                PrintAndLog("Card Number Truncated to 16-bits (Presco): %u", usercode);
        }
        
-       if ( !GetPrescoBits(sitecode, usercode, bs)) {
-               PrintAndLog("Error with tag bitstream generation.");
-               return 1;
-       }       
-
-       blocks[1] = bytebits_to_byte(bs,32);
-       blocks[2] = bytebits_to_byte(bs+32,32);
-       blocks[3] = bytebits_to_byte(bs+64,32);
-       blocks[4] = bytebits_to_byte(bs+96,32);
+       blocks[1] = 0x10D00000; //preamble
+       blocks[2] = 0x00000000;
+       blocks[3] = 0x00000000;
+       blocks[4] = fullcode;
 
-       PrintAndLog("Preparing to clone Presco to T55x7 with SiteCode: %u, UserCode: %u", sitecode, usercode);
+       PrintAndLog("Preparing to clone Presco to T55x7 with SiteCode: %u, UserCode: %u, FullCode: %08x", sitecode, usercode, fullcode);
        PrintAndLog("Blk | Data ");
        PrintAndLog("----+------------");
        PrintAndLog(" 00 | 0x%08x", blocks[0]);
@@ -160,54 +206,50 @@ int CmdPrescoClone(const char *Cmd) {
        PrintAndLog(" 03 | 0x%08x", blocks[3]); 
        PrintAndLog(" 04 | 0x%08x", blocks[4]); 
        
-       // UsbCommand resp;
-       // UsbCommand c = {CMD_T55XX_WRITE_BLOCK, {0,0,0}};
-
-       // for (uint8_t i=0; i<5; i++) {
-               // c.arg[0] = blocks[i];
-               // c.arg[1] = i;
-               // clearCommandBuffer();
-               // SendCommand(&c);
-               // if (!WaitForResponseTimeout(CMD_ACK, &resp, 1000)){
-                       // PrintAndLog("Error occurred, device did not respond during write operation.");
-                       // return -1;
-               // }
-       // }
+       UsbCommand resp;
+       UsbCommand c = {CMD_T55XX_WRITE_BLOCK, {0,0,0}};
+
+       for (int i=4; i>=0; i--) {
+               c.arg[0] = blocks[i];
+               c.arg[1] = i;
+               clearCommandBuffer();
+               SendCommand(&c);
+               if (!WaitForResponseTimeout(CMD_ACK, &resp, T55XX_WRITE_TIMEOUT)){
+                       PrintAndLog("Error occurred, device did not respond during write operation.");
+                       return -1;
+               }
+       }
     return 0;
 }
 
+// takes base 12 ID converts to hex
+// Or takes 8 digit hex ID
 int CmdPrescoSim(const char *Cmd) {
-       // uint32_t id = 0;
-       // uint64_t rawID = 0;
-       // uint8_t clk = 32, encoding = 1, separator = 0, invert = 0;
-
-       // char cmdp = param_getchar(Cmd, 0);
-       // if (strlen(Cmd) == 0 || cmdp == 'h' || cmdp == 'H') return usage_lf_presco_sim();
-
-       // id = param_get32ex(Cmd, 0, 0, 16);
-       // if (id == 0) return usage_lf_presco_sim();
+       uint32_t sitecode=0, usercode=0, fullcode=0;
+       bool Q5=false;
+       // get wiegand from printed number.
+       if (GetWiegandFromPresco(Cmd, &sitecode, &usercode, &fullcode, &Q5) == -1) return usage_lf_presco_sim();
 
-       //rawID = getVikingBits(id);
+       uint8_t clk = 32, encoding = 1, separator = 1, invert = 0;
+       uint16_t arg1, arg2;
+       size_t size = 128;
+       arg1 = clk << 8 | encoding;
+       arg2 = invert << 8 | separator;
 
-       // uint16_t arg1, arg2;
-       // size_t size = 64;
-       // arg1 = clk << 8 | encoding;
-       // arg2 = invert << 8 | separator;
+       PrintAndLog("Simulating Presco - SiteCode: %u, UserCode: %u, FullCode: %08X",sitecode, usercode, fullcode);
 
-       // PrintAndLog("Simulating - ID: %08X, Raw: %08X%08X",id,(uint32_t)(rawID >> 32),(uint32_t) (rawID & 0xFFFFFFFF));
-       
-       // UsbCommand c = {CMD_ASK_SIM_TAG, {arg1, arg2, size}};
-       // num_to_bytebits(rawID, size, c.d.asBytes);
-       // clearCommandBuffer();
-       // SendCommand(&c);
+       UsbCommand c = {CMD_ASK_SIM_TAG, {arg1, arg2, size}};
+       GetPrescoBits(fullcode, c.d.asBytes);
+       clearCommandBuffer();
+       SendCommand(&c);
        return 0;
 }
 
 static command_t CommandTable[] = {
     {"help",   CmdHelp,                1, "This help"},
        {"read",        CmdPrescoRead,  0, "Attempt to read and Extract tag data"},
-       {"clone",       CmdPrescoClone, 0, "<8 digit ID number> clone presco tag"},
-//     {"sim",         CmdPrescoSim,   0, "<8 digit ID number> simulate presco tag"},
+       {"clone",       CmdPrescoClone, 0, "d <9 digit ID> or h <hex> [Q5] clone presco tag"},
+       {"sim",         CmdPrescoSim,   0, "d <9 digit ID> or h <hex> simulate presco tag"},
     {NULL, NULL, 0, NULL}
 };
 
Impressum, Datenschutz