Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Consider removing CONFIG_BT_FIXED_PASSKEY #36005

Open
Emill opened this issue Jun 7, 2021 · 12 comments
Open

Consider removing CONFIG_BT_FIXED_PASSKEY #36005

Emill opened this issue Jun 7, 2021 · 12 comments
Assignees
Labels
area: Bluetooth Host area: Bluetooth Enhancement Changes/Updates/Additions to existing features

Comments

@Emill
Copy link

Emill commented Jun 7, 2021

Consider removing CONFIG_BT_FIXED_PASSKEY

In #9169, an option CONFIG_BT_FIXED_PASSKEY was added to allow a fixed / static passkey to be used instead of a unique randomized one for every attempt, without a real discussion on what security implications this has.

But this is not in line with the specification. The SMP spec lists only two cases for the passkey. The first is that the user enters the same passkey on both devices. The other is that one device generates it. The spec also mentions explicitly that a static passkey should not be used due to security. (section 2.3.5.6.3). There is a very strong reason for this, which in my opinion makes me think that the word in the spec's clarification should really be "must" rather than "should".

The LESC passkey protocol is not a PAKE (password authenticated key exchange) algorithm. It's an ad-hoc "gradually disclosure" protocol with 20 iterations, one per bit in the passkey. This protocol has an important difference to a PAKE, which is that it is only secure as long as the passkey is random for every new attempt.

The protocol, in a simplified non-technical way, works more or less like this:
For every bit in the passkey:
Each party writes the bit, as well as the two public DH keys on a sign, holds it up in the air but with a cover on it so no one can see what's written on it. Next, when both signs are clearly up, both parties remove the cover and they both confirm that the content on the other's sign matches the expected values. If anything is wrong, the protocol is aborted. Otherwise, after all iterations, the DH keys are used to create a shared secret.

If an attacker doesn't know the passkey, it's clear that the protocol will be successful only with a probability of one in a million. But, note that

  1. An eavesdropper will see the passkey used.
  2. An attacker guessing the passkey learns after each attempt exactly which is the first bit that is incorrect. This means it takes on average 10, at most 20, attempts to "crack" the passkey, if it is always reused.

For these two reasons, the protocol can only be deemed secure if the passkey is randomly re-generated for every new attempt.

Due to this, using a fixed passkey is only slightly more secure than the Just Works method. On the other hand, by allowing fixed passkeys, the implementer or end user will get a sense of false security, since they might think the protocol is more secure than it actually is. That's why I simply recommend to remove this option. (And also since the spec doesn't list fixed passkey as a valid option)

Ironically, using a fixed key in the LE legacy pairing protocol could in a way be treated as more secure than the LESC protocol, since 2. above doesn't apply there, so the attack scenario of an attacker trying to "log in" to a responder device would take up to a million attempts by brute forcing.

Further reading: https://devzone.nordicsemi.com/f/nordic-q-a/35856/questions-about-lesc-mitm-and-passkey/138216#138216.

@Emill Emill added the Enhancement Changes/Updates/Additions to existing features label Jun 7, 2021
@carlescufi
Copy link
Member

carlescufi commented Jun 7, 2021

Thanks for the input @Emill. We have some Kconfig options that are inherently dangerous, and we warn the user when building the image. The particular warning for this one can be foud here, displaying the following:

A fixed passkey is easy to deduce during the pairing procedure, do not use in production.

There are several others that are even potentially even more dangerous, like for example the ability to use debug keys. Those are there mainly for debugging.

@Emill
Copy link
Author

Emill commented Jun 7, 2021

Right, I didn't notice that warning, which was apparently added recently. It's good that it's there :)

But when reading through the description and the comments at #8350, it is apparent that noone understood the security implications of this, since the reason for adding this was to get an extra "feature" to be able to get MITM security on devices that don't have a display/keyboard, and not to get an extra debug feature.

If you would have been aware of this issue in the first place, would the feature have been implemented at all?

The reason that debug key option exists is on the other hand very good for debugging, if you use an air sniffer for example and want to debug/decrypt the traffic. I guess people also understand the security implications of this, that it will be unsecure due to a publicly known key.

On the other hand, I see very little use for debug purposes for fixed passkey. Just use Just Works during debugging or something, if it's annoying to enter the passkey? Implementing a whole different flow just for an insecure debug feature, that probably might be left on during production somewhere since people don't understand the implications, that seems to be a bigger risk.

If you really want to keep the feature, better call it BT_FIXED_PASSKEY_FOR_DEBUG or something, and clearly state in the Kconfig that this option must only be used for debugging purposes since it's completely unsecure since the passkey is revealed after every attempt. The Kconfig file currently doesn't mention the security implications at all.

Just my two cents...

@carlescufi
Copy link
Member

@Emill You raise good points, but there might still be valid usecases for this feature in certain domains. Without going into specifics, suffice to say that we have had multiple requests for this in the past with descriptions that were convincingly well conceived. I will send a PR trying to clarify the risk implications of the Kconfig option and copy you there.

@Emill
Copy link
Author

Emill commented Jun 7, 2021

Great!

Would you mind sharing the convincing descriptions, or use cases?

@joerchan
Copy link
Contributor

