]> cvs.zerfleddert.de Git - proxmark3-svn/commitdiff
Merge branch 'master' of github.com:merlokk/proxmark3 into 14a_rework3
authormerlokk <olegmsn@gmail.com>
Wed, 1 Nov 2017 15:13:27 +0000 (17:13 +0200)
committermerlokk <olegmsn@gmail.com>
Wed, 1 Nov 2017 15:13:27 +0000 (17:13 +0200)
1  2 
armsrc/iso14443a.c
client/cmdhf14a.c
client/cmdhf14a.h

diff --combined armsrc/iso14443a.c
index 860af2382b1e39a54efc8eae9d666fc438b20c01,06a83feb72693d4b252556059f708f3416083065..7d4840154d3d33ffdc223b7bce341a881a43851a
@@@ -1698,6 -1698,13 +1698,13 @@@ int iso14443a_select_card(byte_t *uid_p
        int cascade_level = 0;
        int len;
  
+       // init card struct
+       if(p_hi14a_card) {
+               p_hi14a_card->uidlen = 0;
+               memset(p_hi14a_card->uid, 0, 10);
+               p_hi14a_card->ats_len = 0;
+       }
        // Broadcast for a card, WUPA (0x52) will force response from all cards in the field
      ReaderTransmitBitsPar(wupa, 7, NULL, NULL);
        
  
        if(p_hi14a_card) {
                memcpy(p_hi14a_card->atqa, resp, 2);
-               p_hi14a_card->uidlen = 0;
-               memset(p_hi14a_card->uid,0,10);
        }
  
        if (anticollision) {
  
        if(p_hi14a_card) {
                p_hi14a_card->sak = sak;
-               p_hi14a_card->ats_len = 0;
        }
  
        // non iso14443a compliant tag
 -      if( (sak & 0x20) == 0) return 2; 
 +      // https://www.nxp.com/docs/en/application-note/AN10834.pdf page 7
 +      if( (sak & 0x20) != 0) return 2; 
  
        if (!no_rats) {
                // Request for answer to select
@@@ -1909,9 -1912,8 +1913,9 @@@ void ReaderIso14443a(UsbCommand *c
        size_t lenbits = c->arg[1] >> 16;
        uint32_t timeout = c->arg[2];
        uint32_t arg0 = 0;
-       byte_t buf[USB_CMD_DATA_SIZE];
+       byte_t buf[USB_CMD_DATA_SIZE] = {0};
        uint8_t par[MAX_PARITY_SIZE];
 +      bool cantSELECT = false;
    
        if(param & ISO14A_CONNECT) {
                clear_trace();
        }
  
        if(param & ISO14A_CONNECT) {
 +              LED_A_ON();
 +              clear_trace();
                iso14443a_setup(FPGA_HF_ISO14443A_READER_LISTEN);
                if(!(param & ISO14A_NO_SELECT)) {
                        iso14a_card_select_t *card = (iso14a_card_select_t*)buf;
                        arg0 = iso14443a_select_card(NULL, card, NULL, true, 0, param & ISO14A_NO_RATS);
 +
 +                      // if we cant select then we cant send data
 +                      cantSELECT = (arg0 != 1);
 +                      
 +                      LED_B_ON();
                        cmd_send(CMD_ACK,arg0,card->uidlen,0,buf,sizeof(iso14a_card_select_t));
 +                      LED_B_OFF();
                }
        }
  
                iso14a_set_timeout(timeout);
        }
  
 -      if(param & ISO14A_APDU) {
 +      if(param & ISO14A_APDU && !cantSELECT) {
                arg0 = iso14_apdu(cmd, len, buf);
 +              LED_B_ON();
                cmd_send(CMD_ACK,arg0,0,0,buf,sizeof(buf));
 +              LED_B_OFF();
        }
  
 -      if(param & ISO14A_RAW) {
 +      if(param & ISO14A_RAW && !cantSELECT) {
                if(param & ISO14A_APPEND_CRC) {
                        if(param & ISO14A_TOPAZMODE) {
                                AppendCrc14443b(cmd,len);
                        }
                }
                arg0 = ReaderReceive(buf, par);
 +
 +              LED_B_ON();
                cmd_send(CMD_ACK,arg0,0,0,buf,sizeof(buf));
 +              LED_B_OFF();
        }
  
        if(param & ISO14A_REQUEST_TRIGGER) {
diff --combined client/cmdhf14a.c
index 1a7f6970db214a2c39b5a640fa15e2de934532c1,3f103f5f0cb3d3f50e7d23ab4163b98a1a614926..f3189c108bd45ef06cd7a9be200f77b1fad3eefe
@@@ -1,5 -1,5 +1,5 @@@
  //-----------------------------------------------------------------------------
 -// 2011, Merlok
 +// 2011, 2017 Merlok
  // Copyright (C) 2010 iZsh <izsh at fail0verflow.com>, Hagen Fritsch
  //
  // This code is licensed to you under the terms of the GNU GPL, version 2 or,
@@@ -9,10 -9,33 +9,10 @@@
  // High frequency ISO14443A commands
  //-----------------------------------------------------------------------------
  
 -#include <stdio.h>
 -#include <stdlib.h>
 -#include <inttypes.h>
 -#include <string.h>
 -#include <unistd.h>
 -#include "util.h"
 -#include "util_posix.h"
 -#include "iso14443crc.h"
 -#include "data.h"
 -#include "proxmark3.h"
 -#include "ui.h"
 -#include "cmdparser.h"
  #include "cmdhf14a.h"
 -#include "common.h"
 -#include "cmdmain.h"
 -#include "mifare.h"
 -#include "cmdhfmfu.h"
 -#include "mifarehost.h"
  
  static int CmdHelp(const char *Cmd);
 -static void waitCmd(uint8_t iLen);
 -
 -// structure and database for uid -> tagtype lookups 
 -typedef struct { 
 -      uint8_t uid;
 -      char* desc;
 -} manufactureName; 
 +static int waitCmd(uint8_t iLen);
  
  const manufactureName manufactureMapping[] = {
        // ID,  "Vendor Country"
        { 0x00, "no tag-info available" } // must be the last entry
  };
  
 -
  // get a product description based on the UID
  //            uid[8]  tag uid
  // returns description of the best match      
@@@ -109,7 -133,80 +109,80 @@@ int CmdHF14AList(const char *Cmd
        return 0;
  }
  
- int CmdHF14AReader(const char *Cmd)
+ int CmdHF14AReader(const char *Cmd) {
+       uint32_t cm = ISO14A_CONNECT;
+       bool disconnectAfter = false;
+       
+       int cmdp = 0;
+       while(param_getchar(Cmd, cmdp) != 0x00) {
+               switch(param_getchar(Cmd, cmdp)) {
+               case 'h':
+               case 'H':
+                       PrintAndLog("Usage: hf 14a reader [d] [3]");
+                       PrintAndLog("       d    drop the signal field after command executed");
+                       PrintAndLog("       x    just drop the signal field");
+                       PrintAndLog("       3    ISO14443-3 select only (skip RATS)");
+                       return 0;
+               case '3':
+                       cm |= ISO14A_NO_RATS; 
+                       break;
+               case 'd':
+               case 'D':
+                       disconnectAfter = true;
+                       break;
+               case 'x':
+               case 'X':
+                       disconnectAfter = true;
+                       cm = cm - ISO14A_CONNECT;
+                       break;
+               default:
+                       PrintAndLog("Unknown command.");
+                       return 1;
+               }       
+               
+               cmdp++;
+       }
+       if (!disconnectAfter)
+               cm |= ISO14A_NO_DISCONNECT; 
+       
+       UsbCommand c = {CMD_READER_ISO_14443a, {cm, 0, 0}};
+       SendCommand(&c);
+       if (ISO14A_CONNECT & cm) {
+               UsbCommand resp;
+               WaitForResponse(CMD_ACK,&resp);
+               
+               iso14a_card_select_t card;
+               memcpy(&card, (iso14a_card_select_t *)resp.d.asBytes, sizeof(iso14a_card_select_t));
+               uint64_t select_status = resp.arg[0];           // 0: couldn't read, 1: OK, with ATS, 2: OK, no ATS, 3: proprietary Anticollision
+               
+               if(select_status == 0) {
+                       PrintAndLog("iso14443a card select failed");
+                       return 1;
+               }
+               if(select_status == 3) {
+                       PrintAndLog("Card doesn't support standard iso14443-3 anticollision");
+                       PrintAndLog("ATQA : %02x %02x", card.atqa[1], card.atqa[0]);
+                       return 1;
+               }
+               PrintAndLog(" UID : %s", sprint_hex(card.uid, card.uidlen));
+               PrintAndLog("ATQA : %02x %02x", card.atqa[1], card.atqa[0]);
+               PrintAndLog(" SAK : %02x [%d]", card.sak, resp.arg[0]);
+               if(card.ats_len >= 3) {                 // a valid ATS consists of at least the length byte (TL) and 2 CRC bytes
+                       PrintAndLog(" ATS : %s", sprint_hex(card.ats, card.ats_len));
+               }
+               PrintAndLog("Card is selected. You can now start sending commands");
+       } else {
+               PrintAndLog("Field dropped.");
+       }
+       return 0;
+ }
+ int CmdHF14AInfo(const char *Cmd)
  {
        UsbCommand c = {CMD_READER_ISO_14443a, {ISO14A_CONNECT | ISO14A_NO_DISCONNECT, 0, 0}};
        SendCommand(&c);
@@@ -530,170 -627,6 +603,170 @@@ int CmdHF14ASnoop(const char *Cmd) 
        return 0;
  }
  
 +int ExchangeAPDU14a(uint8_t *datain, int datainlen, bool activateField, bool leaveSignalON, uint8_t *dataout, int *dataoutlen) {
 +      uint8_t data[USB_CMD_DATA_SIZE];
 +      int datalen;
 +      uint8_t cmdc = 0;
 +      uint8_t first, second;
 +      
 +      if (activateField)
 +              cmdc |= ISO14A_CONNECT;
 +      if (leaveSignalON)
 +              cmdc |= ISO14A_NO_DISCONNECT;
 +
 +      // ISO 14443 APDU frame: PCB [CID] [NAD] APDU CRC PCB=0x02
 +      memcpy(data + 1, datain, datainlen);
 +      data[0] = 0x02; // bnr,nad,cid,chn=0; i-block(0x00)     
 +      datalen = datainlen + 1;
 +      
 +      ComputeCrc14443(CRC_14443_A, data, datalen, &first, &second);
 +      data[datalen++] = first;
 +      data[datalen++] = second;
 +
 +      // "Command APDU" length should be 5+255+1, but javacard's APDU buffer might be smaller - 133 bytes
 +      // https://stackoverflow.com/questions/32994936/safe-max-java-card-apdu-data-command-and-respond-size
 +      // here length USB_CMD_DATA_SIZE=512
 +      // timeout timeout14a * 1.06 / 100, true, size, &keyBlock[6 * c], e_sector); // timeout is (ms * 106)/10 or us*0.0106
 +      UsbCommand c = {CMD_READER_ISO_14443a, {ISO14A_RAW | ISO14A_SET_TIMEOUT | cmdc, (datalen & 0xFFFF), 1000 * 1000 * 1.06 / 100}}; 
 +      memcpy(c.d.asBytes, data, datalen);
 +      SendCommand(&c);
 +      
 +    uint8_t *recv;
 +    UsbCommand resp;
 +
 +      if (activateField) {
 +              if (!WaitForResponseTimeout(CMD_ACK, &resp, 1500)) 
 +                      return 1;
 +              if (resp.arg[0] != 1)
 +                      return 1;
 +      }
 +
 +    if (WaitForResponseTimeout(CMD_ACK, &resp, 1500)) {
 +        recv = resp.d.asBytes;
 +        uint8_t iLen = resp.arg[0];
 +              
 +              *dataoutlen = iLen - 1 - 2;
 +              if (*dataoutlen < 0)
 +                      *dataoutlen = 0;
 +              memcpy(dataout, recv + 1, *dataoutlen);
 +              
 +        if(!iLen)
 +            return 1;
 +
 +              // check apdu length
 +              if (iLen < 5) {
 +                      PrintAndLog("APDU ERROR: Small APDU response.");
 +                      return 2;
 +              }
 +              
 +              // check block
 +              if (data[0] != recv[0]) {
 +                      PrintAndLog("APDU ERROR: Block type mismatch: %02x-%02x", data[0], recv[0]);
 +                      return 2;
 +              }
 +              
 +              // CRC Check
 +              ComputeCrc14443(CRC_14443_A, recv, iLen, &first, &second);
 +              if (first || second) {
 +                      PrintAndLog("APDU ERROR: ISO 14443A CRC error.");
 +                      return 3;
 +              }
 +              
 +    } else {
 +        PrintAndLog("APDU ERROR: Reply timeout.");
 +              return 4;
 +    }
 +      
 +      return 0;
 +}
 +
 +int CmdHF14AAPDU(const char *cmd) {
 +      uint8_t data[USB_CMD_DATA_SIZE];
 +      int datalen = 0;
 +      bool activateField = false;
 +      bool leaveSignalON = false;
 +      bool decodeTLV = false;
 +      
 +      if (strlen(cmd) < 2) {
 +              PrintAndLog("Usage: hf 14a apdu [-s] [-k] [-t] <APDU (hex)>");
 +              PrintAndLog("       -s    activate field and select card");
 +              PrintAndLog("       -k    leave the signal field ON after receive response");
 +              PrintAndLog("       -t    executes TLV decoder if it possible. TODO!!!!");
 +              return 0;
 +      }
 +
 +      int cmdp = 0;
 +      while(param_getchar(cmd, cmdp) != 0x00) {
 +              char c = param_getchar(cmd, cmdp);
 +              if ((c == '-') && (param_getlength(cmd, cmdp) == 2))
 +                      switch (param_getchar_indx(cmd, 1, cmdp)) {
 +                              case 's':
 +                              case 'S':
 +                                      activateField = true;
 +                                      break;
 +                              case 'k':
 +                              case 'K':
 +                                      leaveSignalON = true;
 +                                      break;
 +                              case 't':
 +                              case 'T':
 +                                      decodeTLV = true;
 +                                      break;
 +                              default:
 +                                      PrintAndLog("Unknown parameter '%c'", param_getchar_indx(cmd, 1, cmdp));
 +                                      return 1;
 +                      }
 +                      
 +              if (isxdigit(c)) {
 +                      // len = data + PCB(1b) + CRC(2b)
 +                      switch(param_gethex_to_eol(cmd, cmdp, data, sizeof(data) - 1 - 2, &datalen)) {
 +                      case 1:
 +                              PrintAndLog("Invalid HEX value.");
 +                              return 1;
 +                      case 2:
 +                              PrintAndLog("APDU too large.");
 +                              return 1;
 +                      case 3:
 +                              PrintAndLog("Hex must have even number of digits.");
 +                              return 1;
 +                      }
 +                      
 +                      // we get all the hex to end of line with spaces
 +                      break;
 +              }
 +              
 +              cmdp++;
 +      }
 +
 +      PrintAndLog("--%s %s %s >>>> %s", activateField ? "sel": "", leaveSignalON ? "keep": "", decodeTLV ? "TLV": "", sprint_hex(data, datalen));
 +      
 +      switch(ExchangeAPDU14a(data, datalen, activateField, leaveSignalON, data, &datalen)) {
 +              case 0:
 +                      break;
 +              case 1:
 +                      PrintAndLog("APDU ERROR: Send APDU error.");
 +                      return 1;
 +              case 2:
 +                      return 2;
 +              case 3:
 +                      return 3;
 +              case 4:
 +                      return 4;
 +              default:
 +                      return 5;
 +      }
 +
 +      PrintAndLog("<<<< %s", sprint_hex(data, datalen));
 +      
 +      PrintAndLog("APDU response: %02x %02x - %s", data[datalen - 2], data[datalen - 1], GetAPDUCodeDescription(data[datalen - 2], data[datalen - 1])); 
 +
 +      // here TLV decoder...
 +      if (decodeTLV && datalen > 4) {
 +              TLVPrintFromBuffer(data, datalen - 2);
 +      }
 +      
 +      return 0;
 +}
  
  int CmdHF14ACmdRaw(const char *cmd) {
        UsbCommand c = {CMD_READER_ISO_14443a, {0, 0, 0}};
        SendCommand(&c);
  
        if (reply) {
 -              if(active_select)
 -                      waitCmd(1);
 -              if(datalen>0)
 +              int res = 0;
 +              if (active_select)
 +                      res = waitCmd(1);
 +              if (!res && datalen > 0)
                        waitCmd(0);
        } // if reply
        return 0;
  }
  
  
 -static void waitCmd(uint8_t iSelect)
 -{
 +static int waitCmd(uint8_t iSelect) {
      uint8_t *recv;
      UsbCommand resp;
      char *hexout;
  
      if (WaitForResponseTimeout(CMD_ACK,&resp,1500)) {
          recv = resp.d.asBytes;
-         uint8_t iLen = iSelect ? resp.arg[1] : resp.arg[0];
-         PrintAndLog("received %i octets", iLen);
+         uint8_t iLen = resp.arg[0];
+               if (iSelect){
+                       iLen = resp.arg[1];
+                       if (iLen){
+                               PrintAndLog("Card selected. UID[%i]:", iLen);
+                       } else {
+                               PrintAndLog("Can't select card.");
+                       }
+               } else {
+                       PrintAndLog("received %i bytes:", iLen);
+               }
          if(!iLen)
 -            return;
 +            return 1;
          hexout = (char *)malloc(iLen * 3 + 1);
          if (hexout != NULL) {
              for (int i = 0; i < iLen; i++) { // data in hex
              free(hexout);
          } else {
              PrintAndLog("malloc failed your client has low memory?");
 +                      return 2;
          }
      } else {
          PrintAndLog("timeout while waiting for reply.");
 +              return 3;
      }
 +      return 0;
  }
  
  static command_t CommandTable[] = 
  {
    {"help",   CmdHelp,              1, "This help"},
    {"list",   CmdHF14AList,         0, "[Deprecated] List ISO 14443a history"},
-   {"reader", CmdHF14AReader,       0, "Act like an ISO14443 Type A reader"},
+   {"reader", CmdHF14AReader,       0, "Start acting like an ISO14443 Type A reader"},
+   {"info",   CmdHF14AInfo,         0, "Reads card and shows information about it"},
    {"cuids",  CmdHF14ACUIDs,        0, "<n> Collect n>0 ISO14443 Type A UIDs in one go"},
    {"sim",    CmdHF14ASim,          0, "<UID> -- Simulate ISO 14443a tag"},
    {"snoop",  CmdHF14ASnoop,        0, "Eavesdrop ISO 14443 Type A"},
 +  {"apdu",   CmdHF14AAPDU,         0, "Send ISO 1443-4 APDU to tag"},
    {"raw",    CmdHF14ACmdRaw,       0, "Send raw hex data to tag"},
    {NULL, NULL, 0, NULL}
  };
diff --combined client/cmdhf14a.h
index d11d17ebf23feb314e0865fab290d761a5f2e56d,2556678d0a1e6b2ddda387d6c6f7da2bfb7f0880..16e03574a4bc5d9b5c5d50277d4516a87ff5d229
  #ifndef CMDHF14A_H__
  #define CMDHF14A_H__
  
 +#include <stdio.h>
  #include <stdint.h>
 +#include <stdlib.h>
 +#include <inttypes.h>
 +#include <string.h>
 +#include <unistd.h>
 +#include "util.h"
 +#include "util_posix.h"
 +#include "iso14443crc.h"
 +#include "data.h"
 +#include "proxmark3.h"
 +#include "ui.h"
 +#include "cmdparser.h"
 +#include "common.h"
 +#include "cmdmain.h"
 +#include "mifare.h"
 +#include "cmdhfmfu.h"
 +#include "mifarehost.h"
 +#include "emv/apduinfo.h"
 +#include "emv/emvcore.h"
 +
 +// structure and database for uid -> tagtype lookups 
 +typedef struct { 
 +      uint8_t uid;
 +      char* desc;
 +} manufactureName; 
  
  int CmdHF14A(const char *Cmd);
  int CmdHF14AList(const char *Cmd);
  int CmdHF14AMifare(const char *Cmd);
  int CmdHF14AReader(const char *Cmd);
+ extern int CmdHF14AInfo(const char *Cmd);
  int CmdHF14ASim(const char *Cmd);
  int CmdHF14ASnoop(const char *Cmd);
  char* getTagInfo(uint8_t uid);
  
 +extern int ExchangeAPDU14a(uint8_t *datain, int datainlen, bool activateField, bool leaveSignalON, uint8_t *dataout, int *dataoutlen);
 +
  #endif
Impressum, Datenschutz