Pairing/Bonding errors with a nRF MCU to a Windows laptop

I've written a GUI in python on a windows laptop which communicates fine with an nRF MCU when using open broadcast and no security. I'm using python's bleak library to connect and read/write gatt characteristics. I now want to implement security. I have copied much of the code from lesson 2 in the sdk fundamentals. I've modified it to use a static passkey for security level 4 connections. It still uses the filter accept list and pairing button. 

It works fine on the nRF connect app. I connect, then write to one of the characteristics, which then prompts an input for the static passkey. However, on windows, this is not the case. I'm doing pairing outside of the python program as I don't believe bleak supports that functionality. I intend to use the GUI after pairing. When connecting, it says "connecting..." on windows, the 'on_connected' callback executes on the MCU, then it errors out on both the laptop and mcu after about 15 seconds. No bonding occurs and no messages are sent/received.

Errors seen:

[00:09:16.687,164] <inf> BLE_Main: Security failed: 58:A0:23:A6:35:0A (public) level 1 err 9

[00:09:16.687,377] <inf> BLE_Main: Disconnected (reason 8)

My Bluetooth drivers:

Error 9 on security fail is BT_SECURITY_ERR_UNSPECIFIED. Is the issue that the windows laptop has no means of entering the static passkey? Or could it be that LE Secure Connections is not natively supported?

Help is much appreciated.

  • Hi Austin, 
    As you already found error 9 doesn't give much info about the error. I would suggest to use a sniffer to capture the bonding process. 
    You can find the sniffer guide in the same Bluetooth course. Please send us the sniffer trace for further investigation. 
    Could you describe how you do static passkey. As far as I understand it's not recommended to use static passkey with LE Secure Connection. It only takes 20 trials to crack it. 

  • Here are the logs and sniffer packets before the sniffer halts and no longer captures packets. Upon disconnect, it's configured to automatically start advertising again and the RPA then changes. 

    BLE_Secure_Windows_Error.csv

    8741.BLE_Windows_Secure_Error.pcapng

    With the nRF connect mobile app I can properly us the SC LTK to decode encrypted messages in Wireshark. I see no issues there.

    I was planning to use a static passkey and static MAC address for pairing. The device has only a button so the user is to click the button which puts it in advertising mode briefly. An app/gui initiates a pair request then the user enters the key and address. Are there better alternative secure pairing options? OOB with NFC is feasible, but I believe adds unnecessary complication.

    As for actually setting the passkey, I have CONFIG_BT_FIXED_PASSKEY=y in prj.conf and bt_passkey_set(PASSKEY); called on initialization.

  • What the BLE standard can offer for you in this case is LESC with Just Works pairing, which is ok for protecting against eavesdropping attackers. Assuming no input/output capabilities, unless you use OOB pairing, the BLE standard does unfortunately not offer any Man-in-the-middle protection pairing variants. Homekit and Matter standards use their own Password-authenticated key agreement (PAKE) on top of normal unencrypted BLE using a QR code sticker as a workaround in order to get MITM and eavesdropper protection.

    In any case, you should upload more sniffer logs from more attempts than just a single one. It appears the central Bluetooth controller fails and drops the connection upon receiving the LL_PHY_REQ from the peripheral, which seems to be a bug in the central Bluetooth controller. You should file a bug report to Intel if you can repeatedly reproduce this.

    One question though to the Nordic team is why the peripheral sends an additional feature request to the central when it moments ago already received the feature set from the central.

  • Hi Hung Bui,

    I made a post on stack overflow and was assisted by two individuals Emil and Risto, who pointed out another post https://devzone.nordicsemi.com/f/nordic-q-a/104258/security-failed-level-1-err-9-connecting-error-with-bonded-device.

    Upon placing either CONFIG_BT_PHY_UPDATE=n or CONFIG_BT_AUTO_PHY_UPDATE=n the pairing issue is resolved. I would still like to know exactly why this occurs. Why does this only occur on PC but not my mobile phone? Where can I read more about PHY update details? 

    Also, could you help answer Emil's question?

  • Hi Austin, 

    I'm glad that you found the workaround. I agree with Emil that it could be something wrong on the BLE controller on the PC's side that couldn't handle the LL_PHY_REQ. My suggestion is to try request LL_PHY_REG at later stage after the bonding has been completed. There is a chance that the controller prohibit to change PHY when the pairing is on going. Even though as far as I know it's not prohibited by the spec. 

    Regarding static passkey, I don't agree with Emil that Passkey (not static passkey) doesn't offer any MITM protection. It does provide MITM protection if it's used correctly, in this case randomly generated on each pairing. 

    You should avoid using static passkey though. It's intended for testing only, not production. You can find the discussion here: https://github.com/zephyrproject-rtos/zephyr/issues/36005

    Regarding this

    Emil Lenngren said:
    One question though to the Nordic team is why the peripheral sends an additional feature request to the central when it moments ago already received the feature set from the central.

    I assume Emil was asking about the LL_PERIPHERAL_FEATURE_REQ. Be aware that the first LL_FEATURE_REQ is from the central the second one is from the peripheral. So they are on the opposite direction to get the feature set of each peers. 

Related