Calculating the initial CRC value instead of adding the CRC to the payload

Most of the CRCs I've implemented were adding the calculated CRC value to the message (payload) and checking for a null result in the receiver after all bytes incl. The CRC value was supplied through the CRC register. Obviously, this is a pretty standard approach.

Now I would like to use a different approach:

  • Calculate the value from the payload.
  • Use this value as the initial value for the CRC register before . message bytes (payload) are fed through the CRC register so that the result after the last byte of the payload is fed through zero.

What's the best way to do this? Do you have a good idea or some pointers where to dig deeper?

ps: Why do I want to do this? In some applications (ROMs), I cannot add data because the data is stored at the end of the address space of the ROM. So I would like to either preload the CRC register or add a value to the post.


source to share

1 answer

I have now programmed a solution for the above problem that was simpler than I originally thought it would be.

I found several articles on how you can fake a CRC. This means how to correct the data so that the calculated CRC has a predefined value.

Using this approach, I just had to use the last bytes of my actual payload as the CRC value, which is quite obvious.

Finally, I needed to calculate the "inverse" CRC using my payload data. The result of this calculation is the initial value that I should use when calculating the CRC.

Since I am working on a limited memory system, I have reduced the size of the 256 element CRC table (1024 bytes for CRC32) down to 16 entries (64 bytes) and now process each byte in two steps, which are now still much faster than bit offset ...

// Reverse CRC table for Castagnoli polynomial (0x1EDC6F41)
static const unsigned long crc32c_revTable[16] =
    0x00000000L, 0x05EC76F1L, 0x0BD8EDE2L, 0x0E349B13L,
    0x17B1DBC4L, 0x125DAD35L, 0x1C693626L, 0x198540D7L,
    0x2F63B788L, 0x2A8FC179L, 0x24BB5A6AL, 0x21572C9BL,
    0x38D26C4CL, 0x3D3E1ABDL, 0x330A81AEL, 0x36E6F75FL

unsigned long calcReverseCRC32C(unsigned long crc32c, 
                                const unsigned char* pData,
                                unsigned long len)
    while (len--)
        crc32c = (crc32c << 4) ^ crc32c_revTable[crc32c >> 28];
        crc32c = (crc32c << 4) ^ crc32c_revTable[crc32c >> 28];
        crc32c ^= *pData--;

    return crc32c;



    // This array contains test data with 4 bytes CRC appended
    // The result of CRC-32C calculation using this data is zero
    unsigned char arr[] = {'1', '2', '3', '4', '5', '6', '7', '8', '9',
                           0x7c, 0x6d, 0xf9, 0x1c};

    unsigned long expectedResultOfCRC = 0;
    unsigned long init = calcReverseCRC32C(expectedResultOfCRC,
                                           &arr[sizeof(arr) -1],
                                           sizeof(arr) );




All Articles