Factory-pairing two nRF52840

Hi there,

I'm developing a product composed of two nRF52840, one being a USB+BLE keyboard and the other being a wireless USB dongle. The two are connected via Nordic UART Service.

I want to pre-pair the keyboard and dongle in the factory via USB. I already store the keyboard's address in the dongle via the settings API and vice versa, which works as intended. But I also want to ensure secure communication.

By secure communication, I'm not even sure which security level I should use, but I'd expect the pre-pairing process to fill out the relevant bt/* Settings API values so that the keyboard and dongle get securely connected.

Please give me some directions regarding the implementation details because I'm quite lost.

Thanks in advance!
- Laci

Parents
  • Hello,

    If you want to ensure two devices (or a family of devices) are the ones only able to bond. Then I recommend to check out OOB, normally OOB is used over NFC, but there is nothing preventing you to store a 16byte OOB key in produciton, and use this OOB key to ensure only those two devices you control can successfully bond and exchange information.

    I suggest to for instance look at the auth_oob_data_request() in main.c for peripheral_keyboard  and replace app_nfc_oob_data_get() with the 128-bit key you want to use. Similar on central you need to add the .oob_data_request callback in conn_auth_callbacks to handle such event. I believe you can use this example as starting point for central:
    https://developer.nordicsemi.com/nRF_Connect_SDK/doc/latest/nrf/samples/bluetooth/central_hids/README.html 

    Similar for keyboard:
    https://developer.nordicsemi.com/nRF_Connect_SDK/doc/latest/nrf/samples/bluetooth/peripheral_hids_keyboard/README.html#peripheral-hids-keyboard 

    Kenneth

  • Hi Kenneth!

    I took over this issue on our side from Laci, and am utterly confused. I don't know much about bluetooth and I haven't found much information on oob key exchange.

    Could you please elaborate, and maybe point me to some comprehensible information source?


    bt_le_oob_set_sc_data expects bt_le_oob_sc_data for local and/or remote:

    struct bt_le_oob_sc_data {
        /** Random Number. */
        uint8_t r[16];
    
        /** Confirm Value. */
        uint8_t c[16];
    };

    If I understand correctly, the entire procedure should proceed as follows:

    1. device A generates a random number and computes the confirm value based on the random number and A's public(?) key
    2. I transfer above keys and A's addres to B by a private channel, and there store it in RAM
    3. I set the oob_data_request callback on B and let the devices initiate the connection
    4. when oob_data_request is called, I call bt_le_oob_set_sc_data with A's keys (as remote oob data?)

    I have tried to identify what confuses me, and came up with following questions:

    • I believe this should take place symmetrically on both devices, is this correct?
    • This is two 16-byte keys and each device has its own r and c, so in the end I need to exchange four 16 byte keys, is that correct?
    • How do I generate/retrieve the r and c values in the first place in step 1? (If I am the one to generate r, how do I communicate it to the ble stack?)
    • The peripheral_hids_keyboard example sets the key received from the remote as its local data instead of remote. Why?
    • As to the central_hids example, it doesn't seem very relevant, as it doesn't handle pairing via oob at all.
    • Furthermore, shouldn't computation of c be based on A's private key rather than public? Based on general principles, I would expect a computation based on a public key to be easy to forge by any MITM.

    Thanks in advance!
    Karel

    P.S. I also don't understand why the formatting system randomly changes font sizes. Sob

Reply
  • Hi Kenneth!

    I took over this issue on our side from Laci, and am utterly confused. I don't know much about bluetooth and I haven't found much information on oob key exchange.

    Could you please elaborate, and maybe point me to some comprehensible information source?


    bt_le_oob_set_sc_data expects bt_le_oob_sc_data for local and/or remote:

    struct bt_le_oob_sc_data {
        /** Random Number. */
        uint8_t r[16];
    
        /** Confirm Value. */
        uint8_t c[16];
    };

    If I understand correctly, the entire procedure should proceed as follows:

    1. device A generates a random number and computes the confirm value based on the random number and A's public(?) key
    2. I transfer above keys and A's addres to B by a private channel, and there store it in RAM
    3. I set the oob_data_request callback on B and let the devices initiate the connection
    4. when oob_data_request is called, I call bt_le_oob_set_sc_data with A's keys (as remote oob data?)

    I have tried to identify what confuses me, and came up with following questions:

    • I believe this should take place symmetrically on both devices, is this correct?
    • This is two 16-byte keys and each device has its own r and c, so in the end I need to exchange four 16 byte keys, is that correct?
    • How do I generate/retrieve the r and c values in the first place in step 1? (If I am the one to generate r, how do I communicate it to the ble stack?)
    • The peripheral_hids_keyboard example sets the key received from the remote as its local data instead of remote. Why?
    • As to the central_hids example, it doesn't seem very relevant, as it doesn't handle pairing via oob at all.
    • Furthermore, shouldn't computation of c be based on A's private key rather than public? Based on general principles, I would expect a computation based on a public key to be easy to forge by any MITM.

    Thanks in advance!
    Karel

    P.S. I also don't understand why the formatting system randomly changes font sizes. Sob

Children
  • Hi,

    In an ideal world I would have time to look into the details here, but unfortunately I am not. I would suggest using an example that implement NFC, ideally for both central and peripheral, since that will be the easiet to modify in your case. I can see there is a \central_nfc_pairing and \peripheral_nfc_pairing example in the nRF Connect SDK. Further I can find that there is an option to set CONFIG_BT_OOB_DATA_FIXED, which will use the hardcoded OOB value you can find in bt_smp_le_oob_generate_sc_data(), the quick solution here may just to simple change that value to some #define that you can set somewhere.

    Kenneth

  • Thanks Kenneth!

    It seems I got it working.

    For any reader who might be interested, a few hints:

    - remove old bonds via bt_foreach_bond and bt_unpair
    - on peripheral (nus server), retrieve the address and the c and r numbers (i.e., 6+16+16 bytes of data) via `bt_le_oob_get_local(BT_ID_DEFAULT, &oob);`
    - carry them over to central (nus client)
    - set oob flags via bt_le_oob_set_sc_flag on both devices (maybe one suffices, not sure)
    - trigger pairing. For us it means to disconnect the connection(s) on peripheral, and reload scan filters on central
    - now just wait for the oob_data_request callback and pass the data via bt_le_oob_set_sc_data
    - manage authentication methods via `bt_conn_auth_cancel(conn);`, e.g., to disable passphrase login, or exit when security_changed reports failed authentication
    - clean up based on pairing callbacks

Related