2

Hello everyone I am finishing the last section of my firmware for my NFC project. I am attempting to communicate with an AD-740 NFC Tag which uses NXP's MF0ULx1 MIFARE Ultralight EV1 - Contactless ticket IC. The NFC reader that I am using is NXP's CLRC663. I am controlling the NFC reader with a PSOC5LP device over SPI.

Now that you have all of the background information I will now ask my question.

For this particular NXP Read Method I need to encode my Cmd and Addr into a CRC of length 2 bytes. The datasheet, which I can link to, references ISO/IEC 14443. Searching that in Google brings me to the Wikipedia page, which then shows four sections of a PDF. I am assuming that I need section 4 the transmission protocol section. The only problem is this PDF is blocked by a pay wall. Is this intentional??

Scrounging around on the internet I have found a few code examples that may prevent me from purchasing a 170$ PDF just to look at a polynomial...

Code example 1 - I can post source link in comments. Don't have rep to do it in main post.

    // Calculate an ISO 14443a CRC. Code translated from the code in
    // iso14443a_crc().
    func ISO14443aCRC(data []byte) [2]byte {
        crc := uint32(0x6363)
        for _, bt := range data 
        {
            bt ^= uint8(crc & 0xff)
            bt ^= bt << 4
            bt32 := uint32(bt)
            crc = (crc >> 8) ^ (bt32 << 8) ^ (bt32 << 3) ^ (bt32 >> 4)
         }

       return [2]byte{byte(crc & 0xff), byte((crc >> 8) & 0xff)}
    }

Code example 2 - I can post source link in comments. Don't have rep to do it in main post.

    void iso14443a_crc(byte_t* pbtData, size_t szLen, byte_t* pbtCrc)
    {
      byte_t bt;
      uint32_t wCrc = 0x6363;

      do {
        bt = *pbtData++;
        bt = (bt^(byte_t)(wCrc & 0x00FF));
        bt = (bt^(bt<<4));
        wCrc = (wCrc >> 8)^((uint32_t)bt << 8)^((uint32_t)bt<<3)^((uint32_t)bt>>4);
      } while (--szLen);

      *pbtCrc++ = (byte_t) (wCrc & 0xFF);
      *pbtCrc = (byte_t) ((wCrc >> 8) & 0xFF);
    }

And now on to my final question with all of this information... Would it be safe to assume that:

CRC polynomial is: 0x6363

Seed Value is: 0x00FF

A visual representation can be seen here

CDutko
  • 23
  • 1
  • 5
  • [MF0ULx1 Datahsheet](http://cache.nxp.com/documents/data_sheet/MF0ULX1.pdf?pspll=1) | [Code Example 1 Source](https://github.com/fuzxxl/nfc/blob/master/dev/nfc/crc.go#L23) | [Code Example 2 Source](https://git.eleves.ens.fr/hackens/libnfc/blob/a78cae1c1505dec2c3e411a0592fcbc133c78644/src/lib/bitutils.c) – CDutko Nov 29 '16 at 15:24

2 Answers2

5

I've found a few helpful resources in calculating CRC_A for ISO/IEC 14443:

For posterity, here's libnfc's implementation of iso14443a_crc:

void
iso14443a_crc(uint8_t *pbtData, size_t szLen, uint8_t *pbtCrc)
{
  uint32_t wCrc = 0x6363;

  do {
    uint8_t  bt;
    bt = *pbtData++;
    bt = (bt ^ (uint8_t)(wCrc & 0x00FF));
    bt = (bt ^ (bt << 4));
    wCrc = (wCrc >> 8) ^ ((uint32_t) bt << 8) ^ ((uint32_t) bt << 3) ^ ((uint32_t) bt >> 4);
  } while (--szLen);

  *pbtCrc++ = (uint8_t)(wCrc & 0xFF);
  *pbtCrc = (uint8_t)((wCrc >> 8) & 0xFF);
}
Paul Lammertsma
  • 37,593
  • 16
  • 136
  • 187
4

ISO14443A Polynomial is 0x8408, initial value is 0x6363.

Nipo
  • 2,617
  • 13
  • 20
  • Thank you for your help, but is there any way that you can prove that these are the correct values? – CDutko Nov 29 '16 at 15:40
  • I honestly don't know where you came up with those numbers, but I'm pretty sure they're right. I'm finding multiple sources with those same values now. – CDutko Nov 29 '16 at 16:08
  • 3
    I could tell you to read iso14443-3, but that would be cheeky :) – Nipo Nov 29 '16 at 16:09
  • 2
    CRC_A is defined is ISO/IEC 13239 (HDLC) with a custom initial value. 13239 itself only defines CRC16 wikipedia refers as CRC-16-CCITT. – Nipo Nov 29 '16 at 16:15
  • Thank you for your help Nipo! – CDutko Nov 29 '16 at 16:34
  • How can we create 16 bit crc with ISO/IEC 3309 – Manoj Tarkar Nov 15 '17 at 13:41
  • Please double check. I think CRC for ISO14443A has polynomial 0x1021, initial value 0xC6C6, reverse input and output. When I calculate CRC value for "123456789" string on http://www.zorc.breitbandkatze.de/crc.html it gives me BF05. – Alexandr Zarubkin Feb 18 '19 at 12:12
  • These values are the same with inverted bit order. – Nipo Feb 18 '19 at 12:34
  • @Nipo As per the libnfc code in the other answer, its 0x00FF instead of 0x8408, (initial value is same though), any idea why? – Jimson James Oct 24 '19 at 17:51
  • Masking with `0x00ff` is just there to take the LSBs. Actual polynomial is in expressions `bt = (bt ^ (bt << 4)); wCrc = (wCrc >> 8) ^ ((uint32_t) bt << 8) ^ ((uint32_t) bt << 3) ^ ((uint32_t) bt >> 4);`. Understanding why is left as an exercise to the reader. This implementation avoids both a precomputed table and a loop over 8 bits. If you want more confusion, look for the many CRC implementations of [Proxmark's](https://github.com/Proxmark/proxmark3/) code base. – Nipo Oct 24 '19 at 19:23