This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

Mifare Ultralight C Authentication

Other Parts Discussed in Thread: TRF7970A

I am developing Mifare Ultralight C reader with the TRF7970A. Authentication of the card is not happening properly. The problem is when I send 1A command (for authentication part1), I am get encrypted random number.

But for part 2 authentication (i.e. for AF command) I don't get expected response instead collision is happening.

Please help me with a solution. 

Thank you

  • Aparna - 

    see attached - should help you out with that step - so you can make 0xAF + 0xEk(RndA + RndB’) and send it out. 

    56422.MFULC_AUTH.pdf

  • Thank you Josh Wyatt,

    I have tried this method and used the same commands. But still the response is same as mentioned before. 

    Is there any other solution? 

    Regards,

    Aparna

  • Aparna - these steps work on this side. Do you have more detail like logic captures you can share or exactly how you have configured the part and what commands (in sequence) you are sending back and the Interrupts you get back, etc.

  • I will share you the function I am using. Please check it. Also I am not able to debug with CCS. Without debugging I get ek(RandB) but with debugging on I think I do not get back any response for the commands.

    Should I send SELECT command before AUTH1 (1A) command?

    And may I please know if modifying values of block

    0x2A (which is by default set to 0x30) (so that no authentication is required to read/write blocks) to the block number from where auth  

     and

    0x2B  (which is by default set to NULL) by values which defines if read/write auth is required from the block number specified in 0x2A block

    is required before starting the auth process.

    static unsigned char authCmd1[20] = {0x30, 0x31, 0x30, 0x41, 0x30, 0x30, 0x30, 0x33, 0x30, 0x34, 0x31, 0x38, 0x31, 0x41, 0x30, 0x30, 0x30, 0x30, 0x30,0x30};


    static unsigned char authCmd2[52] = {0x30, 0x31, 0x31, 0x39, 0x30, 0x30, 0x30, 0x33, 0x30, 0x34, 0x31, 0x38, 0x41, 0x46, 0x30, 0x30, 0x30, 0x30, 0x30,0x30};

    static unsigned char AGC_Toggle[18] = {0x30, 0x31, 0x30, 0x39, 0x30, 0x30, 0x30, 0x33, 0x30, 0x34, 0x46, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30 ,0x30};

    static unsigned char AM_PM_TOGGLE[18]= {0x30, 0x31, 0x30, 0x39, 0x30, 0x30, 0x30, 0x33, 0x30, 0x34, 0x46, 0x31, 0x46, 0x46, 0x30, 0x30, 0x30 ,0x30};

    static unsigned char anti_collision[18]={0x30, 0x31, 0x30, 0x39, 0x30, 0x30, 0x30, 0x33, 0x30, 0x34, 0x41, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30 ,0x30};

    static unsigned char isoControl[20] = {0x30,0x31,0x30,0x41,0x30, 0x30, 0x30, 0x33, 0x30, 0x34, 0x31, 0x30, 0x30, 0x31, 0x30, 0x38, 0x30 ,0x30 , 0x30 ,0x30};


    void nfcAuthenticate(void)
    {
    int delay, index, rand_count, index1, index2 = 0, authcnt;
    static int AuthResult;

    switch(nfc_init_stage_auth)
    {
          case POLL:
          {
              UARTSend_NFC(stop_polling,16);
              for(delay=0;delay<=1000000;delay++);
              nfc_init_stage_auth = VER;
         }
         break;


        case VER:
        {
             UARTSend_NFC(firmware_rev,16);
            for(delay=0;delay<=10000000;delay++);
            nfc_init_stage_auth = SETA;
        }
        break;

        case SETA:
       { 
             UARTSend_NFC(set_iso14443a,24);
             for(delay=0;delay<=10000000;delay++);
             nfc_init_stage_auth = AGCT;
       }  
        break; 
       case AGCT:
       { 
            UARTSend_NFC(AGC_Toggle,18);
            for(delay=0;delay<=10000000;delay++);
           nfc_init_stage_auth = AMPMT;
        }
        break;
        case AMPMT:
        {
            UARTSend_NFC(AM_PM_TOGGLE,18);
            for(delay=0;delay<=10000000;delay++);
            nfc_init_stage_auth = ANTICOLL;
         }
         break;

         case ANTICOLL:
          {
                UARTSend_NFC(anti_collision,18);
                 for(delay=0;delay<=10000000;delay++);
                 nfc_init_stage_auth = ISOCNRL;
          }
          break;
          case ISOCNRL:
          {
                UARTSend_NFC(isoControl,20);
               for(delay=0;delay<=10000000;delay++);
               memset(rx_queue_nfc, 0x00, sizeof(rx_queue_nfc) );
             nfc_init_stage_auth = AUTH1;
        }
       break;


             case AUTH1:
             {
                   UARTSend_NFC(authCmd1,20);
                  GPIO_SetBits(GPIOB, GPIO_Pin_9);
                  GPIO_ResetBits(GPIOB, GPIO_Pin_9);

                  for(delay=0;delay<=1000000;delay++);

                 nfc_init_stage_auth = AUTH2;
            }
            break;
            case AUTH2:
            {
                  for(index = 14; index < 46; index++)
                  {
                         authCmd2[index] = RandNum4[rand_count];
                         rand_count++;
                  }
                  for(index = 46; index <53; index++)
                  authCmd2[index] = 0x30;

                 memset(rx_queue_nfc, 0x00, sizeof(rx_queue_nfc));
               
                 UARTSend_NFC(authCmd2,52);

                 GPIO_ResetBits(GPIOB, GPIO_Pin_9);
                 GPIO_SetBits(GPIOB, GPIO_Pin_9);
                 for(delay=0;delay<=1000000;delay++);
                 nfc_init_stage_auth = AUTH3;
            }
            break;
         default:
         break;
        }
    }

    Thank you,

    Aparna

  • Aparna -
    did you check out the PDF in detail?

    you need to take the response from Auth1 (this is called EkRndB) and generate RndB, then take 8 byte random # and RndB' (this is RndB with first byte rotated) and using EkRndB for IV to generate Ek(RndA + RndB'), which is then sent for Auth2 command.

    the EkRndB response will be different each time you challenge the tag with Auth1 command.

    i just went through the steps again here on this side and PICC answered with Ek(RndA') which was correct.

    this is 3(DES) steps by the way, here is a library code example

    www.ti.com/.../des_102612
  • also - please see below for another example (like what is in the PDF) to help you understand the steps.

  • Thank You Josh,

    I have followed all the steps you have mentioned. 

      • On Tag Detection Device will get 7Byte UUID and card type.
      • Device sends Auth1(1A) command to NFC card
      • Upon receiving 1A command the Card sends back  ek(RndB) to TPMOD device.
      • On receiving 8 bytes of data i.e. ek(RndB), device does the following functions:

     

      1. Deciphers ek(RndB) to get RndB. Left rotates 8 bits to get RndB’.
      2. Reader generated RndA
      3. then sends ek(RndA + RndB’) to the card which is encrypted with the key.
      • Card deciphers ek(RndA + RndB’) to get (RndA + RndB’) using the key. Verifies RndB’. 

               Card sends back ek(RandA')

      •  The device verifies RndA’ to confirm whether  the card is authenticated or not.

    I have sent you only the command part of the code because I want to confirm if the commands I have defined are correct and in proper sequence. 

    We have NFC chip integrated on our module and we are not testing on the evm. Could that be the issue here? 

    Please suggest.

    Regards,

    Aparna

  • Hi,

    I have one more question, please go through and give a suggestion

    I did step by step debugging of my code, here are the various arrays I have got.

    ek(RndB) = { 0x5C, 0x8F, 0xBF, 0x38, 0x9A, 0xCC, 0x88, 0x06}

    RndB = { 0x82, 0x3E, 0xDA, 0xA8, 0x5A, 0x41, 0x15, 0xBA}

    RndB' = { 0x3E, 0xDA, 0xA8, 0x5A, 0x41, 0x15, 0xBA, 0x82}

    RndA = { 0x10, 0x8C, 0x02, 0x33, 0xF9, 0x41, 0xA6, 0x5C}

    RndA + RndB' = {0x10, 0x8C, 0x02, 0x33, 0xF9, 0x41, 0xA6, 0x5C,
    0x3E, 0xDA, 0xA8, 0x5A, 0x41, 0x15, 0xBA, 0x82}

    Ek(RndA + RndB') = {0x60, 0xD1, 0x65, 0x91, 0xB4, 0xEA, 0xAF, 0x3C,
    0x6E, 0x53, 0xE1, 0x3C, 0x0B, 0xD2, 0x73, 0xA4}

    KEY = {0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
    0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F};}

    Note : I did write this key to the card using WRITE command, but still I think that may be the key on card is different from the one which we are using. If that is the case what error response can we expect? I am getting collision error now, is it because of different keys used ?

    Thank you,
    Aparna
  • using that key, that random # and Ek(RndB) = 5C8FBF389ACC8806, you should have gotten

    RndB: 91A45074F2535D45
    RndB': A45074F2535D4591

    to yield an Ek(RndA+RndB'): C30BD6ACDF96A1412E4A5779F0D64BD5 (for Auth 2 challenge)

    to yield Auth2 response: Ek(RndA'): F2506BC9DBF852E2
  • That means the key which I am using and the key in card are different ? Is that why I am getting collision error?

    I used simple WRITE command to write key on the card. Is there any way to confirm if the key is written successful?

  • sounds reasonable - why don't you try using a "fresh" card with default key first to check your function is working for that.
    writing is successful if you get ACK back from the writing process, its a fail if you get a NACK
  • Alright. I just wanted to confirm if I am using a relevant library . So here I am attaching the library I am using. Could you please verify if its relevant? 

    Thank you,

    Aparna.stm32-cryp-lib.zip

  • I thought of using the library example you have shared before. But that library uses 24 bytes key whereas we are using 16 bytes key.

    I still don't know why am I getting collision error, but I strongly believe that API I am using are different from the one used by card. I have attached the library in previous reply, so please verify and let me know if that is causing a problem.

    Thank you,
    Aparna
  • Aparna -
    we don't support STM32 here directly. Hope you understand.
    the collision error is most likely occurring because the command going out is incorrect.

    give us a day or two to get back on this.
    thanks for your patience.
  • Aparna -
    the way this works - it is called 3DES by the vendor - in general 3DES has a different scheme, in this case the vendor is using a 1 -2 - 1 scheme.
    So using the library you have from STM , the first 8 bytes (key) will be normal, second 8 bytes (key 1) will be normal, and the 3rd eight bytes will be "key" again (the same as first eight bytes)

    you could also have a look at this (search for Keying Option 2, this is what is being used) ==> en.wikipedia.org/.../Triple_DES
  • Thank you Josh,

    Your suggestions helped me clear my confusion. The TI buffer (buf - used in firmware) gets filled with the command 1A  . however, when I send the second command i.e., AF, the buf will be empty and is not getting filled by the command we have sent and hence the error I suppose.  

    What might be causing this error?

    please suggest.

    Thank you,

    Aparna

  • i think if i were you, i would set a breakpoint or breakpoints in your code and look at your memory locations to track down why the code you are using or have developed does not populate the field as you need it too.
  • I understand Josh,

    I put it here just to know if it is a known issue, I am debugging for the it anyways. 

    Thank you,

    Aparna.