0
votes

I'm struggling to reverse engineer a section of data associated with a CRC-16 checksum. I know the polynom used to calculate the original checksums is 0x8408 but nothing else, I don't know initial value (if any), final XOR value (if any), if the input or the result is reflected...

It seems like there is a known CRC-16 generator using thing polynom, CRC-16-CCITT but despite everything I've tried I just can't understand how the original checksum is being calculated.

Here is the data I've got with their respective checksums. I also included a byte that is between the data and the checksum, it's incremental and I'm not whether it's calculated or not. (see the last two lines, data is almost the same, increment is not the same and yet the checksum are identical)

|                           DATA                           |Inc|CRC|
|----------------------------------------------------------|---|---|
00 00 00 00 00 00 01 ef f7 fe ef ff fd ef fb fa fd a2 aa 21 01 f4 e0
00 00 00 00 00 00 01 ef f7 fd ef ff fd fe fb fa fd a2 aa 21 02 f4 d1
00 00 00 00 00 00 01 f7 fe fd fd ff fd df ff fb fd a2 aa 21 03 f4 cd
00 00 00 00 00 00 01 f7 fe fe fd ff f7 ef ff fa fd a2 aa 21 04 f4 c2
00 00 00 00 00 00 01 ef f7 fe ef ff fe ef fb fa fd a2 aa 21 05 f4 db
00 00 00 00 00 00 01 ef f7 fe ef ff fd ef fb fa fd a2 aa 21 06 f4 db
1
Are you sure about this being a CRC16 with poly 0x8408? If you xor the last 2 lines, it cancels crc initial value and xor out, and you get {00 00 00 00 00 00 00 00 00 00 00 00 03 00 00 00 00 00 00 00 03 00 00}, which is unlikely to be a CRC, since the two 03's and CRC == 0 imply that the cyclic period is 64 bits (8 bytes), which is too short. If you don't include the second 03, you get {{00 00 00 00 00 00 00 00 00 00 00 00 03 00 00 00 00 00 00 00 00 00}, getting a CRC = 0 for non-zero data.rcgldr
@rcgldr Well I can't tell I'm 100% sure about that since I don't have access to the code used to calculate the checksum but I got the poly value, length of the checksum (2 bytes) and its position within the data packet from a SQL table of the software associated with this data.Spacebrain
@rcgldr Plus, in the SQL table some fields clearly says it's CRC. Also, doesn't it looks odd to you how the first byte of the checksum never changes ? Isn't CRC algorithm designed to make the checksum different even with a single data byte changed ?Spacebrain
Yes, typically both halves of the CRC will change along with any change in the data. In the last two lines, the additional sums are the same and the "checksums" are the same, leading me to think it's some form of checksum.rcgldr
@rcgldr So you think it's not CRC ? That's a bit off with my initial question but is there any way to test for known checksums algorithms and then find out which one is used ? Also, for what it's worth, the data + "CRC" ends on an embedded system powered by a Motorola MPC CPU.Spacebrain

1 Answers

2
votes

The last byte of each line appears to be 0xF3 + the negative sum of all but the last byte (including the 0xF4). This code works for the 5 examples:

typedef unsigned char uint8_t;

static uint8_t data0[] = 
   {0x00,0x00,0x00,0x00,0x00,0x00,0x01,0xef,0xf7,0xfe,0xef,
    0xff,0xfd,0xef,0xfb,0xfa,0xfd,0xa2,0xaa,0x21,0x01,0xf4,0xe0};
static uint8_t data1[] = 
   {0x00,0x00,0x00,0x00,0x00,0x00,0x01,0xef,0xf7,0xfd,0xef,
    0xff,0xfd,0xfe,0xfb,0xfa,0xfd,0xa2,0xaa,0x21,0x02,0xf4,0xd1};
static uint8_t data2[] = 
   {0x00,0x00,0x00,0x00,0x00,0x00,0x01,0xf7,0xfe,0xfd,0xfd,
    0xff,0xfd,0xdf,0xff,0xfb,0xfd,0xa2,0xaa,0x21,0x03,0xf4,0xcd};
static uint8_t data3[] = 
   {0x00,0x00,0x00,0x00,0x00,0x00,0x01,0xf7,0xfe,0xfe,0xfd,
    0xff,0xf7,0xef,0xff,0xfa,0xfd,0xa2,0xaa,0x21,0x04,0xf4,0xc2};
static uint8_t data4[] = 
   {0x00,0x00,0x00,0x00,0x00,0x00,0x01,0xef,0xf7,0xfe,0xef,0xff,
    0xfe,0xef,0xfb,0xfa,0xfd,0xa2,0xaa,0x21,0x05,0xf4,0xdb};
static uint8_t data5[] = 
   {0x00,0x00,0x00,0x00,0x00,0x00,0x01,0xef,0xf7,0xfe,0xef,0xff,
    0xfd,0xef,0xfb,0xfa,0xfd,0xa2,0xaa,0x21,0x06,0xf4,0xdb};

int main()
{
size_t i;
uint8_t c = 0xf3;
uint8_t s;
    s = c;
    for(i = 0; i < sizeof(data0)-1; i++)
        s -= data0[i];
    if (data0[i] != s)
        printf("mismatch\n");
    s = c;
    for (i = 0; i < sizeof(data1) - 1; i++)
        s -= data1[i];
    if (data1[i] != s)
        printf("mismatch\n");
    s = c;
    for (i = 0; i < sizeof(data2) - 1; i++)
        s -= data2[i];
    if (data2[i] != s)
        printf("mismatch\n");
    s = c;
    for (i = 0; i < sizeof(data3) - 1; i++)
        s -= data3[i];
    if (data3[i] != s)
        printf("mismatch\n");
    s = c;
    for (i = 0; i < sizeof(data2) - 1; i++)
        s -= data4[i];
    if (data4[i] != s)
        printf("mismatch\n");
    return 0;
}