@Emill It's probably related to older use-cases, before LESC was introduced. In the Legacy pairing procedure a random passkey isn't all that much better than a fixed one. Since the passkey is used as the temporary encryption key in that case then brute-forcing the encryption key in order to get the LTK wasn't that hard. The workaround for that case was to simply turn the TX power all the way down and ask the user to hold them right next to each other, so that the connection cannot be listened in on (or atleast not the peripheral side, since it sends the LTK).

@jefffhaynes
Copy link

I'm not following this. Say you have a peripheral with no screen (e.g. a lightbulb) and you want to prevent random devices from connecting to it. Wouldn't the only way be to put a code on the bulb and have the user enter the code into the central (e.g. phone)? And in this scenario, I don't see how that's possible without a static key. Is there a better approach to this use case that I'm missing?

@Emill
Copy link
Author

Emill commented Jan 8, 2022

@jefffhaynes You are absolutely correct. Using a static passkey like this is exactly what for example Homekit and the upcoming Matter does to ensure "random" devices (i.e. devices controlled e.g. by a hacker standing outside the house) from pairing with it and at the same time ensure authenticated encryption. Algorithms solving this in a secure way are called PAKE (password-authenticated key agreement).

The problem is just that Bluetooth does not support such a protocol, so unfortunately you can't, at least not if you want to use built-in Bluetooth security (Homekit and Matter do not use Bluetooth security). The LESC passkey protocol is like, imagine standing in front of a locked door with a PIN pad, simplified with only digits 1 and 2. For every attempt, a green LED will light up if you pressed the right next key and a red LED will light up if you pressed the wrong next key, so you will have to restart from the beginning. It doesn't take that long to figure out the correct code, even if it is 20 digits long. But if the code changes after every attempt, you will most likely be locked out for a long time since it's one in a million you'll enter the correct code.

Unfortunately people don't understand security and Bluetooth SIG isn't the best about communicating. In the same way Bluetooth stacks aren't (usually) built and designed by people who have security on their CV. That's why people (both device manufacturers and Bluetooth stack designers) think they can (mis)use the "one device generates a random passkey and shows it on a display, the user inputs this passkey on the other device" protocol, replace the random passkey like this xkcd with a static one and believe this is secure.

Lately this good article has popped up: https://insinuator.net/2021/10/change-your-ble-passkey-like-you-change-your-underwear/. It explains quite thoroughly why the protocol is completely broken if you replace the random passkey with a static one and includes a proof of concept.

If only Bluetooth SIG had chosen a PAKE instead from the beginning instead of their ad-hoc protocol, we wouldn't have this situation...

@jefffhaynes
Copy link

Ah interesting, I didn't realize it was so broken. Reminds me slightly of the OpenSSL padding vulnerability. I think the static key will have to suffice for our purposes but a shame they keep mucking these things up.

@rweather
Copy link

rweather commented Feb 9, 2022

Here is a use case for simple pin or passkey authentication.

The company I work for makes equipment that is mounted on electricity poles and operates on power lines that are energised to 15kV or more. We're looking at using Bluetooth to allow checking of device status, configuration of options, and so on by a technician performing maintenance or resolving a fault. There will be higher-level user authentication using TLS over the link to ensure good security, but establishing the Bluetooth link is the first step.

Requiring that a technician climb the pole to type a passkey on a keypad or to press a "pairing allowed" button on the side of the device can be be dangerous. Like dead and in a coffin dangerous. Technicians generally want to avoid climbing the pole unless the issue cannot be resolved from the ground; e.g. by transmitting a close command to a device that has tripped out on a fault.

I'm currently using bt_passkey_set() to set the default pin, as CONFIG_BT_BREDR is not working for me at the moment in my microcontroller for some reason (Nordic nRF5340). If there is some other method than "Just Works" to pair a Bluetooth device without physical access to both ends of the connection, I'm all ears.

@Emill
Copy link
Author

Emill commented Feb 9, 2022

If you use TLS or something else for the real security which satisfies your security requirements, over a BLE link, then there is not much of a point to establish Bluetooth security, so I don't really understand what you would like to solve here by adding BLE security. With BLE you can communicate without devices being paired.

@rweather
Copy link

rweather commented Feb 9, 2022

It's another layer for curious onlookers to get through, as opposed to serious attackers. "Oh look, there's device called ABC in range of this bus stop - I wonder what that is?". "Pairing failed". "Oh well, bus is along soon anyway".

@Emill
Copy link
Author

Emill commented Feb 9, 2022

Any curious person could still connect to it and perform a service discovery and inspect the GATT db which might be fun. This does not require pairing, even if pairing is implemented...

If you really want to avoid people connecting to it you should use the filter accept list to only allow connections from certain centrals.

If you otherwise just want an extremely simple wall layer to keep away curious people, I suggest you to have one characteristic you must first write a "passkey" to unlock the rest of the functionality of the device. Security wise this is similar to static passkey pairing with the Legacy pairing method, for example if an attacker eavesdrops during the connection.

@joerchan joerchan removed their assignment Jun 16, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
area: Bluetooth Host area: Bluetooth Enhancement Changes/Updates/Additions to existing features
Projects
None yet
Development

No branches or pull requests

7 participants