]> git.zerfleddert.de Git - proxmark3-svn/blobdiff - client/cmdlfem4x.c
lf read adjustments
[proxmark3-svn] / client / cmdlfem4x.c
index 12300955da5172f6186cb5ca6d240ea1ae11183e..6b1fa8838a033d0e3e14377eb2e772bd2678108a 100644 (file)
@@ -11,6 +11,7 @@
 #include <stdio.h>
 #include <string.h>
 #include <inttypes.h>
+#include "cmdlfem4x.h"
 #include "proxmark3.h"
 #include "ui.h"
 #include "util.h"
@@ -21,6 +22,7 @@
 #include "cmdlf.h"
 #include "cmdmain.h"
 #include "lfdemod.h"
+#include "protocols.h"
 
 uint64_t g_em410xId=0;
 
@@ -144,17 +146,18 @@ void printEM410x(uint32_t hi, uint64_t id)
 int AskEm410xDecode(bool verbose, uint32_t *hi, uint64_t *lo )
 {
        size_t idx = 0;
-       size_t BitLen = DemodBufferLen;
-       uint8_t BitStream[MAX_GRAPH_TRACE_LEN]={0};
-       memcpy(BitStream, DemodBuffer, BitLen); 
-       if (Em410xDecode(BitStream, &BitLen, &idx, hi, lo)){
+       uint8_t BitStream[512]={0};
+       size_t BitLen = sizeof(BitStream);
+       if ( !getDemodBuf(BitStream, &BitLen) ) return 0;
+
+       if (Em410xDecode(BitStream, &BitLen, &idx, hi, lo)) {
                //set GraphBuffer for clone or sim command
                setDemodBuf(BitStream, BitLen, idx);
-               if (g_debugMode){
+               if (g_debugMode) {
                        PrintAndLog("DEBUG: idx: %d, Len: %d, Printing Demod Buffer:", idx, BitLen);
                        printDemodBuff();
                }
-               if (verbose){
+               if (verbose) {
                        PrintAndLog("EM410x pattern found: ");
                        printEM410x(*hi, *lo);
                        g_em410xId = *lo;
@@ -296,9 +299,7 @@ int CmdEM410xWatch(const char *Cmd)
                        printf("\naborted via keyboard!\n");
                        break;
                }
-               
-               CmdLFRead("s");
-               getSamples("8201",true); 
+               lf_read(true, 8201);
        } while (!CmdAskEM410xDemod(""));
 
        return 0;
@@ -898,47 +899,35 @@ int CmdEM4x05dump(const char *Cmd) {
 int usage_lf_em_write(void) {
        PrintAndLog("Write EM4x05/EM4x69.  Tag must be on antenna. ");
        PrintAndLog("");
-       PrintAndLog("Usage:  lf em 4x05writeword [h] [s] <address> <data> <pwd>");
+       PrintAndLog("Usage:  lf em 4x05writeword [h] a <address> d <data> p <pwd> [s] [i]");
        PrintAndLog("Options:");
-       PrintAndLog("       h         - this help");
-       PrintAndLog("       s         - swap data bit order before write");
-       PrintAndLog("       address   - memory address to write to. (0-15)");
-       PrintAndLog("       data      - data to write (hex)");  
-       PrintAndLog("       pwd       - password (hex) (optional)");
+       PrintAndLog("       h           - this help");
+       PrintAndLog("       a <address> - memory address to write to. (0-15)");
+       PrintAndLog("       d <data>    - data to write (hex)");        
+       PrintAndLog("       p <pwd>     - password (hex) (optional)");
+       PrintAndLog("       s           - swap the data bit order before write");
+       PrintAndLog("       i           - invert the data bits before write");
        PrintAndLog("samples:");
-       PrintAndLog("      lf em 4x05writeword 1");
-       PrintAndLog("      lf em 4x05writeword 1 deadc0de 11223344");
+       PrintAndLog("      lf em 4x05writeword a 5 d 11223344");
+       PrintAndLog("      lf em 4x05writeword a 5 p deadc0de d 11223344 s i");
        return 0;
 }
 
-int CmdEM4x05WriteWord(const char *Cmd) {
-       uint8_t ctmp = param_getchar(Cmd, 0);
-       if ( strlen(Cmd) == 0 || ctmp == 'H' || ctmp == 'h' ) return usage_lf_em_write();
-
-       bool usePwd = false;
+// note: em4x05 doesn't have a way to invert data output so we must invert the data prior to writing
+//         it if invertion is needed. (example FSK2a vs FSK)
+//       also em4x05 requires swapping word data when compared to the data used for t55xx chips.
+int EM4x05WriteWord(uint8_t addr, uint32_t data, uint32_t pwd, bool usePwd, bool swap, bool invert) {
+       if (swap) data = SwapBits(data, 32);
 
-       uint8_t addr = 16; // default to invalid address
-       uint32_t data = 0xFFFFFFFF; // default to blank data
-       uint32_t pwd = 0xFFFFFFFF; // default to blank password
-       char swap = 0;
-
-       int p = 0;
-       swap = param_getchar(Cmd, 0);
-       if (swap == 's' || swap=='S') p++;
-       addr = param_get8ex(Cmd, p++, 16, 10);
-       data = param_get32ex(Cmd, p++, 0, 16);
-       pwd  = param_get32ex(Cmd, p++, 1, 16);
-
-       if (swap == 's' || swap=='S') data = SwapBits(data, 32);
+       if (invert) data ^= 0xFFFFFFFF;
 
        if ( (addr > 15) ) {
                PrintAndLog("Address must be between 0 and 15");
-               return 1;
+               return -1;
        }
-       if ( pwd == 1 )
-               PrintAndLog("Writing address %d data %08X", addr, data);        
-       else {
-               usePwd = true;
+       if ( !usePwd ) {
+               PrintAndLog("Writing address %d data %08X", addr, data);
+       } else {
                PrintAndLog("Writing address %d data %08X using password %08X", addr, data, pwd);
        }
 
@@ -967,8 +956,75 @@ int CmdEM4x05WriteWord(const char *Cmd) {
        return result;
 }
 
+int CmdEM4x05WriteWord(const char *Cmd) {
+       bool errors = false;
+       bool usePwd = false;
+       uint32_t data = 0xFFFFFFFF;
+       uint32_t pwd = 0xFFFFFFFF;
+       bool swap = false;
+       bool invert = false;
+       uint8_t addr = 16; // default to invalid address
+       bool gotData = false;
+       char cmdp = 0;
+       while(param_getchar(Cmd, cmdp) != 0x00)
+       {
+               switch(param_getchar(Cmd, cmdp))
+               {
+               case 'h':
+               case 'H':
+                       return usage_lf_em_write();
+               case 'a':
+               case 'A':
+                       addr = param_get8ex(Cmd, cmdp+1, 16, 10);
+                       cmdp += 2;
+                       break;
+               case 'd':
+               case 'D':
+                       data = param_get32ex(Cmd, cmdp+1, 0, 16);
+                       gotData = true;
+                       cmdp += 2;
+                       break;
+               case 'i':
+               case 'I':
+                       invert = true;
+                       cmdp++;
+                       break;
+               case 'p':
+               case 'P':
+                       pwd = param_get32ex(Cmd, cmdp+1, 1, 16);
+                       if (pwd == 1) {
+                               PrintAndLog("invalid pwd");
+                               errors = true;
+                       }
+                       usePwd = true;
+                       cmdp += 2;
+                       break;
+               case 's':
+               case 'S':
+                       swap = true;
+                       cmdp++;
+                       break;
+               default:
+                       PrintAndLog("Unknown parameter '%c'", param_getchar(Cmd, cmdp));
+                       errors = true;
+                       break;
+               }
+               if(errors) break;
+       }
+       //Validations
+       if(errors) return usage_lf_em_write();
+
+       if ( strlen(Cmd) == 0 ) return usage_lf_em_write();
+
+       if (!gotData) {
+               PrintAndLog("You must enter the data you want to write");
+               return usage_lf_em_write();
+       }
+       return EM4x05WriteWord(addr, data, pwd, usePwd, swap, invert);
+}
+
 void printEM4x05config(uint32_t wordData) {
-       uint16_t datarate = (((wordData & 0x3F)+1)*2);
+       uint16_t datarate = EM4x05_GET_BITRATE(wordData);
        uint8_t encoder = ((wordData >> 6) & 0xF);
        char enc[14];
        memset(enc,0,sizeof(enc));
@@ -979,8 +1035,8 @@ void printEM4x05config(uint32_t wordData) {
        uint8_t delay = (wordData >> 12) & 0x3;
        char cdelay[33];
        memset(cdelay,0,sizeof(cdelay));
-       uint8_t LWR = (wordData >> 14) & 0xF; //last word read
-
+       uint8_t numblks = EM4x05_GET_NUM_BLOCKS(wordData);
+       uint8_t LWR = numblks+5-1; //last word read
        switch (encoder) {
                case 0: snprintf(enc,sizeof(enc),"NRZ"); break;
                case 1: snprintf(enc,sizeof(enc),"Manchester"); break;
@@ -1008,21 +1064,29 @@ void printEM4x05config(uint32_t wordData) {
                case 2: snprintf(cdelay, sizeof(cdelay),"BP/4 or 1/4th bit period delay"); break;
                case 3: snprintf(cdelay, sizeof(cdelay),"no delay"); break;
        }
+       uint8_t readLogin = (wordData & EM4x05_READ_LOGIN_REQ)>>18;
+       uint8_t readHKL = (wordData & EM4x05_READ_HK_LOGIN_REQ)>>19;
+       uint8_t writeLogin = (wordData & EM4x05_WRITE_LOGIN_REQ)>>20;
+       uint8_t writeHKL = (wordData & EM4x05_WRITE_HK_LOGIN_REQ)>>21;
+       uint8_t raw = (wordData & EM4x05_READ_AFTER_WRITE)>>22;
+       uint8_t disable = (wordData & EM4x05_DISABLE_ALLOWED)>>23;
+       uint8_t rtf = (wordData & EM4x05_READER_TALK_FIRST)>>24;
+       uint8_t pigeon = (wordData & (1<<26))>>26;
        PrintAndLog("ConfigWord: %08X (Word 4)\n", wordData);
-       PrintAndLog("Config Breakdown:", wordData);
+       PrintAndLog("Config Breakdown:");
        PrintAndLog(" Data Rate:  %02u | RF/%u", wordData & 0x3F, datarate);
        PrintAndLog("   Encoder:   %u | %s", encoder, enc);
        PrintAndLog("    PSK CF:   %u | %s", PSKcf, cf);
        PrintAndLog("     Delay:   %u | %s", delay, cdelay);
-       PrintAndLog(" LastWordR:  %02u | Address of last word for default read", LWR);
-       PrintAndLog(" ReadLogin:   %u | Read Login is %s", (wordData & 0x40000)>>18, (wordData & 0x40000) ? "Required" : "Not Required");       
-       PrintAndLog("   ReadHKL:   %u | Read Housekeeping Words Login is %s", (wordData & 0x80000)>>19, (wordData & 0x80000) ? "Required" : "Not Required");    
-       PrintAndLog("WriteLogin:   %u | Write Login is %s", (wordData & 0x100000)>>20, (wordData & 0x100000) ? "Required" : "Not Required");    
-       PrintAndLog("  WriteHKL:   %u | Write Housekeeping Words Login is %s", (wordData & 0x200000)>>21, (wordData & 0x200000) ? "Required" : "Not Required"); 
-       PrintAndLog("    R.A.W.:   %u | Read After Write is %s", (wordData & 0x400000)>>22, (wordData & 0x400000) ? "On" : "Off");
-       PrintAndLog("   Disable:   %u | Disable Command is %s", (wordData & 0x800000)>>23, (wordData & 0x800000) ? "Accepted" : "Not Accepted");
-       PrintAndLog("    R.T.F.:   %u | Reader Talk First is %s", (wordData & 0x1000000)>>24, (wordData & 0x1000000) ? "Enabled" : "Disabled");
-       PrintAndLog("    Pigeon:   %u | Pigeon Mode is %s\n", (wordData & 0x4000000)>>26, (wordData & 0x4000000) ? "Enabled" : "Disabled");
+       PrintAndLog(" LastWordR:  %02u | Address of last word for default read - meaning %u blocks are output", LWR, numblks);
+       PrintAndLog(" ReadLogin:   %u | Read Login is %s", readLogin, readLogin ? "Required" : "Not Required"); 
+       PrintAndLog("   ReadHKL:   %u | Read Housekeeping Words Login is %s", readHKL, readHKL ? "Required" : "Not Required");  
+       PrintAndLog("WriteLogin:   %u | Write Login is %s", writeLogin, writeLogin ? "Required" : "Not Required");      
+       PrintAndLog("  WriteHKL:   %u | Write Housekeeping Words Login is %s", writeHKL, writeHKL ? "Required" : "Not Required");       
+       PrintAndLog("    R.A.W.:   %u | Read After Write is %s", raw, raw ? "On" : "Off");
+       PrintAndLog("   Disable:   %u | Disable Command is %s", disable, disable ? "Accepted" : "Not Accepted");
+       PrintAndLog("    R.T.F.:   %u | Reader Talk First is %s", rtf, rtf ? "Enabled" : "Disabled");
+       PrintAndLog("    Pigeon:   %u | Pigeon Mode is %s\n", pigeon, pigeon ? "Enabled" : "Disabled");
 }
 
 void printEM4x05info(uint8_t chipType, uint8_t cap, uint16_t custCode, uint32_t serial) {
@@ -1101,6 +1165,7 @@ int CmdEM4x05info(const char *Cmd) {
        wordData = 0;
        if ( EM4x05ReadWord_ext(4, pwd, usePwd, &wordData) != 1 ) {
                //failed
+               PrintAndLog("Config block read failed - might be password protected.");
                return 0;
        }
        printEM4x05config(wordData);
Impressum, Datenschutz