Re: Authentication with Mifare Classic using libnfc

schwa226 wrote:
  // Encrypt the abtAuth2
  abtArEnc2[pos] = abtAuth2[pos] ^ KeyStream[pos];
  // Encrypt the parity bits for the 4 plaintext bytes of abtAuth2
  abtArEncPar2[pos] = filter(pcs->odd) ^ oddparity(abtAuth2[pos]);

Hmm...

You can not first generate the keystream and later on generate the parity bits using the current crypto-state (LFSR) by calling filter(). You have to do this at the same time. This is because after every byte the parity bit is encrypted by the crypto-state at that moment (just before starting to encrypt the next byte).

This makes more sense to me:

  abtArEnc2[pos] = abtAuth2[pos] ^ crypto1_byte(pcs,0x00,0);
  abtArEncPar2[pos] = filter(pcs->odd) ^ oddparity(abtAuth2[pos]);

Re: Authentication with Mifare Classic using libnfc

I think I tried this also before, but when I take also your sample trace:

+ 923318:  4 :     60  00  f5  7b   
+    112:  4 : TAG 82  a4  16  6c   
+   6985:  8 :     a1  e4! 58  ce! 6e  ea! 41  e0!       !crc
+     64:  4 : TAG 5c! ad  f4  39!   
+ 811513:  4 :     8e  0e! 5d! b9        !crc

the result is:

Found tag with UID: 9c599b32

Auth: 60  00  f5  7b
Nt: 82  a4  16  6c
Ar: a1  e4! 58  ce! 6e  ea! 41  e0!
At: 5c! ad  f4  39!

60  00  f5  7b
Auth2: a6! ef  7a  62!

I do the auth:
encrypt nr = 0xefea1cda, key 0xffffffffffff

  nr[0] = 0xef;
  nr[1] = 0xea;
  nr[2] = 0x1c;
  nr[3] = 0xda;

  // Generate (encrypted) nr+parity by loading it into the cipher
  for (pos=0; pos<4; pos++)
  {
    // Load in, and encrypt, the reader nonce nr
    abtArEnc[pos] = crypto1_byte(pcs,nr[pos],0) ^ nr[pos];
    // Encrypt the parity bits for the 4 plaintext bytes of nr
    abtArEncPar[pos] = filter(pcs->odd) ^ oddparity(nr[pos]);
  }

load also nt to the chiper:

  // 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);
  }

The result is the same like the 8 bytes in your trace: a1  e4! 58  ce! 6e  ea! 41  e0!

Right after this without modifying pcs:

  //do encrypted second auth
  abtAuth2[0] = 0x60;

  // Configure the authentication frame using the supplied block 
  abtAuth2[1] = uiBlock;
  append_iso14443a_crc(abtAuth2,2);
  print_hex(abtAuth2,4);

  // Generate (encrypted) abtAuth2 by
  for (pos=0; pos<4; pos++)
  {
    abtArEnc2[pos] = abtAuth2[pos] ^ crypto1_byte(pcs,0x00,0);
    abtArEncPar2[pos] = filter(pcs->odd) ^ oddparity(abtAuth2[pos]);
  }

But as you can see on top the result isn't ok! I think I m running crazy!

I use v2.4!

28 (edited by pgrahamm 2009-09-26 08:39:21)

Re: Authentication with Mifare Classic using libnfc

As i mentioned earlier the two internal state(tag,reader) must be the same. In your case they are not because the tag shifted the LFSR in order to create the aT and send it to you where At=suc96(nT). So far what you have done is suc64(nT) on the reader side.

29 (edited by schwa226 2009-09-28 09:33:07)

Re: Authentication with Mifare Classic using libnfc

Me again!

EDIT may got it working!

