jopohl / urh

Universal Radio Hacker: Investigate Wireless Protocols Like A Boss
GNU General Public License v3.0
10.79k stars 862 forks source link

Using de-whitening for non-CC1101 radio chips #749

Closed jgromes closed 4 years ago

jgromes commented 4 years ago

Hi,

I'm trying to decode FSK data from SX1268, It's working great for NRZ, however, I'm a bit stuck with whitening. I'm trying to use the built-in dewhitener for CC1101, but that one makes a few assumptions about the procedure that may not be true on radios other than CC1101. For example, I can't seem to find a way to set the initial LFSR value. There's also a comment that the polynomial should be entered without the first bit - why is that?

I think it would be great to generalize the whitening decoder, so that it can be used for other transceivers, not just CC1101. For example, both SX127x and SX126x series use whitening.

Thanks!

PS: Just starting with URH, let me know if I overlooked something :)

andynoack commented 4 years ago

Hi, we assume (111...) as the initial state for the LFSR and this is indeed not configurable in the GUI. Then, the first bit (highest bit) is the degree of the polynomial and not used for internal calculations, therefore omitted. There are, however, implementations that work with a full notation and some that skip the first bit like we do. Taking the bit into account is important when we work with polynomials with degrees != 0 mod 4 (i.e. not hex/byte aligned).

Because configuration file reading/writing methods, GUI (plausibility checks), backend and tests have to be adapted, making the initial state configurable is not simply done. We can, however, add it to our long todo list for features. Can you provide us with a precise description for a generalized algorithm and test values (we just have CC1101 hardware here) in the format: "10101010..." (encoded) -> "11110101010101..." (decoded)? Also skipping the first bit can be discussed, of course. If there are many use cases that use non-hex aligned polynomials (and initial states), it can be reasonable to change this behaviour as well.

jgromes commented 4 years ago

I'm still a bit confused by the first bit interpretation. My understanding so far was that each bit set in the hex number corresponds to the appropriate power of x in the whitening polynomial, so that if I want to use the polynomial x^9 + x^5 + 1, that would become 0b1000100001 (0x221 in hex).

SX126x actually uses the same polynomial as CC1101 (x^9 + x^5 + 1), and since the initial LFSR value is configurable, I tried using 0x1FF, so it should be the same as for CC1101. The first byte of payload is always decoded correctly, but subsequent bytes are nonsense.

Here's a sample, packet structure is:

Sent:        0x55552d010123456789abcdefab5a 
Demodulated: 0x55552d01fea4fd3e3e0a01cbe0cd 
Decoded:     0x55552d010145e0a4d38f32ef0ab7
andynoack commented 4 years ago

Have you tried skipping the first bit of thy polynomial? The CC1101 standard polynomial (x^9+x^5+x^0) can be configured as '0x21'. URH skips the first bit (just the order of the LFSR polynomial) and accepts nibble aligned, i.e. multiple of 4 bits, polynomial lengths. This is because LFSR calculation works this way.

When you are sending with initial state 0x1ff, the decoding should be equal to CC1101 which should work (with polynomial 0x21). Note that if the first decoded byte is correct, the initial state is equal to CC1101, but there is something wrong with the LFSR polynomial.

jgromes commented 4 years ago

I did try that, that's how I got the above posted sample.

I also tried to receive SX1268 transmission with CC1101, the decoded data is the same as what URH decodes. My main guess right now as to what is happenning is that the whitening polynomial listed in SX126x datasheet just doesn't correspond to what is actually implemented on silicon - wouldn't be the first time the docs were "inaccurate" to put it very mildly.

However, I know for a fact that the whitening polynomial on SX126x is the same as on SX127x (since messages whitened on SX127x do decode on SX126x and vice versa). SX127x whitening was cracked previously, and the whitening sequences are known (https://github.com/rpp0/gr-lora/blob/master/lib/tables.h). Slightly off-topic but still - would you happen to know if there's a way to get the correct polynomial from the PRNG sequence (other than emulating the LSFR and bruteforcing)?

andynoack commented 4 years ago

If you have 2m bits of PRNG sequence, you can reconstruct the degree m LFSR polynomial. Can you post a 2m sequence and degree m as bits?

jgromes commented 4 years ago

Could you please clarify what's m in this context? Is it m=9 for x^9 + x^5 + 1? And if that's the case, 18 bits is enough to reconstruct the polynomial? That seems very low for a presumably 9 bit LFSR.

Sorry if it's a dumb question, my knowledge of signal processing is quite basic. The maximum length PRNG sequence I can get from a single packet is 256 bytes (since that's the FIFO size on SX126x), I'll post it shortly.

andynoack commented 4 years ago

It is exactly that way and even if it seems unbelievable, you just need 2m bits for a degree m polynomial. Please do me a favor and post it as bits.

jgromes commented 4 years ago

Here's the PRNG sequence for 8 bytes, I got it by transmitting an array of null bytes, with LFSR initial state set to 0x1FF.

hex: ff87b859b7a1cc24
bin: 1111111110000111101110000101100110110111101000011100110000100100

So if we assume m = 9, then that would make the 2m sequence 111111111000011110.

andynoack commented 4 years ago

Ok, by computation x^9+x^5+x^0 it is, i.e. 0x21 in URH or (0x221) in some other applications. This does not work for you, because there is a difference in the way bits are read.

With the above parameters, URH creates the keystream: 1111.1111.1110.0001.0001.1101 Yours is: 1111.1111.1000.0111.10 If you compare both streams, you note that they are identical, if you read the bits the other way around (bytewise), e.g. 1000.0111 =right-to-left=> 1110.0001. So it is all about the right bitorder. Fortunately there is an encoding function called "Change Bitorder" that you can apply before (and maybe also after...depends on how you want to interpretate the data) the CC1101 dewhitening. Can you play around with this feature and test if it works in your case?

jgromes commented 4 years ago

Oh wow, that actually did the trick! :D

It turns out that the bytes are actually flipped twice: once before whitening, and once afterwards. To decode the SX126x FSK, I now do the following:

The decoder reports a couple of decoding errors (3 errors for 96 bits of message), but it seems to decode the data correctly - possibly an issue with some trailing 0 bits.

Unfortunately, the bit order flipping means no cross-compatibility for whitened SX127x/6x frames with CC1101 (unless the de-whitening is done in software). Oh well, not a huge issue.

Thank you so much, you were a huge help! I guess there's no need to change anything in URH at this point.