Topic: Controlling nonce with touchatag

I have read the suggestion in the proxmark forums how to manage to get the same nonce with proxmark. Iam currently working with touchatag.  The process im doing currently is the following.

1)dropping the field
2)100ms delay
3)anticoll
4)get nonce1
5)dropping field
6)100ms delay
7)anticoll
8)get nonce2

However nonce1 and nonce2 never are the same... i thought of puting it in a while loop which i manage to get 2 same nonces after about 10-15secs of running the program but thats not controlling the nonces.

Could any1 provide any tips? Is there a way to control more precisly the timming of the device?

Last edited by pgrahamm (2009-09-17 22:54:07)

Re: Controlling nonce with touchatag

It would help if you drop the field and call nfc_initiator_select_tag() immediately followed by sending the auth (0x60 ...) frame. The nfc_initiator_select_tag() will enabled the field just before performing the anti-collision. Don't forget to set the configuration option that the chip should not handle the CRC before you send the auth frame.

It should work using ~300ms delay (the proxmark seems to get better results). Tests show that 3 of 5 nonces are the same. For getting better results, a measurement of the nonce-distance (for guessing the next nonce) seems to work more stable.

The field could stay enabled for this. Use the UID as initiator data during the second call to nfc_initiator_select_tag(), it will use a WUPA (0x52) frame then in stead of a REQA (0x26 frame which is ignored by an deactivated tag (check the anticol example for more info about this process).

Re: Controlling nonce with touchatag

roel wrote:

It should work using ~300ms delay (the proxmark seems to get better results). Tests show that 3 of 5 nonces are the same. For getting better results, a measurement of the nonce-distance (for guessing the next nonce) seems to work more stable.

Yes i was troubling my mind for a platform independed code and how to apply the delay. so far my delay is

void delay(clock_t lMillisec)
{
clock_t finish;
finish = clock() + (lMillisec / MILLISEC * CLOCKS_PER_SEC);
while (finish > clock());
} for windows and usleep for posix. however i havent figured out a way to be portable.

As for the nonce distances, by getting a couple of nonces and calculating the distances is like calibrating for the device. I will check to see what results i get and i will post if i have any progress.

Do you happen to know what is the added delay of the usb bus and if that also affects the nonce generation?

Thank you for your support

Re: Controlling nonce with touchatag

You can add some compiler defines

Windows: #define msleep(t) Sleep(t)
Unix: #define msleep(t) usleep((t) * 1000)

The USB timing is indeed not really reliable, but the ACR122U seems to work fine for calibration.
The NFC-dongles are slightly faster, so they produce a little bit more relying timing information.

Re: Controlling nonce with touchatag

Hi,

This is a rough implementation of REQA+WUPA techique to fix a tag nonce. Though it doesn't yield as good results for me as the DROP FIELDS+CONSTANT DELAY (code is here http://www.libnfc.org/community/post/475/#p475)

/*  
 File:
    zv_fixtagnonce_reqawupa.c

 Name:
    Mifare Classic TagNonce-fixation technique REQA+WUPA test

 Description:
    Implementing TagNonce-fixation demo by using 7 bits 0x26 REQA then 0x52 WUPA commands.
    For me, does not yield as good results as DROP FIELDS+CONSTANT DELAY.

 Contact:
    http://andreicostin.com/
    mailto:zveriu@gmail.com
 
 Requirements:
    crapto1 library            (http://code.google.com/p/crapto1)
    libnfc                     (http://www.libnfc.org)
 
 This program is free software: you can redistribute it and/or modify
 it under the terms of the GNU General Public License as published by
 the Free Software Foundation, either version 2 of the License, or
 (at your option) any later version.
 
 This program is distributed in the hope that it will be useful,
 but WITHOUT ANY WARRANTY; without even the implied warranty of
 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 GNU General Public License for more details.
 
 You should have received a copy of the GNU General Public License
 along with this program.  If not, see <http://www.gnu.org/licenses/>. 
*/

/*
// zveriu 
BIBLIOGRPAHY (no specific order)
1. [WPMCC09] - "Wirelessly Pickpocketing a Mifare Classic Card"
2. [ESO08] - "2008-esorics.pdf"
3. [ESOSL08] - "2008-esorics-slides-updated.pdf"
4. [KON08] - "2008-koning-thesis.pdf"
5. [VER08] - "2008-verdult-thesis.pdf"
6. [PATMC] - "A Practical Attack on the MIFARE Classic.pdf"
7. [NCOURFIDSEC09] - "mifare_courtois_rfidsec09.pdf"
8. [MFCLTRB09] - "MifareClassicTroubles.ppt"
9. [TEEP08] - "p2008-teepe-classic_mistakes.pdf"
10. [RFIDSANJ] - "RFID Attacks_WCA_San_Jose.pdf"
11. [ROSS] - "rossum-mifare.pdf"
12. [PLOTZ08] - "SAR-PR-2008-21_.pdf"
13. [ROSSSASG] - "SASG35_Peter_v_Rossum_Mifare.pdf"
*/

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "libnfc.h"
#include "crapto1.h"

#define NOMINMAX
#include "windows.h"

LARGE_INTEGER nFreq;
LARGE_INTEGER nBeginTime;
LARGE_INTEGER nEndTime;
int execution_time = 0;
double g_exec_time = 0;
long long ll_exec_time = 0;

// ISO14443A Anti-Collision Commands
byte_t abtReqa      [1] = { 0x26 };
byte_t abtSelectAll [2] = { 0x93,0x20 };
byte_t abtSelectTag [9] = { 0x93,0x70,0x00,0x00,0x00,0x00,0x00,0x00,0x00 };
byte_t abtRats      [4] = { 0xe0,0x50,0xbc,0xa5 };
byte_t abtHalt      [4] = { 0x50,0x00,0x57,0xcd };
byte_t abtWupa      [1] = { 0x52 };

static byte_t abtRx[MAX_FRAME_LEN];
static uint32_t uiRxBits;
static uint32_t uiRxLen;
static byte_t abtUid[10];
static uint32_t uiUidLen = 4;
static byte_t firstTime = 1;
static uint32_t ntPrev;
static int estimatedSleep = 0;
//static dev_info* pdi;

#define NONCE_VARIANCE 65535
#define NONCE_PERIOD ((9.44f * NONCE_VARIANCE)/1000)

bool transmit_bits(dev_info* pdi, const byte_t* pbtTx, const uint32_t uiTxBits)
{
  // Show transmitted command
  printf("R: "); print_hex_bits(pbtTx,uiTxBits);

  // Transmit the bit frame command, we don't use the arbitrary parity feature
  if (!nfc_initiator_transceive_bits(pdi,pbtTx,uiTxBits,NULL,abtRx,&uiRxBits,NULL)) return false;

  // Show received answer
  printf("T: "); print_hex_bits(abtRx,uiRxBits);

  // Succesful transfer
  return true;
}


bool transmit_bytes(dev_info* pdi, const byte_t* pbtTx, const uint32_t uiTxLen)
{
  // Show transmitted command
  printf("R: "); print_hex(pbtTx,uiTxLen);

  // Transmit the command bytes
  if (!nfc_initiator_transceive_bytes(pdi,pbtTx,uiTxLen,abtRx,&uiRxLen)) return false;

  // Show received answer
  printf("T: "); print_hex(abtRx,uiRxLen);

  // Succesful transfer
  return true;
}

bool mifare_test(dev_info* pdi, byte_t* pbtUid, uint64_t ui64Key, uint32_t uiBlock)
{
  uint32_t pos, nt;
  struct Crypto1State* pcs;
  byte_t abtAuth[4]        = { 0x60,0x00,0x00,0x00 };
  byte_t abtArEnc[8]       = { 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 };
  byte_t abtArEncPar[8]    = { 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 };
  byte_t abtRx[MAX_FRAME_LEN];
  byte_t abtRxPar[MAX_FRAME_LEN];
  uint32_t uiRxLen;
  uint32_t nonceDist;
  double tagPeriodTimeDist;
  double measuredTimeDist;
  
  // Configure the authentication frame using the supplied block 
  abtAuth[1] = uiBlock;
  append_iso14443a_crc(abtAuth,2);

  // Now we take over, first we need full control over the CRC
  nfc_configure(pdi,DCO_HANDLE_CRC,false);
  
  //estimatedSleep = 15;
  if (estimatedSleep != 0)
  {
    Sleep(estimatedSleep);
  }

  // Request plain tag-nonce
  printf(" Nt: ");
  if (!nfc_initiator_transceive_bytes(pdi,abtAuth,4,abtRx,&uiRxLen)) return false;
  print_hex(abtRx,4);
  
  // Save the tag nonce (nt)
  nt = swap_endian32(abtRx);

  if (!firstTime)
  {
    ntPrev = swap_endian32(&ntPrev);
    printf(" Np: ");
    print_hex((const byte_t *)&ntPrev,4);
    ntPrev = swap_endian32(&ntPrev);

    QueryPerformanceCounter(&nEndTime);
    nonceDist = nonce_distance(ntPrev, nt);
    measuredTimeDist = (double)(nEndTime.QuadPart - nBeginTime.QuadPart)*1000/(double)(nFreq.QuadPart);
    tagPeriodTimeDist = (double)nonceDist/NONCE_VARIANCE*NONCE_PERIOD;
    if (measuredTimeDist < NONCE_PERIOD)
    {
      estimatedSleep = (int)(NONCE_PERIOD - measuredTimeDist);
    }
    else
    {
      estimatedSleep = (int)(measuredTimeDist - NONCE_PERIOD);
    }
    printf("\tNonce distance %d (from %d, to %d)\n", nonceDist, ntPrev, nt);
    printf("\tTag-period time distance: %g, Estimated sleep %d\n", tagPeriodTimeDist, estimatedSleep);
    printf("\tMeasured time distance: %g\n", measuredTimeDist);
    QueryPerformanceCounter(&nBeginTime);
  }
  else
  {
    firstTime = 0;
    QueryPerformanceCounter(&nBeginTime);
  }

  ntPrev = nt;

  // Init cipher with key
  pcs = crypto1_create(ui64Key);

  // Load (plain) uid^nt into the cipher
  for (pos=0; pos<4; pos++)
  {
    // Update the cipher with the tag-initialization 
    crypto1_byte(pcs,pbtUid[pos]^abtRx[pos],0);
  }

  // Generate (encrypted) nr+parity by loading it into the cipher
  for (pos=0; pos<4; pos++)
  {
    // Load in, and encrypt, the reader nonce (plain nr=0x00000000)
    abtArEnc[pos] = crypto1_byte(pcs,0x00,0) ^ 0x00;
    // Encrypt the parity bits for the 4 plaintext bytes of nr
    abtArEncPar[pos] = filter(pcs->odd) ^ oddparity(0x00);
  }
  
  // Skip 32 bits in pseudo random generator
  nt = prng_successor(nt,32);
  
  // Generate reader-answer from tag-nonce
  for (pos=4; pos<8; pos++)
  {
    // Get the next random byte for verify the reader to the tag 
    nt = prng_successor(nt,8);

    // Encrypt the reader-answer (nt' = suc2(nt))
    abtArEnc[pos] = crypto1_byte(pcs,0x00,0) ^ (nt&0xff);
    // Encrypt the parity bits for the 4 plaintext bytes of nt'
    abtArEncPar[pos] = filter(pcs->odd) ^ oddparity(nt&0xff);
  }

  // Finally we want to send arbitrary parity bits
  nfc_configure(pdi,DCO_HANDLE_PARITY,false);

  // Transmit reader-answer
  printf(" Ar: ");
  print_hex_par(abtArEnc,64,abtArEncPar);
  if (!nfc_initiator_transceive_bits(pdi,abtArEnc,64,abtArEncPar,abtRx,&uiRxLen,abtRxPar)) return false;
  printf(" At: "); 
  print_hex_par(abtRx,uiRxLen,abtRxPar);
  
  crypto1_destroy(pcs);

  return true;
}


int main(int argc, const char* argv[])
{
  dev_info* pdi;
  tag_info ti;
  uint32_t uiBlock;
  uint64_t ui64Key;

  // zveriu
  uint32_t uiUID = 0;
  byte_t arrUID[4];

  QueryPerformanceFrequency(&nFreq);

  if (argc < 3)
  {
    printf("syntax: %s <key> <block>\n",argv[0]);
    return 1;
  }
  
  sscanf(argv[1],"%012llx",&ui64Key);
  sscanf(argv[2],"%02x",&uiBlock);
  
  // Try to open the NFC reader
  pdi = nfc_connect(NULL);
  
  if (pdi == INVALID_DEVICE_INFO)
  {
    printf("Error connecting NFC reader\n");
    return 1;
  }
  nfc_initiator_init(pdi);

  // Drop the field for a while, so the card can reset
  nfc_configure(pdi,DCO_ACTIVATE_FIELD,false);

  // Let the reader only try once to find a tag
  nfc_configure(pdi,DCO_INFINITE_SELECT,false);

  // Configure the CRC and Parity settings
  //nfc_configure(pdi,DCO_HANDLE_CRC,true);
  //nfc_configure(pdi,DCO_HANDLE_PARITY,true);

  // Enable field so more power consuming cards can power themselves up
  //nfc_configure(pdi,DCO_ACTIVATE_FIELD,true);

  printf("\nConnected to NFC reader: %s\n\n",pdi->acName);

  while(1)
  {
      if (!uiUID)
      {
          /*
          // Poll for a ISO14443A (MIFARE) tag
          if (!nfc_initiator_select_tag(pdi,IM_ISO14443A_106,NULL,0,&ti))
          {
            printf("Error connecting to MIFARE Classic tag\n");
            nfc_disconnect(pdi);
            return 1;
          }
          */

          // Configure the CRC and Parity settings
          nfc_configure(pdi,DCO_HANDLE_CRC,false);
          nfc_configure(pdi,DCO_HANDLE_PARITY,true);

          //Sleep(309);

          // Enable field so more power consuming cards can power themselves up
          nfc_configure(pdi,DCO_ACTIVATE_FIELD,true);

          // Send the 7 bits request command specified in ISO 14443A (0x26)
          if (!transmit_bits(pdi, abtReqa,7))
          {
            printf("Error: REQA No tag available\n");
            continue;
            //nfc_disconnect(pdi);
            //return 1;
          }

          // Anti-collision
          transmit_bytes(pdi, abtSelectAll,2);
          
          // Save the UID
          memcpy(abtUid,abtRx,4);
          memcpy(abtSelectTag+2,abtRx,5);
          append_iso14443a_crc(abtSelectTag,7);
          transmit_bytes(pdi, abtSelectTag,9);

          // zveriu
          arrUID[0] = abtUid[0];
          arrUID[1] = abtUid[1];
          arrUID[2] = abtUid[2];
          arrUID[3] = abtUid[3];
          uiUID = swap_endian32(arrUID);
      }
      else
      {
          // Poll for a ISO14443A (MIFARE) tag
          /*
          if (!nfc_initiator_select_tag(pdi,IM_ISO14443A_106,arrUID,4,&ti))
          {
            printf("Error connecting to MIFARE Classic tag\n");
            nfc_disconnect(pdi);
            return 1;
          }*/

          // Configure the CRC and Parity settings
          nfc_configure(pdi,DCO_HANDLE_CRC,false);
          nfc_configure(pdi,DCO_HANDLE_PARITY,true);

          // Send the 7 bits request command specified in ISO 14443A (0x52)
          if (!transmit_bits(pdi, abtWupa,7))
          {
            printf("Error: WUPA No tag available\n");
            continue;
            //nfc_disconnect(pdi);
            //return 1;
          }

          transmit_bytes(pdi, abtSelectTag,9);
      }

      // Print the uid to the screen 
      //printf("   uid: %08x\n",swap_endian32(ti.tia.abtUid));
      printf("   uid: %08x\n", uiUID);
      printf("   key: %012llx\n",ui64Key);
      printf(" block: %02x\n",uiBlock);
      printf("\n");
      
      // Run the MIFARE Classic test
      if (mifare_test(pdi,arrUID,ui64Key,uiBlock))
      {
        printf("\nAuthentication Succesful\n\n");
      } else {
        printf("\nAuthentication failed\n");
      }

      // Done, halt the tag now
      transmit_bytes(pdi, abtHalt,4);

      // Reset the "advanced" configuration to normal
      nfc_configure(pdi,DCO_HANDLE_CRC,true);
      nfc_configure(pdi,DCO_HANDLE_PARITY,true);
      //Sleep(309);
  }

  // Clean up and release device
  nfc_disconnect(pdi);
  return 0;
}

Hope the code is useful for someone.

Re: Controlling nonce with touchatag

Thank you very much for your contribution. If feel like it, you can make a package from your software (googlecode?) so we can link on the main website to your code as demonstration and 3rd party software that uses libnfc.

Re: Controlling nonce with touchatag

Hi Roel,

First, thanks for pointing out good information and replying to the posted topics - really appreciate your dedication to community!

Regarding the idea of a googlecode project - I have created the http://code.google.com/p/tk-libnfc-crapto1/ - "Toolkit containing samples and various tools based on and around libnfc and crapto1".

Initial plans are to contain:
- sample for nonce tag fixation with REQA+WUPA technique
- sample for nonce tag fixation with DROP_FIELD+CONST_DELAY technique
- sample for decrypting the 4 bits encrypted NACK with the 4 bits of ks3 (as described here http://eprint.iacr.org/2009/137)

I also talked to guys at Nethemba, and hopefully they will jump into this toolkit suite with their (improved) MFOC (maybe a better name would be MiFare Card-Only Nested Attack/Cracker, but they know better) into this toolkit package. The final goal would be to have a open source GPL cracker which optimally discover at least one key of a complete unknown and NON-default mifare card. In this way the toolkit would be quite useful and maybe even rainbow 384GB-based-table implementations will appear on top :)

Will clean, test and checkin the first two mentioned samples in the coming days so the project will not look stale :)

Working on the third now, not too much progress with getting proper 4 bits of ks3 which give the 0x5 when XORed with the encrypted 4 bits response when the parity is guessed

Re: Controlling nonce with touchatag

No problem at all, it seems useful to explain the vulnerabilities with care, to make clear what the impact of those are. It is important that people can independently test the security of their systems, a open source package sounds like a good way to provide this.

zveriu wrote:

Working on the third now, not too much progress with getting proper 4 bits of ks3 which give the 0x5 when XORed with the encrypted 4 bits response when the parity is guessed

Do you have any direct questions about the problems I can help you with?

Re: Controlling nonce with touchatag

I'd be interested to know what sort of figures you get when trying to do tag nonce control with a Touchatag?

I have done a few tries and I have to admit I am not getting very good figures - 20 to 30% best case. I wonder if the pcsc-lite version might have an impact? I am using 1.5.5. AFAIK, when trying to control the tag nonce with an reader device which goes through PCSC, we have sources of 'timing uncertainties' such as communication with the pcscd daemon, I am not quite sure how those can impact the overall performance ? Of course, this is why there are devices like the Proxmark smile