Skip to content

crc8_ccitt discards the MSB of every input byte on non-AVR targets #1370

Description

@TudorFanaru18

modm::math::crc8_ccitt_update never examines bit 7 of its input. On non-AVR targets the shift happens before the test, and on a uint8_t that discards the bit being tested.

src/modm/math/utils/crc.hpp:

inline uint8_t
crc8_ccitt_update(uint8_t crc, uint8_t data)
{
#ifdef __AVR__
    return _crc8_ccitt_update(crc, data);
#else
    data ^= crc;
    for (uint8_t ii = 0; ii < 8; ii++)
    {
        data <<= 1;                       // <-- bit 7 is gone here
        if (data & 0x80) data ^= 0x07;    // <-- so this tests the pre-shift bit 6
    }
    return data;
#endif
}

The avr-libc assembly it replaces:

1:  lsl    %0        ; shift left, MSB -> CARRY
    brcc   2f        ; branch on CARRY, i.e. the *pre-shift* MSB
    eor    %0, %2

lsl preserves the departing bit in the carry flag, so brcc still tests bit 7 of the value before the shift. C has no carry flag, so data <<= 1 simply loses that bit and the following if (data & 0x80) reads the pre-shift bit 6 instead.

The AVR path is correct; only the #else branch is affected.

Impact

crc8_ccitt("123456789") returns 0x9B. CRC-8 with polynomial 0x07 and init 0xFF is 0xFB.

Because one input bit is ignored:

  • crc8_ccitt_update(crc, d) == crc8_ccitt_update(crc, d ^ 0x80) for all 32768 (crc, d) pairs
  • only 128 of 256 output values are reachable
  • for an n-byte message, 2ⁿ distinct messages share a CRC

Suggested fix

Capture the MSB before shifting, which is what the carry flag does on AVR:

data ^= crc;
for (uint8_t ii = 0; ii < 8; ii++)
{
    const bool msb = (data & 0x80) != 0;
    data <<= 1;
    if (msb) data ^= 0x07;
}
return data;

Notes

  • Tested against develop at 2390135.
  • Checked crc16_ccitt and crc32 against their published check values (0x6F91 CRC-16/MCRF4XX and 0xCBF43926 CRC-32/ISO-HDLC); both are correct and MSB-sensitive. Only crc8_ccitt is affected.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions