]> cvs.zerfleddert.de Git - proxmark3-svn/blobdiff - client/cmdhf.c
Merge pull request #548 from merlokk/mfsniff_fix
[proxmark3-svn] / client / cmdhf.c
index 0d678ab62646b826803304cdd891cb5b1de2b5ed..7a2f3252f368e0648e28b68eaeb693af01a27c21 100644 (file)
@@ -8,11 +8,16 @@
 // High frequency commands
 //-----------------------------------------------------------------------------
 
+#include <stdlib.h>
 #include <stdio.h>
 #include <string.h>
 #include "proxmark3.h"
-#include "graph.h"
+#include "util.h"
+#include "data.h"
 #include "ui.h"
+#include "iso14443crc.h"
+#include "parity.h"
+#include "cmdmain.h"
 #include "cmdparser.h"
 #include "cmdhf.h"
 #include "cmdhf14a.h"
@@ -25,6 +30,7 @@
 #include "cmdhfmfu.h"
 #include "cmdhftopaz.h"
 #include "protocols.h"
+#include "emv/cmdemv.h"
 
 static int CmdHelp(const char *Cmd);
 
@@ -72,11 +78,57 @@ void annotateIso14443a(char *exp, size_t size, uint8_t* cmd, uint8_t cmdsize)
        case MIFARE_CMD_DEC:                    snprintf(exp,size,"DEC(%d)",cmd[1]); break;
        case MIFARE_CMD_RESTORE:                snprintf(exp,size,"RESTORE(%d)",cmd[1]); break;
        case MIFARE_CMD_TRANSFER:               snprintf(exp,size,"TRANSFER(%d)",cmd[1]); break;
-       case MIFARE_AUTH_KEYA:                  snprintf(exp,size,"AUTH-A(%d)",cmd[1]); break;
+       case MIFARE_AUTH_KEYA:{
+               if ( cmdsize > 3)
+                       snprintf(exp,size,"AUTH-A(%d)",cmd[1]); 
+               else
+                       //      case MIFARE_ULEV1_VERSION :  both 0x60.
+                       snprintf(exp,size,"EV1 VERSION");
+               break;
+       }
        case MIFARE_AUTH_KEYB:                  snprintf(exp,size,"AUTH-B(%d)",cmd[1]); break;
        case MIFARE_MAGICWUPC1:                 snprintf(exp,size,"MAGIC WUPC1"); break;
        case MIFARE_MAGICWUPC2:                 snprintf(exp,size,"MAGIC WUPC2"); break;
        case MIFARE_MAGICWIPEC:                 snprintf(exp,size,"MAGIC WIPEC"); break;
+       case MIFARE_ULC_AUTH_1:         snprintf(exp,size,"AUTH "); break;
+       case MIFARE_ULC_AUTH_2:         snprintf(exp,size,"AUTH_ANSW"); break;
+       case MIFARE_ULEV1_AUTH:
+               if ( cmdsize == 7 )
+                       snprintf(exp,size,"PWD-AUTH KEY: 0x%02x%02x%02x%02x", cmd[1], cmd[2], cmd[3], cmd[4] );
+               else
+                       snprintf(exp,size,"PWD-AUTH");
+               break;
+       case MIFARE_ULEV1_FASTREAD:{
+               if ( cmdsize >=3 && cmd[2] <= 0xE6)
+                       snprintf(exp,size,"READ RANGE (%d-%d)",cmd[1],cmd[2]); 
+               else
+                       snprintf(exp,size,"?");
+               break;
+       }
+       case MIFARE_ULC_WRITE:{
+               if ( cmd[1] < 0x21 )
+                       snprintf(exp,size,"WRITEBLOCK(%d)",cmd[1]); 
+               else
+                       snprintf(exp,size,"?");
+               break;
+       }
+       case MIFARE_ULEV1_READ_CNT:{
+               if ( cmd[1] < 5 )
+                       snprintf(exp,size,"READ CNT(%d)",cmd[1]);
+               else
+                       snprintf(exp,size,"?");
+               break;
+       }
+       case MIFARE_ULEV1_INCR_CNT:{
+               if ( cmd[1] < 5 )
+                       snprintf(exp,size,"INCR(%d)",cmd[1]);
+               else
+                       snprintf(exp,size,"?");
+               break;
+       }
+       case MIFARE_ULEV1_READSIG:              snprintf(exp,size,"READ_SIG"); break;
+       case MIFARE_ULEV1_CHECKTEAR:    snprintf(exp,size,"CHK_TEARING(%d)",cmd[1]); break;
+       case MIFARE_ULEV1_VCSL:         snprintf(exp,size,"VCSL"); break;
        default:                                                snprintf(exp,size,"?"); break;
        }
        return;
