Most of the CRCs I\'ve implemented were appending the calculated CRC value to the message (payload) and checking for a zero result at the receiver after all
I've now programmed a solution for the above mentioned problem which was easier than I initially thought it would be.
I found several articles about how one can forge a CRC. That means how to patch data that way that the calculated CRC value will have a predefined value.
Using such an approach I simply had to use the last bytes of my actual payload as CRC value which is quite obvious.
Finally I only needed to calculate the "reverse" CRC using my payload data. The result of this calculation is the initial value I have to use when calculating the CRC.
As I'm working on a very memory constrained system I reduced the size of the CRC table with 256 entries (1024 bytes for CRC32) down to 16 entries (64 bytes) and now process each byte in two steps now which still is much faster than shifting the bits.
// 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;
}
Usage:
{
// 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) );
}