This post sums up my steps for understanding the BANNED Redi Check MAV222 (aka Redi Check Model ET-732) checksum algorithm. I'm posting this, hoping it'll help others that are interested in figuring out, how the algorithm works. Note: this is not a generic recipe on how to proceed when reverse engineering something like a checksum algorithm.
Thanks to the previous posts in this thread, we already know, that the temperature values are tranmitted more or less in plain text. However, there wasn't much information available on what information the checksum contains, and how it behaves. I started by making a list of questions regarding the checksum.
In order to figure out, how the checksum behaves, it is beneficial to gather as much data as possible as a starting point. For deterministic results I tried to set up an environment, which is completely under control, including
I decided to replace the thermometers with variable resistors. In case anyone wants to reproduce this: the resistance is non-linear. At low temperatures (0..25°C) it takes several 100 KOhm, (around 0°C even MOhm) to increase / decrease the temperature by 1°C. At higher temperatures it takes just several KOhm to increase / decrease the temperature by 1°C. Furthermore, I used a stabilized external power supply, instead of batteries.
For gathering the actual data, I wrote a simple Linux kernel module, which prints the received data and checksum bits on the console. The output looks like this:
Code: Select all
t0=0,t1=575,1111,1010,1000,0010,1000,1111,1100,0000,0000,0101,1010,0010,1001
t0=0,t1=576,1111,1010,1000,0010,1001,0000,0000,0000,0000,1011,1010,1010,1110
t0=0,t1=577,1111,1010,1000,0010,1001,0000,0100,0000,0000,0110,0110,0110,1110
t0=0,t1=578,1111,1010,1000,0010,1001,0000,1000,0000,0000,0001,0011,0000,1111
t0=0,t1=579,1111,1010,1000,0010,1001,0000,1100,0000,0000,1100,1111,1100,1111
t0=0,t1=580,1111,1010,1000,0010,1001,0001,0000,0000,0000,1111,1001,1100,1101
t0=0,t1=581,1111,1010,1000,0010,1001,0001,0100,0000,0000,0010,0101,0000,1101
t0=0,t1=582,1111,1010,1000,0010,1001,0001,1000,0000,0000,0101,0000,0110,1100
t0=0,t1=583,1111,1010,1000,0010,1001,0001,1100,0000,0000,1000,1100,1010,1100
t0=0,t1=584,1111,1010,1000,0010,1001,0010,0000,0000,0000,0011,1100,0110,1000
t0=0,t1=585,1111,1010,1000,0010,1001,0010,0100,0000,0000,1110,0000,1010,1000
t0=0,t1=586,1111,1010,1000,0010,1001,0010,1000,0000,0000,1001,0101,1100,1001
t0=0,t1=587,1111,1010,1000,0010,1001,0010,1100,0000,0000,0100,1001,0000,1001
t0=0,t1=588,1111,1010,1000,0010,1001,0011,0000,0000,0000,0111,1111,0000,1011
t0=0,t1=589,1111,1010,1000,0010,1001,0011,0100,0000,0000,1010,0011,1100,1011
t0=0,t1=590,1111,1010,1000,0010,1001,0011,1000,0000,0000,1101,0110,1010,1010
t0=0,t1=591,1111,1010,1000,0010,1001,0011,1100,0000,0000,0000,1010,0110,1010
t0=0,t1=592,1111,1010,1000,0010,1001,0100,0000,0000,0000,1010,0111,0000,0011
t0=0,t1=593,1111,1010,1000,0010,1001,0100,0100,0000,0000,0111,1011,1100,0011
t0=0,t1=594,1111,1010,1000,0010,1001,0100,1000,0000,0000,0000,1110,1010,0010
t0=0,t1=595,1111,1010,1000,0010,1001,0100,1100,0000,0000,1101,0010,0110,0010
t0=0,t1=596,1111,1010,1000,0010,1001,0101,0000,0000,0000,1110,0100,0110,0000
t0=0,t1=597,1111,1010,1000,0010,1001,0101,0100,0000,0000,0011,1000,1010,0000
t0=0,t1=598,1111,1010,1000,0010,1001,0101,1000,0000,0000,0100,1101,1100,0001
t0=0,t1=599,1111,1010,1000,0010,1001,0101,1100,0000,0000,1001,0001,0000,0001
t0=0,t1=600,1111,1010,1000,0010,1001,0110,0000,0000,0000,0010,0001,1100,0101
t0=0,t1=601,1111,1010,1000,0010,1001,0110,0100,0000,0000,1111,1101,0000,0101
t0=0,t1=602,1111,1010,1000,0010,1001,0110,1000,0000,0000,1000,1000,0110,0100
t0=0,t1=603,1111,1010,1000,0010,1001,0110,1100,0000,0000,0101,0100,1010,0100
t0=0,t1=604,1111,1010,1000,0010,1001,0111,0000,0000,0000,0110,0010,1010,0110
t0=0,t1=605,1111,1010,1000,0010,1001,0111,0100,0000,0000,1011,1110,0110,0110
t0=0,t1=606,1111,1010,1000,0010,1001,0111,1000,0000,0000,1100,1011,0000,0111
t0=0,t1=607,1111,1010,1000,0010,1001,0111,1100,0000,0000,0001,0111,1100,0111
t0=0,t1=608,1111,1010,1000,0010,1001,1000,0000,0000,0000,1000,0001,1111,0100
Since the microcontroller used in the transmitter is a quite simple device (4 bit Microcontroller - WindRiver: W541E260), it is likely, that the checksum calculation is a relatively simple operation, as well (e.g. using logical AND, OR, XOR, bitshift, etc.). A
containing the assembler instruction set reinforces this assumption. Although it's in Chinese, it still contains the english acronyms of the instructions, including the registers they work on and whether they set carry-over or zero flags.
My first attempt in deciphering the checksum was to look at checksum as a whole. I was looking for patterns, e.g. what happens to checksum, if temperature is increased by 1°C:
However, to me there was no obvious pattern. Therefore, I started to look at the behaviour of individual checksum bits:
As one can see in this example, the bold checksum bits in column csum[2] seem to toggle with the bold data bits in column data[8]. Therefore, it's likely, that this checksum bit depends on the data bit. However there's an irregularity at t=592, as the bit doesn't toggle there. If you encounter such irregularities, don't scrap your assumption immediaely. Instead, try to figure out, what the root cause of the irregularity might be. Upon closer inspection of this row, it becomes clear, that another data bit (which was previously always zero) toggled to one (data[7], bold bit). Therefore, it's likely that the considered checksum bit not only depends on one but several data bits, which are XORd with each other.
From this point on, it makes sense to systematically analyze, which checksum bit depends on which data bit. In case you want to retrace the steps for determining the dependencies, I recommend to look at the following temperature changes:
Furthermore, plug and unplug the thermometer probes to toggle an additional bit.
After a systematic evaluation, it turns out that each checksum bit depends on approximately 7-9 data bits. In total this makes over 120 individual XOR operation. At this point it's possible to calculate the checksum. However, there are still three issues
To address issue 3), I decided to see, if there's a pattern in how the XOR operations are applied. My approach was to make a table for better visualization:
If you check the green column and have a look at the column next to it, it seems, that the XOR bit pattern is shifted "upwards". However this pattern changes at column data[8], bit 3. Therefore it's not a simple bitshift operation. Upon closer inspection, it becomes clear, that the bit pattern changes, whenever bit 3 of csum[0] is "1" and the bit pattern is shifted left ("up" in the picture). This is a behaviour typical for a linear feedback shift register. I decided to verify this assumption, by implementing a shift register in software. The "green" column is the initial bitmask (0x3331). When executing the shift register step by step, one can determine, which bit positions should be fed back. The final result is that the feedback pattern is 0001 0000 0010 0001 (= 0x1021).
To address issue 2, I decided not only to generate the XOR mask for data nibbles data[8]...data[4], but also to generate the XOR mask for nibble data[3]. By also including nibble data[3], issue 2 could be resolved. This means that the checksum not only includes the temperature (contained in nibbles data[4] ... data[8]), but also nibble data[3].
With all this informaiton, it's now relatively easy to write code for generating the checksum:
The C code provided in the previous post performs exactly aforementioned steps with some optimizations :)