Found tag with UID: 9c599b32
Auth: 60  00  f5  7b
Nt: 82  a4  16  6c
[Nr + Nt']: a1  e4! 58  ce! 6e  ea! 41  e0!
[Nt'']: 5c! ad  f4  39!
Nt'': 9a  42  7b  20

Second auth: 60  00  f5  7b
[Second auth]: 8e  0e! 5d! b9
[Nt]: 5a! 92  0d! 85!
Nt: 57  22  5a  f5

After receiving [Nt''] i decrypt it by xor

  //decrypt tag answer:
  for (pos=0; pos<4; pos++)
  {  
    at[pos] = crypto1_byte(pcs,0x00,0) ^ abtRx[pos];
  }

Then i encrypt the new auth with:

  //encrypt second request:
  for (pos=0; pos<4; pos++)
  {
    abtArEnc2[pos] = crypto1_byte(pcs,0x00,0) ^ abtAuth2[pos];
    abtArEncPar2[pos] = filter(pcs->odd) ^ oddparity(abtAuth2[pos]);
  }

Until now the simulation runns right!

But if I try to decrypt the new Nt with:

  //decrypt new tag nounce:
  for (pos=0; pos<4; pos++)
  {  
    newnt[pos] = crypto1_byte(pcs,0x00,0) ^ abtRx[pos];
  }

The results isn't correct. It is 57  22  5a  f5 but it should be: A5 5D 95 0B.

30 (edited by schwa226 2009-10-04 17:04:16)

Re: Authentication with Mifare Classic using libnfc

Results:

(Block 0x03, KeyA: 0xA0A1A2A3A4A5, KeyB: 0xB0B1B2B3B4B5)

-------------------------------------------------------------------
Starting loop 0
Connected to NFC reader: PN533USB - PN533 v2.7 (0x07)

R: 26
T: 04  00
R: 93  20
T: b4  d1  03  a9  cf
R: 93  70  b4  d1  03  a9  cf  b3  e7
T: 08  b6  dd

Found tag with UID: b4d103a9
Auth: 60  03  6e  49
Nt: 4a  fc  33  e3
[Nr + Nt']: f5  a2! da  e5  f9! 82! 66  82
[Nt'']: 45  6e! e5! 37
Nt'': e7  33  fd  30

Second auth: 61  03  b6  50
[Second auth]: d4! 79  ff  c9
[Nt]: c0  5b! 0d  95

-------------------------------------------------------------------
Starting loop 1
Connected to NFC reader: PN533USB - PN533 v2.7 (0x07)

R: 26
T: 04  00
R: 93  20
T: b4  d1  03  a9  cf
R: 93  70  b4  d1  03  a9  cf  b3  e7
T: 08  b6  dd

Found tag with UID: b4d103a9
Auth: 60  03  6e  49
Nt: 4a  fc  33  e3
[Nr + Nt']: f5  a2! da  e5  f9! 82! 66  82
[Nt'']: 45  6e! e5! 37
Nt'': e7  33  fd  30

Second auth: 61  03  b6  50
[Second auth]: d4! 79  ff  c9
[Nt]: 5a! 00  fa! 16

-------------------------------------------------------------------
Starting loop 2
Connected to NFC reader: PN533USB - PN533 v2.7 (0x07)

R: 26
T: 04  00
R: 93  20
T: b4  d1  03  a9  cf
R: 93  70  b4  d1  03  a9  cf  b3  e7
T: 08  b6  dd

Found tag with UID: b4d103a9
Auth: 60  03  6e  49
Nt: 4a  fc  33  e3
[Nr + Nt']: f5  a2! da  e5  f9! 82! 66  82
[Nt'']: 45  6e! e5! 37
Nt'': e7  33  fd  30

Second auth: 61  03  b6  50
[Second auth]: d4! 79  ff  c9
[Nt]: 5a! 00  fa! 16

I hade to insert a random sleep because of same Nt's! Can't belive it!

-------------------------------------------------------------------
Starting loop 0
rand delay: 91ms

Connected to NFC reader: PN533USB - PN533 v2.7 (0x07)

R: 26
T: 04  00
R: 93  20
T: b4  d1  03  a9  cf
R: 93  70  b4  d1  03  a9  cf  b3  e7
T: 08  b6  dd

Found tag with UID: b4d103a9
Auth: 60  03  6e  49
Nt: 44  81  37  2d
[Nr + Nt']: 89  8f! 92  ad! c4  3f  4a  21!
[Nt'']: 74  c3! 12  81!
Nt'': 08  f0  8b  2d

Second auth: 61  03  b6  50
[Second auth]: 12  c0! df! 6b!
[Nt]: 1f  f7  e9  57

-------------------------------------------------------------------
Starting loop 1
rand delay: 517ms

Connected to NFC reader: PN533USB - PN533 v2.7 (0x07)

R: 26
T: 04  00
R: 93  20
T: b4  d1  03  a9  cf
R: 93  70  b4  d1  03  a9  cf  b3  e7
T: 08  b6  dd

Found tag with UID: b4d103a9
Auth: 60  03  6e  49
Nt: ff  3a  c8  72
[Nr + Nt']: 05! b5! 02  0d  5f  5b  42  ee!
[Nt'']: 80! f8! 8d  d1!
Nt'': 7b  2e  59  89

Second auth: 61  03  b6  50
[Second auth]: ff! df! f2! 1f!
[Nt]: 89  2b  e1! 9f!

-------------------------------------------------------------------
Starting loop 2
rand delay: 384ms

Connected to NFC reader: PN533USB - PN533 v2.7 (0x07)

R: 26
T: 04  00
R: 93  20
T: b4  d1  03  a9  cf
R: 93  70  b4  d1  03  a9  cf  b3  e7
T: 08  b6  dd

Found tag with UID: b4d103a9
Auth: 60  03  6e  49
Nt: b2  63  35  3c
[Nr + Nt']: b1! 5d  19  eb! 51! fe  c4! ff
[Nt'']: f8! e0  a9  fd!
Nt'': 60  26  07  32

Second auth: 61  03  b6  50
[Second auth]: 6c! 35! 4b! 9a!
[Nt]: 9f  df  c9! 7f

thx to all for the basics!

#include <stdio.h>
#include <stdlib.h>
#include <stddef.h>
#include <stdint.h>
#include <stdbool.h>
#include <Windows.h>
#include "libnfc.h"
#include "crapto1.h"

#define SAK_FLAG_ATS_SUPPORTED 0x20

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 dev_info* pdi;

// 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 };

bool transmit_bits(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(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;
}

int main(int argc, const char* argv[])
{

    uint64_t ui64Key;
    uint32_t uiBlock1, uiBlock2, uiTimes, times;
    uint32_t SleepTime;

    char * KeyTyp1;
    char * KeyTyp2;


  if (argc < 6)
  {
    printf(" How to use:\n");
    printf(" nfc-multi-auth <KeyA1/KeyB1> <Key> <block1> <KeyA2/KeyB2> <block2> <times>\n\n");
    printf(" example nfc-multi-auth a ffffffffffff 3 b 3 3\n");
    printf(" desc: login to block 0x03 with KeyA: 0xffffffffffff\n");
    printf(" after successfull login send authentication request for KeyB and block 0x03\n");
    printf(" do this 3 times\n\n");
    printf(" If no times is defined the authentication will be done once\n");
    return 1;
  }

  KeyTyp1 = argv[1];
  sscanf(argv[2],"%012llx",&ui64Key);
  sscanf(argv[3],"%x",&uiBlock1);

  KeyTyp2 = argv[4];
  sscanf(argv[5],"%x",&uiBlock2);

  if (argc == 6)
  {
      uiTimes = 1;
  } else {
      sscanf(argv[6],"%x",&uiTimes);
  }

  //start loop * uiTimes:
  for (times=0; times<uiTimes; times++)
  {
  printf("\n-------------------------------------------------------------------");
  printf("\nStarting loop %d", times);
  SleepTime = rand() % 500 + 50;
  printf("\n rand delay: %dms\n", SleepTime); 

          // Try to open the NFC reader
          pdi = nfc_connect();
          
          if (!pdi)
          {
            printf(" Error connecting NFC reader\n");
            return 1;
          }
          nfc_initiator_init(pdi);

          // Drop the field for a while
          nfc_configure(pdi,DCO_ACTIVATE_FIELD,false);

          // Configure the CRC and Parity settings
          nfc_configure(pdi,DCO_HANDLE_CRC,false);
          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("\n Connected to NFC reader: %s\n\n",pdi->acName);

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

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


          // Test if we are dealing with a 4 bytes uid
          if (abtUid[0]!= 0x88)
          {
            uiUidLen = 4;
          } else {


            // We have to do the anti-collision for cascade level 2
            abtSelectAll[0] = 0x95;
            abtSelectTag[0] = 0x95;


            // Anti-collision
            transmit_bytes(abtSelectAll,2);
            
            // Save the UID
            memcpy(abtUid+4,abtRx,4);
            memcpy(abtSelectTag+2,abtRx,5);
            append_iso14443a_crc(abtSelectTag,7);
            transmit_bytes(abtSelectTag,9);
            uiUidLen = 7;
          }
          
          // Request ATS, this only applies to tags that support ISO 14443A-4
          if (abtRx[0] & SAK_FLAG_ATS_SUPPORTED) transmit_bytes(abtRats,4);
         
          printf("\n Found tag with UID: ");
          if (uiUidLen == 4)
          {
            printf("%08x\n",swap_endian32(abtUid));
          } else {
            printf("%014llx\n",swap_endian64(abtUid)&0x00ffffffffffffffull);
          }

          //random sleep for generating different tag nounces:
          Sleep(SleepTime);
            mifare_multisector_auth(pdi,abtUid,KeyTyp1,ui64Key,uiBlock1,KeyTyp2,uiBlock2);


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

          nfc_disconnect(pdi);
  }

  return 0;
}

bool mifare_multisector_auth(dev_info* pdi, byte_t* pbtUid, char * KeyTyp1, uint64_t ui64Key, uint32_t uiBlock1, char * KeyTyp2, uint32_t uiBlock2)
{
  uint32_t pos, nt;
  struct Crypto1State* pcs;
  byte_t abtAuth[4]        = { 0x00,0x00,0x00,0x00 };
  byte_t at[4]              = { 0x00,0x00,0x00,0x00 };
  byte_t abtAuth2[4]        = { 0x00,0x00,0x00,0x00 };
  byte_t abtArEnc2[4]       = { 0x00,0x00,0x00,0x00 };
  byte_t abtArEncPar2[4]    = { 0x00,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;
  byte_t nr[4]        = { 0xef,0xea,0x1c,0xda };


  //configure if KeyA or KeyB:
  if (*KeyTyp1 == 'a' || *KeyTyp1 == 'A')
  {
    abtAuth[0] = 0x60;
  } else {
    abtAuth[0] = 0x61;
  }
  
  // Configure the authentication frame using the supplied block 
  abtAuth[1] = uiBlock1;
  append_iso14443a_crc(abtAuth,2);

  //print Auth Block:
  printf(" Auth: ");
  print_hex(abtAuth,4);

  // Now we take over, first we need full control over the CRC
  nfc_configure(pdi,DCO_HANDLE_CRC,false);


  // 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);

  // 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(" [Nr + Nt']: ");
  print_hex_par(abtArEnc,64,abtArEncPar);
  if (!nfc_initiator_transceive_bits(pdi,abtArEnc,64,abtArEncPar,abtRx,&uiRxLen,abtRxPar)) return false;
  printf(" [Nt'']: "); 
  print_hex_par(abtRx,uiRxLen,abtRxPar);

  //decrypt tag answer:
  for (pos=0; pos<4; pos++)
  {  
    at[pos] = crypto1_byte(pcs,0x00,0) ^ abtRx[pos];
  }
  printf(" Nt'': ");
  print_hex(at,4);


  //---------------------------------------------------------------------------------------------------
  //do encrypted second auth

  //configure if KeyA or KeyB:
  if (*KeyTyp2 == 'a' || *KeyTyp2 == 'A')
  {
    abtAuth2[0] = 0x60;
  } else {
    abtAuth2[0] = 0x61;
  }
  
  // Configure the authentication frame using the supplied block 
  abtAuth2[1] = uiBlock2;
  append_iso14443a_crc(abtAuth2,2);

  //encrypt second request:
  for (pos=0; pos<4; pos++)
  {
    abtArEnc2[pos] = crypto1_byte(pcs,0x00,0) ^ abtAuth2[pos];
    abtArEncPar2[pos] = filter(pcs->odd) ^ oddparity(abtAuth2[pos]);
  }

  //print Auth Block:
  printf("\n Second auth: ");
  print_hex(abtAuth2,4);

  printf(" [Second auth]: "); 
  print_hex_par(abtArEnc2,32,abtArEncPar2);

  // Request enc tag-nonce
  printf(" [Nt]: ");
  if (!nfc_initiator_transceive_bits(pdi,abtArEnc2,32,abtArEncPar2,abtRx,&uiRxLen,abtRxPar)) return false; 
  print_hex_par(abtRx,32,abtRxPar);

  crypto1_destroy(pcs);

  return true;
}

Re: Authentication with Mifare Classic using libnfc

schwa226 wrote:

But if I try to decrypt the new Nt with:

  //decrypt new tag nounce:
  for (pos=0; pos<4; pos++)
  {  
    newnt[pos] = crypto1_byte(pcs,0x00,0) ^ abtRx[pos];
  }

The results isn't correct. It is 57  22  5a  f5 but it should be: A5 5D 95 0B.

You may want to look into this post again.

The cipher is re-initialized after the second auth() command. This means, load in the new key and start decrypting Nt. This is exactly the point where you are able to learn something about the new key without knowing it.

Re: Authentication with Mifare Classic using libnfc

schwa226 wrote:

Me again!

EDIT may got it working!

After receiving [Nt''] i decrypt it by xor

  //decrypt tag answer:
  for (pos=0; pos<4; pos++)
  {  
    at[pos] = crypto1_byte(pcs,0x00,0) ^ abtRx[pos];
  }

What you are doing here is what i was telling you to do. you are shifting the lfsr so you manage to get the same lfsr state both in the tag and the reader! Even if you skipped the xoring part and called crypto_byte(pcs,0x00,0) 4 times it would still work, or even better call crypto1_word(pcs,0,0) once.

schwa226 wrote:

But if I try to decrypt the new Nt with:

  //decrypt new tag nounce:
  for (pos=0; pos<4; pos++)
  {  
    newnt[pos] = crypto1_byte(pcs,0x00,0) ^ abtRx[pos];
  }

The results isn't correct. It is 57  22  5a  f5 but it should be: A5 5D 95 0B.

As roel says now the situation on the tag side changes. The tag now loads the key into the lfsr. Accordingly you must do the same if we are talking about a legit multisector authentication. But since you want to do the attack what you gain from this new Nt is some knowledge about the new key. This new Nt can be 1 out of 2^16(^ power). So the simplest attack and the most time consuming is to check every Nt to see which one generates the keystream that this one was encrypted and then rollback the register. However parity,time also helps in cutting down those 2^16 values.

Re: Authentication with Mifare Classic using libnfc

schwa226 wrote:

Results:

(Block 0x03, KeyA: 0xA0A1A2A3A4A5, KeyB: 0xB0B1B2B3B4B5)

-------------------------------------------------------------------
Starting loop 0
Connected to NFC reader: PN533USB - PN533 v2.7 (0x07)
...

Hello again, how do you get this results? What algorithm have you used?
I'm trying to do something like that from this topic but unsuccessful.

34 (edited by *dudux 2009-11-25 18:21:52)

Re: Authentication with Mifare Classic using libnfc

roel wrote:

Since there are more questions about this topic I decided to write a working example.
This peace of code uses the current SVN repository version of libnfc and the crapto1 implementation.
I hope this example explains how to perform a manual MIFARE Classic authentication.

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

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;
  
  // 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);

  // 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);

  // 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;

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

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

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

I used the following line for compilation.

gcc -o crypto1test crypto1test.c crypto1.c crapto1.h -I/usr/local/include/libnfc -L/usr/local/lib/ -lnfc

And the console output during execution

./crypto1test ffffffffffff 14

Connected to NFC reader: ACR122U101 - PN532 v1.4 (0x07)

   uid: 6c14df2a
   key: ffffffffffff
 block: 14

 Nt: 65  25  bb  51  
 Ar: 8c! ca  16  f9! c8! 2d  2a! 54  
 At: 9e  cf! 75! 77  

Authentication Succesful

Why do i need for compile?

guepardo crapto1 # gcc -o crypto1test crypto1test.c crypto1.c crapto1.h -I/usr/local/include/libnfc -L/usr/local/lib/ -lnfc
crypto1test.c: In function ‘main’:
crypto1test.c:101: error: too many arguments to function ‘nfc_connect’
guepardo crapto1 #
developing the future!

Re: Authentication with Mifare Classic using libnfc

Does anyone know of where I can get sample code to read/write NDEF messages
to a Mifare Classic tag **without** using an NXP reader ? I guess I would need
sample that shows how to code to authenticate, read/writre encrypt and decrypt
(including parity bit handling) on a regular 14443 PCD with no PN53x. I can control
the parity bit on each byte. I downloaded the Crypto1 library.

TIA.

Re: Authentication with Mifare Classic using libnfc

Hi,

Im trying to read mifare classic tag using CR95HF IC with CRYPTO1.C libraries but, the tag alway response me with NAK byte.
I use this values for other post to test my firmware.
       
        Initialization values
         UID: c1  08  41  6a
         KEY: 62  be  a1  92  fa  37
              Decrypted random nonces
          Nt: ab  cd  19  49
         Nt': 6b  01  17  99
        Nt'': b8  68  c4  dc
          Nr: 16  05  49  0d
              Mifare Classic trace, []=Encrypted
    Auth(00): 60  00  f5  7b
          Nt: ab  cd  19  49
    [Nr,Nt']: 59! d5  92  0f! 15  b9  d5! 53!
      [Nt'']: a7! 9a  3f! ee!

Can someone tell me what means ! simbol in he parity bits.

Please if someone could answer my questions or konws something about crypto1 algorithm I appreciate that answer.