@@ -145,7 +197,6 @@ void annotateIso15693(char *exp, size_t size, uint8_t* cmd, uint8_t cmdsize)
 
 void annotateTopaz(char *exp, size_t size, uint8_t* cmd, uint8_t cmdsize)
 {
-
        switch(cmd[0]) {
                case TOPAZ_REQA                                         :snprintf(exp, size, "REQA");break;
                case TOPAZ_WUPA                                         :snprintf(exp, size, "WUPA");break;
@@ -154,6 +205,10 @@ void annotateTopaz(char *exp, size_t size, uint8_t* cmd, uint8_t cmdsize)
                case TOPAZ_READ                                         :snprintf(exp, size, "READ");break;
                case TOPAZ_WRITE_E                                      :snprintf(exp, size, "WRITE-E");break;
                case TOPAZ_WRITE_NE                                     :snprintf(exp, size, "WRITE-NE");break;
+               case TOPAZ_RSEG                                         :snprintf(exp, size, "RSEG");break;
+               case TOPAZ_READ8                                        :snprintf(exp, size, "READ8");break;
+               case TOPAZ_WRITE_E8                                     :snprintf(exp, size, "WRITE-E8");break;
+               case TOPAZ_WRITE_NE8                            :snprintf(exp, size, "WRITE-NE8");break;
                default:                            snprintf(exp,size,"?"); break;
        }
 }
