Merge branch 'master' into 14a_rework3
authorOleg Moiseenko <olegmsn@gmail.com>
Thu, 2 Nov 2017 12:14:55 +0000 (14:14 +0200)
committerGitHub <noreply@github.com>
Thu, 2 Nov 2017 12:14:55 +0000 (14:14 +0200)
1  2 
armsrc/iso14443a.c
client/cmdhf14a.c

diff --combined armsrc/iso14443a.c
index c39b8a20b61a07facd721db67c41711d72153f68,987d29ad56cf9da7e4f0bf754b4841ca82ad4ac4..5a27e06b6193b73737b17a9ae40f2ec1e224c9ec
@@@ -1821,7 -1821,7 +1821,7 @@@ int iso14443a_select_card(byte_t *uid_p
        }
  
        // PICC compilant with iso14443a-4 ---> (SAK & 0x20 != 0)
-       if( (sak & 0x20) == 0) return 2; 
+       if( (sak & 0x20) == 0) return 2; 
  
        if (!no_rats) {
                // Request for answer to select
@@@ -1914,7 -1914,6 +1914,7 @@@ void ReaderIso14443a(UsbCommand *c
        uint32_t arg0 = 0;
        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
 +                      if (arg0 != 1 && arg0 != 2) {
 +                              // 1 - all is OK with ATS, 2 - without ATS
 +                              cantSELECT = true;
 +                      }
 +                      
 +                      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 86cfea2fbc1a1bf3a549f41f851715f5f4e7034c,928864a1b39936000231a552a983986d615c34d8..1ae63adae791f0948502e63ba3ab993d6f6fca78
@@@ -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      
@@@ -220,8 -244,10 +220,10 @@@ int CmdHF14AInfo(const char *Cmd
        PrintAndLog("ATQA : %02x %02x", card.atqa[1], card.atqa[0]);
        PrintAndLog(" SAK : %02x [%d]", card.sak, resp.arg[0]);
  
+       bool isMifareClassic = true;
        switch (card.sak) {
                case 0x00: 
+                       isMifareClassic = false;
  
                        //***************************************test****************
                        // disconnect
        // try to see if card responses to "chinese magic backdoor" commands.
        mfCIdentify();
        
+       if (isMifareClassic) {          
+               switch(DetectClassicPrng()) {
+               case 0:
+                       PrintAndLog("Prng detection: HARDEND (hardnested)");            
+                       break;
+               case 1:
+                       PrintAndLog("Prng detection: WEAK");
+                       break;
+               default:
+                       PrintAndLog("Prng detection error.");           
+               }
+       }
+       
        return select_status;
  }
  
@@@ -603,170 -642,6 +618,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])); 
 +
 +      // 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;
                        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[] = 
    {"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}
  };
Impressum, Datenschutz