This post is older than 2 years and might not be relevant anymore
More Info: Consider searching for newer posts

Update passkey after bonding

Hello,

I would like to know the best practices to update a passkey for bonding.

For the moment, I have a static passkey that I set during ble initialization and I can bond to my device with the default password "123456". I have a characteristic with MITM secure access to save a passkey. After bonding, I can set this characteristic.

I would like to take this value and then set a new passkey. During the initialisation I used this function sd_ble_opt_set(BLE_GAP_OPT_PASSKEY, &sOpt); to set my key.

My question is how update this key with the new value. I need to set the value after disconnect or I can do this during connexion. I test to recall the function sd_ble_opt_set with the new value but doesn't work.

Parents
  • Hi Konova,

    I'm having trouble understanding what you really want to do. Why do you want to change the passkey? What are you actually trying to protect against? Depending on this, there are multiple answers to your question.

    First of all, once a bond has been established, you should not need the passkey again until the bond is considered lost. If you ever want to connect to only one device, you can simply disallow bonding altogether once a bond exists, and allow the user to delete the bond through a physical operation (e.g. keypress).

    Secondly, setting the passkey should be done before connection initiation. This can be solved by generating a random number and storing it in RAM or flash. You can also let the peer write to a special characteristic to change the default static passkey. To permanently store this, you need to store it in flash.

    But if your concern is to protect against sniffing, you should not use legacy pairing at all - unless you are using the OOB mode. Best practice is to use LE Secure Connections, and to have some way to exchange data, like keyboard/display/NFC. When you use legacy pairing with "Just Works", the temporal key (used to derive the session key, which encrypts during bonding information exchange) is all zeros. If you use a passkey, it is all zeros except 6 ASCII codes at the end, all between 0-9. That doesn't take much computer power to brute-force, so if someone sniffs the bonding procedure they can trivially sniff future connections too. But if the bonding happens in secret or in a secure way, the long-term key used has high enough entropy to be secure.

    To put it simple, adding a passkey makes little difference to a passive sniffer, when using legacy pairing. It does protect against accidental connections, if you make sure that all your devices have different passkeys. Best practice for security is to use LESC.

Reply
  • Hi Konova,

    I'm having trouble understanding what you really want to do. Why do you want to change the passkey? What are you actually trying to protect against? Depending on this, there are multiple answers to your question.

    First of all, once a bond has been established, you should not need the passkey again until the bond is considered lost. If you ever want to connect to only one device, you can simply disallow bonding altogether once a bond exists, and allow the user to delete the bond through a physical operation (e.g. keypress).

    Secondly, setting the passkey should be done before connection initiation. This can be solved by generating a random number and storing it in RAM or flash. You can also let the peer write to a special characteristic to change the default static passkey. To permanently store this, you need to store it in flash.

    But if your concern is to protect against sniffing, you should not use legacy pairing at all - unless you are using the OOB mode. Best practice is to use LE Secure Connections, and to have some way to exchange data, like keyboard/display/NFC. When you use legacy pairing with "Just Works", the temporal key (used to derive the session key, which encrypts during bonding information exchange) is all zeros. If you use a passkey, it is all zeros except 6 ASCII codes at the end, all between 0-9. That doesn't take much computer power to brute-force, so if someone sniffs the bonding procedure they can trivially sniff future connections too. But if the bonding happens in secret or in a secure way, the long-term key used has high enough entropy to be secure.

    To put it simple, adding a passkey makes little difference to a passive sniffer, when using legacy pairing. It does protect against accidental connections, if you make sure that all your devices have different passkeys. Best practice for security is to use LESC.

Children
  • Hello, Thank you for your reply. I have a device with no screen or keyboard so i set a défault static key "123456". My question is how i can changed this passkey after bonding. I create a characteristic to save the new passkey but i don't know how i can update with the new passkey for future bonding.

  • Create a custom characteristic, and when a write is sent to it, filter out that write event. Do some sanity checking (must be only numbers, in ASCII, 6 characters), then write it to a flash page. Whenever you are about to start to advertise/connect, read the value from flash and call sd_ble_opt_set() just like you do now. To store to flash, you could just erase and write on your own through the flash API, or try to make use of the Pstorage module if you intend to store more data later.

    The other points about the security still stands though. A static passkey adds very little security over non-MITM protected connections.

Related