Skip to main content
Visitor II
September 28, 2021
Solved

CRC Polynomial

  • September 28, 2021
  • 4 replies
  • 2752 views

Hi,

How to calculate the ISO14443-a CRC value(16 bit). Please help me how to get the CRC.

ISO14443-A >>> CR95HFDLL_SENDRECEIVE, 300028

<< 8015 6A1E4DB17E00004B3592000000000000 9BC3 080000

0x9BC3 ISO14443-a CRC value

Kind Regards,

Merin

    This topic has been closed for replies.
    Best answer by alister

    A Google search threw these...

    A CRC function and links to others: https://stackoverflow.com/questions/40869293/iso-iec-14443a-crc-calcuation

    Some details on CR95HF and clues where to get more: https://community.st.com/s/question/0D50X00009XkW7G/iso-14443a-cr95hf-and-the-crc-bit

    Another CRC implementation: https://www.microchip.com/forums/m896426.aspx

    Datasheets, tools and software: https://www.st.com/en/nfc/st25-nfc-rfid-tags-readers.html

    4 replies

    alisterAnswer
    Explorer
    September 28, 2021

    A Google search threw these...

    A CRC function and links to others: https://stackoverflow.com/questions/40869293/iso-iec-14443a-crc-calcuation

    Some details on CR95HF and clues where to get more: https://community.st.com/s/question/0D50X00009XkW7G/iso-14443a-cr95hf-and-the-crc-bit

    Another CRC implementation: https://www.microchip.com/forums/m896426.aspx

    Datasheets, tools and software: https://www.st.com/en/nfc/st25-nfc-rfid-tags-readers.html

    Mjohn.1Author
    Visitor II
    September 28, 2021

    The resolved program to calculate the ISO14443-a CRC value(16 bit) as follow.

    data_byte = 0x12;

    CHECKSUM_CALCULATE(0x12 ^ 0x6363);

    unsigned int CHECKSUM_DATA;

    void CHECKSUM_CALCULATE(unsigned int C_DATA)

    {

    unsigned int n;

     for(n=1;n<=8;n++)

     {

     if((C_DATA & 0x01)==0x01)

     {

     C_DATA = C_DATA >> 1;

     C_DATA = C_DATA ^ 0x8408;

     }

     else

     {

     C_DATA = C_DATA >> 1;

     }

     }

     CHECKSUM_DATA = C_DATA;

    }

    ISO14443A Polynomial is 0x8408, initial value is 0x6363, CRC output is 0x626d

    online 16bit crc calculator : https://hub.zhovner.com/tools/nfc/

    Kind Regards,

    Merin

    Technical Moderator
    September 28, 2021

    Hi,

    just for my curiosity, why do you need to compute the CRC? The CR95HF does the job for you and provides a CRC error bit in the response flags of the SendReceive command.

    Rgds

    BT

    Graduate II
    September 28, 2021

    The CRC here is 0xC39B in small endian form. If you run the data+crc thru the right shifting algorithm the data will divide cleanly resulting in a zero remainder.

    C:\MSVC\CRC>iso14443a

    626D == 0x626D

    626D

    test_one=C39B << Note High/Low bytes swapped

    test_two=0000

    PASS

    // ISO14443A CRC Example sourcer32@gmail.com
     
    #include <windows.h>
    #include <stdio.h>
    #include <stdlib.h>
     
    typedef unsigned char uint8_t;
    typedef unsigned short uint16_t;
    typedef unsigned long uint32_t;
     
    uint16_t crc_iso14443a(uint16_t crc, uint8_t data)
    {
     int i;
     crc = crc ^ data;
     for(i=0; i<8; i++)
     if (crc & 1)
     crc = (crc >> 1) ^ 0x8408;
     else
     crc >>= 1;
     return(crc);
    }
     
    uint16_t crc_iso14443a_quick(uint16_t crc, uint8_t data)
    {
     static const uint16_t crctbl[] = { // 0x8408 Nibble Table, sourcer32@gmail.com
     0x0000,0x1081,0x2102,0x3183,0x4204,0x5285,0x6306,0x7387,
     0x8408,0x9489,0xA50A,0xB58B,0xC60C,0xD68D,0xE70E,0xF78F };
     
     crc = crc ^ data;
     
     crc = (crc >> 4) ^ crctbl[crc & 0xF]; // Two rounds of 4-bits
     crc = (crc >> 4) ^ crctbl[crc & 0xF];
     
     return(crc);
    }
     
    uint16_t crc_iso14443a_quick_block(uint16_t crc, int size, uint8_t *buffer)
    {
     while(size--)
     crc = crc_iso14443a_quick(crc, *buffer++);
     
     return(crc);
    }
     
    void test_one(void)
    {
     // ISO14443-A >>> CR95HFDLL_SENDRECEIVE, 300028
     // << 8015 6A1E4DB17E00004B3592000000000000 9BC3 080000
     
     uint8_t data[] = {
     0x6A,0x1E,0x4D,0xB1,0x7E,0x00,0x00,0x4B,
     0x35,0x92,0x00,0x00,0x00,0x00,0x00,0x00 };
     
     uint16_t crc;
     
     crc = crc_iso14443a_quick_block(0x6363, sizeof(data), data);
     
     printf("test_one=%04X\n", crc );
    }
     
    void test_two(void)
    {
     // ISO14443-A >>> CR95HFDLL_SENDRECEIVE, 300028
     // << 8015 6A1E4DB17E00004B3592000000000000 9BC3 080000
     
     uint8_t data[] = {
     0x6A,0x1E,0x4D,0xB1,0x7E,0x00,0x00,0x4B,
     0x35,0x92,0x00,0x00,0x00,0x00,0x00,0x00,
     0x9B,0xC3 };
     
     uint16_t crc;
     
     crc = crc_iso14443a_quick_block(0x6363, sizeof(data), data);
     
     printf("test_two=%04X\n", crc);
     if (crc == 0) puts("PASS"); else puts("!!FAIL!!");
    }
     
    int main(int argc, char **argv)
    {
     printf("%04X == 0x626D\n", crc_iso14443a(0x6363, 0x12) );
     
     printf("%04X\n", crc_iso14443a_quick(0x6363, 0x12) );
     
     test_one();
     test_two();
     
     return(1);
    }