@@ -319,7 +374,7 @@ bool next_record_is_response(uint16_t tracepos, uint8_t *trace)
 bool merge_topaz_reader_frames(uint32_t timestamp, uint32_t *duration, uint16_t *tracepos, uint16_t traceLen, uint8_t *trace, uint8_t *frame, uint8_t *topaz_reader_command, uint16_t *data_len)
 {
 
-#define MAX_TOPAZ_READER_CMD_LEN       9
+#define MAX_TOPAZ_READER_CMD_LEN       16
 
        uint32_t last_timestamp = timestamp + *duration;
 
@@ -428,15 +483,9 @@ uint16_t printTraceLine(uint16_t tracepos, uint16_t traceLen, uint8_t *trace, ui
 
        for (int j = 0; j < data_len && j/16 < 16; j++) {
 
-               int oddparity = 0x01;
-               int k;
-
-               for (k=0 ; k<8 ; k++) {
-                       oddparity ^= (((frame[j] & 0xFF) >> k) & 0x01);
-               }
                uint8_t parityBits = parityBytes[j>>3];
-               if (isResponse && (oddparity != ((parityBits >> (7-(j&0x0007))) & 0x01))) {
-                       snprintf(line[j/16]+(( j % 16) * 4), 110, " %02x!", frame[j]);
+               if (protocol != ISO_14443B && (isResponse || protocol == ISO_14443A) && (oddparity8(frame[j]) != ((parityBits >> (7-(j&0x0007))) & 0x01))) {
+                       snprintf(line[j/16]+(( j % 16) * 4),110, "%02x! ", frame[j]);
                } else {
                        snprintf(line[j/16]+(( j % 16) * 4), 110, " %02x ", frame[j]);
                }
@@ -479,7 +528,7 @@ uint16_t printTraceLine(uint16_t tracepos, uint16_t traceLen, uint8_t *trace, ui
        int num_lines = MIN((data_len - 1)/16 + 1, 16);
        for (int j = 0; j < num_lines ; j++) {
                if (j == 0) {
-                       PrintAndLog(" %9d | %9d | %s |%-64s | %s| %s",
+                       PrintAndLog(" %10d | %10d | %s |%-64s | %s| %s",
                                (timestamp - first_timestamp),
                                (EndOfTransmissionTimestamp - first_timestamp),
                                (isResponse ? "Tag" : "Rdr"),
@@ -487,7 +536,7 @@ uint16_t printTraceLine(uint16_t tracepos, uint16_t traceLen, uint8_t *trace, ui
                                (j == num_lines-1) ? crc : "    ",
                                (j == num_lines-1) ? explanation : "");
                } else {
-                       PrintAndLog("           |           |     |%-64s | %s| %s",
+                       PrintAndLog("            |            |     |%-64s | %s| %s",
                                line[j],
                                (j == num_lines-1) ? crc : "    ",
                                (j == num_lines-1) ? explanation : "");
@@ -498,7 +547,7 @@ uint16_t printTraceLine(uint16_t tracepos, uint16_t traceLen, uint8_t *trace, ui
        
        if (showWaitCycles && !isResponse && next_record_is_response(tracepos, trace)) {
                uint32_t next_timestamp = *((uint32_t *)(trace + tracepos));
-               PrintAndLog(" %9d | %9d | %s | fdt (Frame Delay Time): %d",
+               PrintAndLog(" %10d | %10d | %s | fdt (Frame Delay Time): %d",
                        (EndOfTransmissionTimestamp - first_timestamp),
                        (next_timestamp - first_timestamp),
                        "   ",
@@ -514,7 +563,7 @@ int CmdHFList(const char *Cmd)
        bool showWaitCycles = false;
        bool markCRCBytes = false;
        char type[40] = {0};
-       int tlen = param_getstr(Cmd,0,type);
+       int tlen = param_getstr(Cmd,0,type, sizeof(type));
        char param1 = param_getchar(Cmd, 1);
        char param2 = param_getchar(Cmd, 2);
        bool errors = false;
@@ -600,8 +649,8 @@ int CmdHFList(const char *Cmd)
        PrintAndLog("iso14443a - All times are in carrier periods (1/13.56Mhz)");
        PrintAndLog("iClass    - Timings are not as accurate");
        PrintAndLog("");
-       PrintAndLog("     Start |       End | Src | Data (! denotes parity error)                                   | CRC | Annotation         |");
-       PrintAndLog("-----------|-----------|-----|-----------------------------------------------------------------|-----|--------------------|");
+       PrintAndLog("      Start |        End | Src | Data (! denotes parity error)                                   | CRC | Annotation         |");
+       PrintAndLog("------------|------------|-----|-----------------------------------------------------------------|-----|--------------------|");
 
        while(tracepos < traceLen)
        {
@@ -612,6 +661,41 @@ int CmdHFList(const char *Cmd)
        return 0;
 }
 
+int CmdHFSearch(const char *Cmd){
+       int ans = 0;
+       PrintAndLog("");
+       ans = CmdHF14AInfo("s");
+       if (ans > 0) {
+               PrintAndLog("\nValid ISO14443A Tag Found - Quiting Search\n");
+               return ans;
+       }
+       ans = HFiClassReader("", false, false);
+       if (ans) {
+               PrintAndLog("\nValid iClass Tag (or PicoPass Tag) Found - Quiting Search\n");
+               return ans;
+       }
+       ans = HF15Reader("", false);
+       if (ans) {
+               PrintAndLog("\nValid ISO15693 Tag Found - Quiting Search\n");
+               return ans;
+       }
+       //14b is longest test currently (and rarest chip type) ... put last
+       ans = HF14BInfo(false);
+       if (ans) {
+               PrintAndLog("\nValid ISO14443B Tag Found - Quiting Search\n");
+               return ans;
+       }
+       PrintAndLog("\nno known/supported 13.56 MHz tags found\n");
+       return 0;
+}
+
+int CmdHFSnoop(const char *Cmd)
+{
+       char * pEnd;
+       UsbCommand c = {CMD_HF_SNIFFER, {strtol(Cmd, &pEnd,0),strtol(pEnd, &pEnd,0),0}};
+       SendCommand(&c);
+       return 0;
+}
 
 static command_t CommandTable[] = 
 {
@@ -620,6 +704,7 @@ static command_t CommandTable[] =
        {"14b",         CmdHF14B,               1, "{ ISO14443B RFIDs... }"},
        {"15",          CmdHF15,                1, "{ ISO15693 RFIDs... }"},
        {"epa",         CmdHFEPA,               1, "{ German Identification Card... }"},
+       {"emv",         CmdHFEMV,               1, "{ EMV cards... }"},
        {"legic",       CmdHFLegic,             0, "{ LEGIC RFIDs... }"},
        {"iclass",      CmdHFiClass,    1, "{ ICLASS RFIDs... }"},
        {"mf",          CmdHFMF,                1, "{ MIFARE RFIDs... }"},
@@ -627,6 +712,8 @@ static command_t CommandTable[] =
        {"topaz",       CmdHFTopaz,             1, "{ TOPAZ (NFC Type 1) RFIDs... }"},
        {"tune",        CmdHFTune,              0, "Continuously measure HF antenna tuning"},
        {"list",        CmdHFList,              1, "List protocol data in trace buffer"},
+       {"search",      CmdHFSearch,    1, "Search for known HF tags [preliminary]"},
+       {"snoop",   CmdHFSnoop,     0, "<samples to skip (10000)> <triggers to skip (1)> Generic HF Snoop"},
        {NULL,          NULL,                   0, NULL}
 };
 
Impressum, Datenschutz