nfc-tools / libnfc

Platform independent Near Field Communication (NFC) library
http://nfc-tools.org
GNU Lesser General Public License v3.0
1.71k stars 443 forks source link

nfc_initiator_transceive_bytes_timed #292

Open Rokia88 opened 9 years ago

Rokia88 commented 9 years ago

I report here a bug that I discover while using the function nfc_initiator_transceive_bytes_timed. The problem is that the behaviour of my program when I use this function in mode debug 'step by step' is OK, while in mode 'normal' (i.e : execution normal without debug) is KO. In fact, for example, in mode debug I can use some values for the maximal number of cycles without problem, but in mode execution, the timer of the reader becomes saturated even if the same value of the maximal number of cycles is used.

Thanks in advance for your answer.

neomilium commented 9 years ago

Please provide some code and context of usage... Are you sure to use the right function ?

Rokia88 commented 9 years ago

Yes, I am sure that I use nfc_initiator_transceive_bytes_timed() because I run my program with -t option. The context of use is that I am doing relay attacks against the Mifare Desfire card, and I want to measure the response time of different commands. So without adding any delay, I send commands to the Desfire card using this function in order to obtain the response time of each command. Since this function does not allow easy framing functionnality, I add the header (PCB) by my self to the commands before sending them to the card. There are no applicative errors because when I use a very big number of cycles (21 * 65553 for example) I obtain the right responses from the card.

here the code of the transmit_bytes function where I add the PCB header and I treat the time extension request:

static  bool
transmit_bytes(const uint8_t *pbtTx, const size_t szTx)
{
  //uint32_t cycles = 65535 * 5;
  uint32_t cycles = 0;
  uint8_t T[MAX_FRAME_LEN];
  T[0] = 0x02;
  memcpy(T+1,pbtTx,szTx);
  size_t szTxt = szTx + 1;

  // Show transmitted command
  if (!quiet_output) {
    printf("Sent bytes:     ");
    print_hex(T, szTx+1);
  }
  int res;
  // Transmit the command bytes
  if (timed) {
label:
      printf("************************\n");
    if ((res = nfc_initiator_transceive_bytes_timed(pnd, T, szTxt, abtRx, sizeof(abtRx), &cycles)) < 0)
      return false;
    if ((!quiet_output) && (res > 0)) {
      printf("Response after %u cycles\n", cycles);
    }
  }
  else {
    if ((res = nfc_initiator_transceive_bytes(pnd, pbtTx, szTx, abtRx, sizeof(abtRx),timeout)) < 0)
      return false;
  }
  szRx = res;
  status_word = abtRx[res-2];
  status_word = (status_word<<8) + abtRx[res-1];
  // Show received answer
  if (!quiet_output) {
    printf("Received bytes: ");
    print_hex(abtRx, szRx);
  }
  if(abtRx[0] == 0xf2)
  {
      T[0] = abtRx[0];
      T[1] = abtRx[1];
      szTxt = 2;
      goto label;
  }
  // Succesful transfer
  return true;
}

In the main function, I disable the NP_easy_Framing option:
if (nfc_device_set_property_bool(pnd, NP_EASY_FRAMING, false) < 0) {
          nfc_perror(pnd, "nfc_device_set_property_bool");
          nfc_close(pnd);
          nfc_exit(context);
          exit(EXIT_FAILURE);
  }
The Desfire commands are managed without any exceptional modification, here an example of the select application command:

int selectApplication(unsigned int AID)
{

    uint8_t abtTx[MAX_FRAME_LEN]; /*input buffer          */
    size_t abtTx_size;

    if(AID > 0xffffff || AID < 0x000000)
    {
          if(!quiet_output)
           {
            printf("AID is not valid\n");
           }
         return EXIT_FAILURE;
    }
    /*prepare the data*/
    abtTx_size = 9;
    memcpy(abtTx,selectApplication_apdu,abtTx_size);
    abtTx[7] = (AID >> 16) & 0xff; /*data 0*/
    abtTx[6] = (AID >> 8 ) & 0xff; /*data 1*/
    abtTx[5] = AID & 0xff;         /*data 2*/

    if(!transmit_bytes(abtTx,abtTx_size) || (status_word != 0x9100))
    {
        nfc_perror(pnd, "SELECT APPLICATION");
        return EXIT_FAILURE;
    }

    return EXIT_SUCCESS;
}

Thanks in advance for your answer

Rokia88 commented 9 years ago

I forgot to say that I don't handle completely the ISO 14443-4 layer since for example I don't process the cases where the card send R(ACK) or R(NACK) (and that because I didn't receive these frames, during my tests.. :) )

neomilium commented 9 years ago

Any patch to provide ?

Rokia88 commented 9 years ago

No, I don't have. I was told that this function is intended to be used for short commands (such as anti-collision protocol commands). For long commands, it is preferable to use Micropross or proxmark for example to measure the response time of the RFID tag.

Cordially

Rokia

2015-08-19 11:57 GMT+02:00 Romuald Conty notifications@github.com:

Any patch to provide ?

— Reply to this email directly or view it on GitHub https://github.com/nfc-tools/libnfc/issues/292#issuecomment-132522248.

Bien cordialement Rokia LAMRANI ALAOUI