]> git.zerfleddert.de Git - proxmark3-svn/blobdiff - client/cmdhflegic.c
FIX: one send command bug fixed. Turns out that uint16_t is too small for 21/23bits...
[proxmark3-svn] / client / cmdhflegic.c
index d544a91cca73d5ca9060075b7705b952fb0cf358..889942431e576fdaa41ba83776d7ed7ea6cde79a 100644 (file)
@@ -13,10 +13,10 @@ static int CmdHelp(const char *Cmd);
 
 #define MAX_LENGTH 1024        
 
-int usage_legic_calccrc8(void){
+int usage_legic_calccrc(void){
        PrintAndLog("Calculates the legic crc8/crc16 on the input hexbytes.");
        PrintAndLog("There must be an even number of hexsymbols as input.");
-       PrintAndLog("Usage:  hf legic crc8 [h] b <hexbytes> u <uidcrc> c <crc type>");
+       PrintAndLog("Usage:  hf legic crc [h] b <hexbytes> u <uidcrc> c <crc type>");
        PrintAndLog("Options:");
        PrintAndLog("      h             : this help");
        PrintAndLog("      b <hexbytes>  : hex bytes");
@@ -24,8 +24,8 @@ int usage_legic_calccrc8(void){
        PrintAndLog("      c <crc type>  : 8|16 bit crc size");
        PrintAndLog("");
        PrintAndLog("Samples:");
-       PrintAndLog("      hf legic crc8 b deadbeef1122");
-       PrintAndLog("      hf legic crc8 b deadbeef1122 u 9A c 16");
+       PrintAndLog("      hf legic crc b deadbeef1122");
+       PrintAndLog("      hf legic crc b deadbeef1122 u 9A c 16");
        return 0;
 }
 int usage_legic_load(void){
@@ -60,28 +60,15 @@ int usage_legic_sim(void){
 }
 int usage_legic_write(void){
        PrintAndLog(" Write sample buffer to a legic tag. (use after load or read)");
-       PrintAndLog("Usage:  hf legic write [h] <offset> <length> <IV>");
+       PrintAndLog("Usage:  hf legic write [h] o <offset> d <data (hex symbols)>");
        PrintAndLog("Options:");
        PrintAndLog("  h             : this help");
-       PrintAndLog("  <offset>      : offset in data array to start writing from (hex)");
-       PrintAndLog("  <length>      : number of bytes to write (hex)");
-       PrintAndLog("  <IV>          : (optional) Initialization vector to use (ODD and 7bits)");
+       PrintAndLog("  o <offset>    : offset in data array to start writing");
+       //PrintAndLog("  <IV>          : (optional) Initialization vector to use (ODD and 7bits)");
+       PrintAndLog("  d <data>      : bytes to write (hex symbols)");
        PrintAndLog("");
        PrintAndLog("Samples:");
-       PrintAndLog("      hf legic write 10 4      - writes 0x4 to byte[0x10]");
-       return 0;
-}
-int usage_legic_rawwrite(void){
-       PrintAndLog("Write raw data direct to a specific offset on legic tag.");
-       PrintAndLog("Usage:  hf legic writeraw [h] <offset> <value> <IV>");
-       PrintAndLog("Options:");
-       PrintAndLog("  h             : this help");
-       PrintAndLog("  <offset>      : offset to write to (hex)");
-       PrintAndLog("  <value>       : value (hex)");
-       PrintAndLog("  <IV>          : (optional) Initialization vector to use (hex, odd and 7bits)");
-       PrintAndLog("");
-       PrintAndLog("Samples:");
-       PrintAndLog("      hf legic writeraw 10 4    - writes 0x4 to byte[0x10]");
+       PrintAndLog("      hf legic write o 10 d 11223344    - Write 0x11223344 starting from offset 0x10");
        return 0;
 }
 int usage_legic_reader(void){
@@ -119,7 +106,6 @@ int usage_legic_dump(void){
        PrintAndLog("      hf legic dump o myfile");
        return 0;
 }
-
 int usage_legic_eload(void){
        PrintAndLog("It loads binary dump from the file `filename.bin`");
        PrintAndLog("Usage:  hf legic eload [h] [card memory] <file name w/o `.bin`>");
@@ -152,7 +138,6 @@ int usage_legic_esave(void){
        return 0;
 }
 
-
 /*
  *  Output BigBuf and deobfuscate LEGIC RF tag data.
  *  This is based on information given in the talk held
@@ -447,11 +432,11 @@ int CmdLegicInfo(const char *Cmd) {
        return 0;
 }
 
+// params:
+// offset in data memory
+// number of bytes to read
 int CmdLegicRdmem(const char *Cmd) {
 
-       // params:
-       // offset in data memory
-       // number of bytes to read
        char cmdp = param_getchar(Cmd, 0);
        if ( cmdp == 'H' || cmdp == 'h' ) return usage_legic_rdmem();
        
@@ -470,39 +455,39 @@ int CmdLegicRdmem(const char *Cmd) {
        clearCommandBuffer();
        SendCommand(&c);
        UsbCommand resp;
-       if (WaitForResponseTimeout(CMD_ACK, &resp, 3000)) {
-               uint8_t isOK = resp.arg[0] & 0xFF;
-               uint16_t readlen = resp.arg[1];
-                if ( isOK ) {
-
-                       uint8_t *data = malloc(readlen);
-                       if ( !data ){
-                               PrintAndLog("Cannot allocate memory");
-                               return 2;
-                       }
+       if ( !WaitForResponseTimeout(CMD_ACK, &resp, 3000) ) {
+               PrintAndLog("command execution time out");
+               return 1;
+       }
+
+       uint8_t isOK = resp.arg[0] & 0xFF;
+       uint16_t readlen = resp.arg[1];
+       if ( !isOK ) {
+               PrintAndLog("failed reading tag");
+               return 2;
+       }
+       
+       uint8_t *data = malloc(readlen);
+       if ( !data ){
+               PrintAndLog("Cannot allocate memory");
+               return 2;
+       }
                        
-                       if ( readlen != len )
-                               PrintAndLog("Fail, only managed to read 0x%02X bytes", readlen);
+       if ( readlen != len )
+               PrintAndLog("Fail, only managed to read 0x%02X bytes", readlen);
                        
-                       // copy data from device
-                       GetEMLFromBigBuf(data, readlen, 0);
-                       if ( !WaitForResponseTimeout(CMD_ACK, NULL, 2500)){
-                               PrintAndLog("Command execute timeout");
-                               if ( data ) 
-                                       free(data);
-                               return 1;
-                       }
-       
-                       PrintAndLog("\n ##  | Data");
-                       PrintAndLog("-----+-----");
-                       print_hex_break( data, readlen, 32);
-                } else {
-                        PrintAndLog("failed reading tag");
-                }
-       } else {
-               PrintAndLog("command execution time out");
+       // copy data from device
+       GetEMLFromBigBuf(data, readlen, 0);
+       if ( !WaitForResponseTimeout(CMD_ACK, NULL, 2500)){
+               PrintAndLog("Command execute timeout");
+               free(data);
                return 1;
        }
+       
+       PrintAndLog("\n ##  | Data");
+       PrintAndLog("-----+-----");
+       print_hex_break( data, readlen, 32);
+       free(data);
        return 0;
 }
 
@@ -553,7 +538,6 @@ int CmdLegicLoad(const char *Cmd) {
                index += res;
                        
                if ( index == USB_CMD_DATA_SIZE ){
-//                     PrintAndLog("sent %d | %d | %d", index, offset, totalbytes);
                        UsbCommand c = { CMD_DOWNLOADED_SIM_SAMPLES_125K, {offset, 0, 0}};
                        memcpy(c.d.asBytes, data, sizeof(data));
                        clearCommandBuffer();
@@ -655,20 +639,74 @@ int CmdLegicRfSim(const char *Cmd) {
 
 int CmdLegicRfWrite(const char *Cmd) {
 
-       // offset - in tag memory
-       // length - num of bytes to be written
-
-       char cmdp = param_getchar(Cmd, 0);
-       if ( cmdp == 'H' || cmdp == 'h' ) return usage_legic_write();
-       
-       uint32_t offset = 0, len = 0, IV = 0;
-       
-    int res = sscanf(Cmd, "%x %x %x", &offset, &len, &IV);
-       if(res < 2) {
-               PrintAndLog("Please specify the offset and length as two hex strings and, optionally, the IV also as an hex string");
-        return -1;
-    }
+       uint8_t *data = NULL;
+       uint8_t cmdp = 0;
+       bool errors = false;
+       int len = 0, bg, en;
+       uint32_t offset = 0, IV = 0x55;
        
+       while(param_getchar(Cmd, cmdp) != 0x00) {
+               switch(param_getchar(Cmd, cmdp)) {
+               case 'd':
+               case 'D':
+                       // peek at length of the input string so we can
+                       // figure out how many elements to malloc in "data"
+                       bg=en=0;
+                       if (param_getptr(Cmd, &bg, &en, cmdp+1)) {
+                               errors = true;
+                               break;
+                       }
+                       len = (en - bg + 1);
+
+                       // check that user entered even number of characters
+                       // for hex data string
+                       if (len & 1) {
+                               errors = true;
+                               break;
+                       }
+
+                       // it's possible for user to accidentally enter "b" parameter
+                       // more than once - we have to clean previous malloc
+                       if (data)
+                               free(data);
+                       data = malloc(len >> 1);
+                       if ( data == NULL ) {
+                               PrintAndLog("Can't allocate memory. exiting");
+                               errors = true;
+                               break;
+                       }
+                       
+                       if (param_gethex(Cmd, cmdp+1, data, len)) {
+                               errors = true;
+                               break;
+                       }
+
+                       len >>= 1;      
+                       cmdp += 2;
+                       break;
+               case 'o':
+               case 'O':
+                       offset = param_get32ex(Cmd, cmdp+1, 4, 10);
+                       cmdp += 2;
+                       break;
+               case 'h':
+               case 'H':
+                       errors = true;
+                       break;
+               default:
+                       PrintAndLog("Unknown parameter '%c'", param_getchar(Cmd, cmdp));
+                       errors = true;
+                       break;
+               }
+               if (errors) break;
+       }
+       //Validations
+       if (errors){
+               if (data) 
+                       free(data);
+               return usage_legic_write();
+       }
+
        // tagtype
        legic_card_select_t card;
        if (legic_get_type(&card)) {
@@ -679,107 +717,48 @@ int CmdLegicRfWrite(const char *Cmd) {
        legic_print_type(card.cardsize, 0);
        
        // OUT-OF-BOUNDS check
-       if ( len + offset > card.cardsize ) {
-               PrintAndLog("Out-of-bounds, Cardsize = %d, [offset+len = %d ]", card.cardsize, len + offset);
+       // UID 4 bytes can't be written to.
+       if ( len + offset + 4 >= card.cardsize ) {
+               PrintAndLog("Out-of-bounds, Cardsize = %d, [offset+len = %d ]", card.cardsize, len + offset + 4);
                return -2;
        }
-       
+
        legic_chk_iv(&IV);
        
-    UsbCommand c = {CMD_WRITER_LEGIC_RF, {offset, len, IV}};   
+       PrintAndLog("Writing to tag");
+    UsbCommand c = {CMD_WRITER_LEGIC_RF, {offset, len, IV}};
+       memcpy(c.d.asBytes, data, len);
+       
        clearCommandBuffer();
     SendCommand(&c);
        UsbCommand resp;
-       if (WaitForResponseTimeout(CMD_ACK, &resp, 2000)) {
-               uint8_t isOK = resp.arg[0] & 0xFF;
-                if ( !isOK )
-                        PrintAndLog("failed writing tag");
-       } else {
+       if (!WaitForResponseTimeout(CMD_ACK, &resp, 4000)) {
                PrintAndLog("command execution time out");
                return 1;
        }
+       uint8_t isOK = resp.arg[0] & 0xFF;
+       if ( !isOK ) {
+               PrintAndLog("failed writing tag");
+               return 1;
+       }
        
     return 0;
 }
 
+/*
 int CmdLegicRfRawWrite(const char *Cmd) {
-
-       char cmdp = param_getchar(Cmd, 0);
-       if ( cmdp == 'H' || cmdp == 'h' ) return usage_legic_rawwrite();
-       
-       uint32_t offset = 0, data = 0, IV = 0;  
-       char answer;
-
-    int res = sscanf(Cmd, "%x %x %x", &offset, &data, &IV);
-       if(res < 2)
-               return usage_legic_rawwrite();
-       
-       // OUT-OF-BOUNDS check
-       if ( offset > MAX_LENGTH ) {
-               PrintAndLog("Out-of-bound, offset");
-               return 1;
-       }
-       
-       if ( (IV & 0x7F) != IV ){
-               IV &= 0x7F;
-               PrintAndLog("Truncating IV to 7bits");
-       }
-       if ( (IV & 1) == 0 ){
-               IV |= 0x01;  // IV must be odd
-               PrintAndLog("LSB of IV must be SET");   
-       }
-
-       UsbCommand c = { CMD_RAW_WRITER_LEGIC_RF, {offset, data, IV} };
-       
-       if (c.arg[0] == 0x05 || c.arg[0] == 0x06) {
-               PrintAndLog("############# DANGER !! #############");
-               PrintAndLog("# changing the DCF is irreversible  #");
-               PrintAndLog("#####################################");
-               PrintAndLog("do youe really want to continue? y(es) n(o)");             
-               if (scanf(" %c", &answer) > 0 && (answer == 'y' || answer == 'Y')) {
-                       SendCommand(&c);
-                       return 0;
-               }
-               return -1;
-       }
-       
-       clearCommandBuffer();
-    SendCommand(&c);
+       PrintAndLog("############# DANGER !! #############");
+       PrintAndLog("# changing the DCF is irreversible  #");
+       PrintAndLog("#####################################");
+       PrintAndLog("do youe really want to continue? y(es) n(o)");             
+       // if (scanf(" %c", &answer) > 0 && (answer == 'y' || answer == 'Y')) {
+               // return 0;
+       // }
        return 0;
 }
+*/
 
-void static calc4(uint8_t *cmd, uint8_t len){
-       crc_t crc;
-       //crc_init_ref(&crc, 4, 0x19 >> 1, 0x5, 0, TRUE, TRUE);
-       crc_init(&crc, 4, 0x19 >> 1, 0x5, 0);
-
-       crc_clear(&crc);
-       crc_update(&crc, 1, 1); /* CMD_READ */
-       crc_update(&crc, cmd[0], 8);
-       crc_update(&crc, cmd[1], 8);
-       printf("crc4 %X\n", reflect(crc_finish(&crc), 4) ) ;
-
-       crc_clear(&crc);
-       crc_update(&crc, 1, 1); /* CMD_READ */
-       crc_update(&crc, cmd[0], 8);
-       crc_update(&crc, cmd[1], 8);
-       printf("crc4 %X\n",  crc_finish(&crc) ) ;
-
-       printf("---- old ---\n");
-       crc_update2(&crc, 1, 1); /* CMD_READ */
-       crc_update2(&crc, cmd[0], 8);
-       crc_update2(&crc, cmd[1], 8);
-       printf("crc4 %X \n", reflect(crc_finish(&crc), 4) ) ;
-
-       
-       crc_clear(&crc);
-       crc_update2(&crc, 1, 1); /* CMD_READ */
-       crc_update2(&crc, cmd[0], 8);
-       crc_update2(&crc, cmd[1], 8);
-       printf("crc4 %X\n",  crc_finish(&crc) ) ;
-}      
-int CmdLegicCalcCrc8(const char *Cmd){
+int CmdLegicCalcCrc(const char *Cmd){
 
        uint8_t *data = NULL;
        uint8_t cmdp = 0, uidcrc = 0, type=0;
@@ -849,16 +828,13 @@ int CmdLegicCalcCrc8(const char *Cmd){
        //Validations
        if (errors){
                if (data) free(data);
-               return usage_legic_calccrc8();
+               return usage_legic_calccrc();
        }
        
        switch (type){
                case 16:
                        PrintAndLog("Legic crc16: %X", CRC16Legic(data, len, uidcrc));
                        break;
-               case 4:
-                       calc4(data, 0);
-                       break;
                default:
                        PrintAndLog("Legic crc8: %X",  CRC8Legic(data, len) );
                        break;
@@ -912,18 +888,15 @@ void legic_chk_iv(uint32_t *iv){
                PrintAndLog("LSB of IV must be SET %u", *iv);   
        }
 }
-
 void legic_seteml(uint8_t *src, uint32_t offset, uint32_t numofbytes) {
-
        size_t len = 0;
        UsbCommand c = {CMD_LEGIC_ESET, {0, 0, 0}};     
-
        for(size_t i = 0; i < numofbytes; i += USB_CMD_DATA_SIZE) {
                
                len = MIN((numofbytes - i), USB_CMD_DATA_SIZE);         
                c.arg[0] = i; // offset
                c.arg[1] = len; // number of bytes
-               memcpy(c.d.asBytes, src, len); 
+               memcpy(c.d.asBytes, src+i, len); 
                clearCommandBuffer();
                SendCommand(&c);
                PrintAndLog("ICE: offset %d | len %d", i, len);
@@ -1023,6 +996,7 @@ int CmdLegicDump(const char *Cmd){
                PrintAndLog("Fail, cannot allocate memory");
                return 3;
        }
+       memset(data, 0, readlen);
        
        if ( readlen != dumplen )
                PrintAndLog("Fail, only managed to read 0x%02X bytes of 0x%02X", readlen, dumplen);
@@ -1148,8 +1122,7 @@ int CmdLegicESave(const char *Cmd) {
        memset(data, 0, numofbytes);
                
        // download emulator memory
-       PrintAndLog("Reading emulator memory...");
-       
+       PrintAndLog("Reading emulator memory...");      
        GetEMLFromBigBuf(data, numofbytes, 0);
        if ( !WaitForResponseTimeout(CMD_ACK, NULL, 2500)) {
                PrintAndLog("Fail, transfer from device time-out");
@@ -1186,7 +1159,7 @@ static command_t CommandTable[] =  {
        {"load",        CmdLegicLoad,           0, "<filename> -- Restore samples"},
        {"sim",         CmdLegicRfSim,          0, "[phase drift [frame drift [req/resp drift]]] Start tag simulator (use after load or read)"},
        {"write",       CmdLegicRfWrite,        0, "<offset> <length> <iv> -- Write sample buffer (user after load or read)"},
-       {"crc8",        CmdLegicCalcCrc8,       1, "Calculate Legic CRC8 over given hexbytes"}, 
+       {"crc",         CmdLegicCalcCrc,        1, "Calculate Legic CRC over given hexbytes"},  
        {"eload",       CmdLegicELoad,          1, "Load binary dump to emulator memory"},
        {"esave",       CmdLegicESave,          1, "Save emulator memory to binary file"},
        {NULL, NULL, 0, NULL}
Impressum, Datenschutz