Page 1 of 2

More secure Bluetooth LE pairing method

Posted: Mon Jun 17, 2024 1:00 pm
by eriksl
For BLE I am now using a pincode which is transferred "out-of-band" from the peripheral/server = ESP32-S3 to the central/client = Linux host and this works.

The problem is the pin code can only be 5 digits long. That is really far to short for a device that's in general reach (even outdoors) to be secure.

I tried various other methods, including a passphrase (which I'd like to use), but it doesn't seem to be supported by either Nimble, ESP-IDF or BLE, is that correct?

The only other solution I can think of is having the client authenticate itself after pairing, but that's really inconvenient, I'd rather avoid that.

Suggestions?

Thanks!

Re: More secure Bluetooth LE pairing method

Posted: Tue Jun 18, 2024 6:25 am
by Linetkux Wang
I am afraid that you may still choose to use some special attribute for second-step auth.
Here is my sugguestion:
For enhancing the security of your BLE setup, you can implement a mechanism using a special attribute that must be written with a correct session key or similar password. This attribute acts as a security gatekeeper, ensuring that all other attributes can only be read or written after the correct key has been provided. Here's a basic outline of how you can implement this:

Define a Security Attribute: Create a new attribute in the BLE GATT table specifically for storing the session key or password.

Set Access Permissions: Configure this attribute to be writable. The other attributes should only be accessible if the correct session key is present in this security attribute.

Add Security Checks: Before allowing read or write operations on other attributes, check if the correct session key has been written to the security attribute.

Implement Security Logic:

After pairing, the client must write the correct session key to the security attribute.
Once the correct key is provided, the server will permit normal operations on other attributes.
Here's an example using the ESP-IDF framework to illustrate this approach:

Code: Select all

// Define the security attribute UUID
#define SECURITY_ATTRIBUTE_UUID 0xFFF1

// Function to handle writes to the security attribute
void handle_write_security_attribute(uint8_t *value, uint16_t length) {
    if (is_correct_key(value, length)) {
        // Enable access to other attributes
        enable_other_attributes();
    } else {
        // Deny access to other attributes
        disable_other_attributes();
    }
}

// Function to check if the provided key is correct
bool is_correct_key(uint8_t *value, uint16_t length) {
    // Define the correct session key (example: "12345")
    uint8_t correct_key[] = { '1', '2', '3', '4', '5' };
    if (length != sizeof(correct_key)) {
        return false;
    }
    return memcmp(value, correct_key, length) == 0;
}

// Function to enable access to other attributes
void enable_other_attributes() {
    // Logic to enable other attributes
}

// Function to disable access to other attributes
void disable_other_attributes() {
    // Logic to disable other attributes
}


Re: More secure Bluetooth LE pairing method

Posted: Tue Jun 18, 2024 9:09 am
by eriksl
Yeah, I was afraid of that. I was hoping I simply didn't read the documentation well enough.

When going this route, I will proceed a bit differently, please let me explain (if you're interested).

My firmware is accessible for commands over wifi (tcp and udp), bluetooth and console (USB-C). For all three I am using a generic input/output processing procedure which allows to choose between a pure ASCII approach and a packetised approach. The first is very convenient for wifi if you only have telnet or netcat at your disposal. It would also be required when the layout of the packet format would need to change (which hasn't happened yet though). Also it's convenient for console access so you don't have to type in hex codes for packet fields :D On the other hand the packetised format has some great advantages, like knowing the length of the total packet in advance, which makes defragmentation (udp) / desegmentation (tcp) and reassembly (bt) a lot easier and more robust. It also can have a checksum of the payload and some other metadata.

So that is why I am allowing both at the moment.

The alternative approach would then be
- disallow raw ASCII access for bt (no sense in this, because you'll need a specialised client program anyway)
- include a field for a passphrase into the packet header so every packet is authenticated
- the payload could optionally be encrypted using this passphrase

I am considering dropping pairing security altogether in this case, because it wouldn't add much security, just complexity. I'll have to dig into the docs whether that is possible.

Re: More secure Bluetooth LE pairing method

Posted: Tue Jun 18, 2024 9:13 am
by eriksl
Having said that, I think your approach is interesting too, because it's much more simple. The only thing is that one would need to disable access at some point too. Maybe attach it to the disconnect event?

Re: More secure Bluetooth LE pairing method

Posted: Tue Jun 18, 2024 1:32 pm
by Linetkux Wang
Glad this will help, and according to your description, I think you may put the gatekeeper code to enable/disable BLE passage just before the final input function.

+---------+
| BLE |
+---------+
|
v
+----------------+
| Gatekeeper |
+----------------+
|
v
+-----------------+
| Service Handler |
+-----------------+

+-----------+
| Ethernet |
+-----------+
|
v
+-----------------+
| Service Handler |
+-----------------+

+---------+
| Wi-Fi |
+---------+
|
v
+-----------------+
| Service Handler |
+-----------------+

Re: More secure Bluetooth LE pairing method

Posted: Fri Jun 21, 2024 7:01 am
by eriksl
Actually I already implemented it yesterday :D

The wifi and console do not need to be protected, just the BT input function.

I was thinking of a challenge-response system so anyone eavesdropping will never see the same key. But for the sake of simplicity and because the pairing has already been completed at this point, making the connection encrypted, I opted for another approach where the mac address is encrypted using AES, using a static key and static IV. Not very secure but at least better than a static password.

If you haven't authenticated properly, the BT "write attribute event" handler just drops the input, so it won't spend any time on processing it. I am happy for the moment. Maybe I'll implement a challenge handshake protocol later.

Still I think it's amazing (in a bad way) that Nimble doesn't support pairing with a proper passphrase.

Re: More secure Bluetooth LE pairing method

Posted: Fri Jun 21, 2024 7:02 am
by eriksl
eriksl wrote:
Tue Jun 18, 2024 9:13 am
Having said that, I think your approach is interesting too, because it's much more simple. The only thing is that one would need to disable access at some point too. Maybe attach it to the disconnect event?
BTW I was talking about revoking the access when the client goes away (so a new client needs to authenticate again). I've implemented it in both the "connected" en "disconnected" events (to be sure) and I think it works well.

Re: More secure Bluetooth LE pairing method

Posted: Wed Jul 10, 2024 11:49 am
by MikeCode
I came across this post as I also need a method to make NimBLE secure for unauthorized access.

Currently everyone within reach of my ESP32-S3 is able to connect and manipulate my ESP32-S3 NimBLE application.

Is there a way to allow pairing only once for 30 seconds only after pressing a button? So that paring is only possible within these 30 seconds and after the device has paired successfully no other device can pair to the EP32-S3?

Isn't there a common way to protect BLE devices from being connected without permission?

I would expect there must be a recommended way to handle this security issue.

Re: More secure Bluetooth LE pairing method

Posted: Wed Jul 10, 2024 3:07 pm
by eriksl
What I know of it:
- BLE does allow for keyed pairing, like Bluetooth Classic does
- it actually does work too, I have been using it
- the main problem is that Nimble only allows for the "simple" authentication schemes, where an pin code is used of just 5 integer digits
- a 5 digits pin code is far too weak for a system that is continuously available

I am using BT for rescue access whenever the Wifi doesn't work for whatever reason, so it needs to be on all of the time anyway.

When pairing is started and also when a connection is made, a callback function is called. I am quite certain you can deny access at that point, for example because some other door-knocking mechanism hasn't been activated (like a physical button), by returning a non-success return value.

Another way would be, which I did, is to always allow pairing and also always allow connecting, but to require to do a secret handshaking thing on a separate GATT service, after connecting. Until that succeeds, simply ignore everything that is sent on the main GATT service.

Re: More secure Bluetooth LE pairing method

Posted: Thu Jul 11, 2024 7:33 am
by MikeCode
Thanks for your elaboration!

Your method of using a secret handshake after connection is a feasible workaround but isn't there a problem, that when somebody has paired with your device before, you cannot connect to the device because it is already paired?

It's hard believe that there is no out-of-the box implementation for security in BLE as this is always needed for any device.

Normally you have to press a button on the device to enable pairing for 30 seconds. And after these 30 seconds the device is not visible any more so that nobody else can connect.

Somewhere I read about bonding:

"Bonded devices automatically establish a connection whenever they're close enough. When I start up my car, for example, the phone in my pocket immediately connects to the car's Bluetooth system because they share a bond. No UI interactions are required!

Bonds are created through one-time a process called pairing. When devices pair up, they share their addresses, names, and profiles, and usually store them in memory. The also share a common secret key, which allows them to bond whenever they're together in the future."

So bonding the BLE device should be the needed way to go?