Skip to content

Commit

Permalink
minor: Refactor ccitt_whitening() to bit_util
Browse files Browse the repository at this point in the history
  • Loading branch information
zuckschwerdt committed Dec 15, 2024
1 parent 5f17123 commit 11d2c7a
Show file tree
Hide file tree
Showing 3 changed files with 66 additions and 39 deletions.
11 changes: 11 additions & 0 deletions include/bit_util.h
Original file line number Diff line number Diff line change
Expand Up @@ -180,6 +180,17 @@ uint8_t lfsr_digest8_reflect(uint8_t const message[], int bytes, uint8_t gen, ui
/// @return digest value
uint16_t lfsr_digest16(uint8_t const message[], unsigned bytes, uint16_t gen, uint16_t key);

/// Apply CCITT data whitening to a buffer.
///
/// The CCITT data whitening process is built around a 9-bit Linear Feedback Shift Register (LFSR).
/// The LFSR polynomial is the same polynomial as for IBM data whitening (x9 + x5 + 1).
/// The initial value of the data whitening key is set to all ones, 0x1FF.
/// s.a. https://www.nxp.com/docs/en/application-note/AN5070.pdf s.5.2
///
/// @param buffer bytes of message data
/// @param buffer_size number of bytes to process
void ccitt_whitening(uint8_t *buffer, unsigned buffer_size);

/// Compute bit parity of a single byte (8 bits).
///
/// @param byte single byte to check
Expand Down
49 changes: 49 additions & 0 deletions src/bit_util.c
Original file line number Diff line number Diff line change
Expand Up @@ -396,6 +396,32 @@ uint16_t lfsr_digest16(uint8_t const message[], unsigned bytes, uint16_t gen, ui
return sum;
}

// The CCITT data whitening process is built around a 9-bit Linear Feedback Shift Register (LFSR).
// The LFSR polynomial is the same polynomial as for IBM data whitening (x9 + x5 + 1).
// The initial value of the data whitening key is set to all ones, 0x1FF.
// s.a. https://www.nxp.com/docs/en/application-note/AN5070.pdf s.5.2
void ccitt_whitening(uint8_t *buffer, unsigned buffer_size)
{
uint8_t key_msb = 0x01;
uint8_t key_lsb = 0xff;
uint8_t key_msb_previous;
uint8_t reflected_key_lsb = key_lsb;

for (unsigned buffer_pos = 0; buffer_pos < buffer_size; buffer_pos++) {
reflected_key_lsb = (key_lsb & 0xf0) >> 4 | (key_lsb & 0x0f) << 4;
reflected_key_lsb = (reflected_key_lsb & 0xcc) >> 2 | (reflected_key_lsb & 0x33) << 2;
reflected_key_lsb = (reflected_key_lsb & 0xaa) >> 1 | (reflected_key_lsb & 0x55) << 1;

buffer[buffer_pos] ^= reflected_key_lsb;

for (uint8_t rol_counter = 0; rol_counter < 8; rol_counter++) {
key_msb_previous = key_msb;
key_msb = (key_lsb & 0x01) ^ ((key_lsb >> 5) & 0x01);
key_lsb = ((key_msb_previous << 7) & 0x80) | ((key_lsb >> 1) & 0xff);
}
}
}

/*
void lfsr_keys_fwd16(int rounds, uint16_t gen, uint16_t key)
{
Expand Down Expand Up @@ -481,6 +507,23 @@ int add_nibbles(uint8_t const message[], unsigned num_bytes)
fprintf(stderr, "FAIL: %d <> %d\n", (a), (b)); \
} \
} while (0)
#define ASSERT_MATCH(a, b, n) \
do { \
if (memcmp(a, b, n) == 0) \
++passed; \
else { \
++failed; \
fprintf(stderr, "FAIL:"); \
for (size_t i = 0; i < n; i++) { \
fprintf(stderr, " %02x", a[i]); \
} \
fprintf(stderr, "\n <>"); \
for (size_t i = 0; i < n; i++) { \
fprintf(stderr, " %02x", b[i]); \
} \
fprintf(stderr, "\n"); \
} \
} while (0)

int main(void) {
unsigned passed = 0;
Expand Down Expand Up @@ -517,6 +560,12 @@ int main(void) {

fprintf(stderr, "util:: test (%u/%u) passed, (%u) failed.\n", passed, passed + failed, failed);

fprintf(stderr, "util::ccitt_whitening():\n");
uint8_t buf[16] = {0};
uint8_t chk[16] = {0xff, 0x87, 0xb8, 0x59, 0xb7, 0xa1, 0xcc, 0x24, 0x57, 0x5e, 0x4b, 0x9c, 0x0e, 0xe9, 0xea, 0x50};
ccitt_whitening(buf, sizeof(buf)) ;
ASSERT_MATCH(buf, chk, sizeof(buf));

return failed;
}
#endif /* _TEST */
45 changes: 6 additions & 39 deletions src/devices/deltadore_x3d.c
Original file line number Diff line number Diff line change
Expand Up @@ -185,35 +185,6 @@ struct __attribute__((packed)) deltadore_x3d_message_payload {
uint16_t target_ack;
};

static void ccitt_dewhitening(
uint8_t *whitening_key_msb_p,
uint8_t *whitening_key_lsb_p,
uint8_t *buffer,
uint16_t buffer_size)
{
uint8_t whitening_key_msb = *whitening_key_msb_p;
uint8_t whitening_key_lsb = *whitening_key_lsb_p;
uint8_t whitening_key_msb_previous;
uint8_t reverted_whitening_key_lsb = whitening_key_lsb;

for (uint16_t buffer_pos = 0; buffer_pos < buffer_size; buffer_pos++) {
reverted_whitening_key_lsb = (whitening_key_lsb & 0xf0) >> 4 | (whitening_key_lsb & 0x0f) << 4;
reverted_whitening_key_lsb = (reverted_whitening_key_lsb & 0xcc) >> 2 | (reverted_whitening_key_lsb & 0x33) << 2;
reverted_whitening_key_lsb = (reverted_whitening_key_lsb & 0xaa) >> 1 | (reverted_whitening_key_lsb & 0x55) << 1;

buffer[buffer_pos] ^= reverted_whitening_key_lsb;

for (uint8_t rol_counter = 0; rol_counter < 8; rol_counter++) {
whitening_key_msb_previous = whitening_key_msb;
whitening_key_msb = (whitening_key_lsb & 0x01) ^ ((whitening_key_lsb >> 5) & 0x01);
whitening_key_lsb = ((whitening_key_msb_previous << 7) & 0x80) | ((whitening_key_lsb >> 1) & 0xff);
}
}

*whitening_key_msb_p = whitening_key_msb;
*whitening_key_lsb_p = whitening_key_lsb;
}

/* clang-format off */
static uint32_t deltadore_x3d_read_le_u24(uint8_t **buffer)
{
Expand Down Expand Up @@ -307,14 +278,12 @@ static int deltadore_x3d_decode(r_device *decoder, bitbuffer_t *bitbuffer)
return DECODE_ABORT_LENGTH;
}

uint8_t whitening_key_msb = 0x01;
uint8_t whitening_key_lsb = 0xff;

// read length byte in advance
uint8_t len;
bitbuffer_extract_bytes(bitbuffer, row, start_pos, &len, 8);

// dewhite length
ccitt_dewhitening(&whitening_key_msb, &whitening_key_lsb, &len, 1);
ccitt_whitening(&len, 1);

if (len > DELTADORE_X3D_MAX_PKT_LEN) {
if (decoder->verbose) {
Expand All @@ -324,16 +293,14 @@ static int deltadore_x3d_decode(r_device *decoder, bitbuffer_t *bitbuffer)
}

uint8_t frame[65] = {0};
frame[0] = len;

// Get frame (len includes the length byte)
bitbuffer_extract_bytes(bitbuffer, row, start_pos + 8, &frame[1], (len - 1) * 8);
// Get whole frame (len includes the length byte)
bitbuffer_extract_bytes(bitbuffer, row, start_pos, frame, len * 8);

// dewhite the data
ccitt_dewhitening(&whitening_key_msb, &whitening_key_lsb, &frame[1], len - 1);
ccitt_whitening(frame, len);

if (decoder->verbose > 1) {
decoder_log_bitrow(decoder, 0, __func__, frame, (len)*8, "frame data");
decoder_log_bitrow(decoder, 0, __func__, frame, len * 8, "frame data");
}

const uint16_t crc = crc16(frame, len - 2, 0x1021, 0x0000);
Expand Down

0 comments on commit 11d2c7a

Please sign in to comment.