nccgroup / Sniffle

A sniffer for Bluetooth 5 and 4.x LE
https://www.nccgroup.trust/us/our-research/sniffle-a-sniffer-for-bluetooth-5/?research=Public+tools
GNU General Public License v3.0
861 stars 127 forks source link

Unable to set WinSize and WinOffset on v1.10.0 #96

Open jsmif opened 2 months ago

jsmif commented 2 months ago

I'm wondering if there's some sanity checking or alteration of CONNECT_IND LLData values somewhere in the firmware that I'm missing? (I did at least look, but it seemed to me that the firmware is just using the LLData as-is.)

I made the following change to sniffle_hw.py's initiate_conn()

         # WinSize, WinOffset, Interval, Latency, Timeout
-        llData.append(3)
-        llData.extend(pack("<H", randint(5, 15)))
-        llData.extend(pack("<H", interval))
-        llData.extend(pack("<H", latency))
-        llData.extend(pack("<H", 50))
+#        llData.append(3)
+#        llData.extend(pack("<H", randint(5, 15)))
+#        llData.extend(pack("<H", interval))
+#        llData.extend(pack("<H", latency))
+#        llData.extend(pack("<H", 50))
+        llData.append(1) # WinSize
+        llData.extend(pack("<H", 0)) # WinOffset
+        llData.extend(pack("<H", 6)) # Interval
+        llData.extend(pack("<H", 0)) # Latency
+        llData.extend(pack("<H", 20)) # Timeout
+        print("setvalues")
+        print(llData)

However, it doesn't seem like it's honoring the new requested WinSize or WinOffset values, as this is what I see when I sniff the request:

image

The values other than WinSize and WinOffset are changing fine, so I'm pulling out my hair trying to figure out what's going on here. When I print out the values, they seem to be appropriate little-endian values across the board:

setvalues
[130, 89, 211, 143, 18, 255, 227, 1, 0, 0, 6, 0, 0, 0, 20, 0]

But what's so weird is that the WinSize isn't even the "3" value that it was in the original code, so I don't know where either WinSize or WinOffset are coming from unless there's some firmware-level fiddling with the data that I missed. I also reverted back to using tagged version 1.10.0 just in case I was getting any sort of weird desynchronization of python vs. fw behavior.

jsmif commented 2 months ago

OK, I did a complete revert on the sniffle_hw.py and brought it back to baseline v1.10.0, but I actually still don't see it honoring WindowSize or WindowOffset from the initial values. Here are two values which shouldn't be possible with the initial llData.append(3) and llData.extend(pack("<H", randint(5, 15)))

image

jsmif commented 2 months ago

FWIW I tested versions 1.9.0-1.9.3 as well, and never saw a WinSize of 3...so I'm not sure what's up...

sultanqasim commented 2 months ago

This is "working as designed" though perhaps I should change it. The bDynamicWinOffset flag is enabled for the initiator command: https://github.com/nccgroup/Sniffle/blob/6cda3db003b23355a35d4e53364b487330b97976/fw/RadioWrapper.c#L673

Thus, it sets WinSize and WinOffset based on the following logic described in the TI reference manual:

25.8.11.4 Automatic Window Offset Insertion

If pParams->initConfig.bDynamicWinOffset is 1, the radio CPU shall perform automatic calculation of the WinSize and WinOffset parameters in the transmitted CONNECT_IND or AUX_CONNECT_REQ message. WinSize is byte 7 of the payload, and WinOffset is byte 8 and 9 (see the Bluetooth Specification documents listed in Related Documentation). The radio CPU shall find the possible start times of the first connection event from the pParams->connectTime parameter and the connection interval, which shall be given in units of 1.25 ms by the Interval field (byte 10 and 11) from the payload to be transmitted (see the Bluetooth Specification documents listed in Related Documentation). The possible times of the first connection event are any whole multiple of connection intervals from pParams->connectTime, which may be in the past or the future from the start of the initiator command.

The radio CPU shall insert a WinOffset parameter in the transmitted CONNECT_IND or AUX_CONNECT_RSP such that the first connection event is signaled to be at the first connection event that comes sufficiently long after the end of the CONNECT_IND or AUX_CONNEXT_REQ packet to be transmitted. This means that the time from the end of the CONNECT_IND or AUX_CONNECT_REQ packet to the start of the first packet in the connection is between transmitWindowDelay + WinOffset and transmitWindowDelay + WinOffset + WinSize, where transmitWindowDelay is 1.25 ms when a CONNECT_IND PDU is used, 2.5 ms when an AUX_CONNECT_REQ PDU is used on an LE Uncoded PHY, and 3.75 ms when an AUX_CONNECT_REQ PDU is used on the LE Coded PHY, (for details, see the Specification of the Bluetooth System, Version 5.0 listed in Related Documentation). The radio CPU shall set up the transmit window (WinOffset and WinSize) so that there is margin both between the start of the transmit window and the start of the first master packet and between the start of the first master packet and the end of the transmit window (see the Specification of the Bluetooth System, Version 5.0 listed in Related Documentation). The inserted WinSize shall be either 1 or 2; ensuring such a margin. The margin is set to the correct value through an override in the BLE stack (see Section 25.8.4).

The radio CPU shall write the calculated values for WinSize and WinOffset into the corresponding locations in the pParams->pConnectData buffer. The start time of the first connection event to be used in order to transmit the first packet within the signaled transmit window shall be written back by the radio CPU in pParams- >connectTime. If no connection is made, the radio CPU shall add a multiple of connection intervals to pParams- >connectTime so that it is the first possible time of a connection event after the operation ended.

jsmif commented 1 month ago

I see. I must have completely imagined it when I thought before that I had successfully set WinSize and WinOffset (probably it was just happening to set WinSize to 1 and then I didn't pay enough attention to other values.)

Thanks for the explanation.