8 years ago.

BLE security and changing services dynamically

Hi, apologies in advance for long-winded question.

I'm developing a BLE device, based on the nRF51822, that has no IO capabilities, and is required to connect securely to any central that has the right credentials. The client doesn't want the user to enter a passkey through iOS in order to pair so we have to use the just works model, however, the device must be able to pair with multiple centrals (not simultaneously), and hide/encrypt sensitive characterisitics unless paired with an authenticated central.

My understanding of BLE security is that if the Just Works model is used, any central can connect, and pair with the device. As the device must be able to connect with multiple authorised centrals, we can't rely on normal 1 to 1, pairing-bonding to restrict access. This means an unauthorised central would be able to gain access to sensitive characterisitics. Even if I had a custom authentication over the top of BLE security, the unauthorised central would still be able to read the data, if not write.

To complicate matters, centrals are given authorisation by separate system and the BLE device doesn't know if a central is authorised until it starts pairing, so can't use whitelisting.

Can I introduce an authentication process between connection and pairing to prevent unauthorised access to characteristics?

I was thinking of having only a small subset of services visible, one being a custom authentication service. Once authenticated the rest of the services become visible. Is there a way of doing this without disconnect-reconnect, or indeed resetting BLE stack?

Another option is to have additional encryption for all characterisitics within the device, and only an authorised central will have the key. This seems wasteful and resource intensive given that the BLE link is already encrypted after pairing.

I also need to support FOTA, however it must be secure. Is it possible to set security on the DFU control point, so only authenticated central can trigger DFU update?

Thanks in advance Andrew

2 Answers

7 years, 12 months ago.

Hello Andrew,

Authentication and authorization are two orthogonal concepts in BLE.

Being authenticated doesn't mean that you gain access/authorization to everything on a GATT server and being authorized to do some operations on a GATT server doesn't mean that a device is authenticated.

I think you can introduce an authorization process once your device is authenticated and your link is encrypted.

Once you have a way to discriminate authorized from unauthorized link, it is possible to intercept read and write request by providing read and write authorization callback for your characteristics. You can register such callbacks by calling GattCharacteristic::setWriteAuthorizationCallback and GattCharacteristic::setReadAuthorizationCallback.

Accepted Answer

I must admit to only a working knowledge of top level BLE, so forgive the follow up, but if the BLE stack takes care of all the authentication, encryption and authorisation, where's the best place to insert another step in the process to introduce custom authorization, and does this also mean that no characteristic data is exchanged until device is authorised? Don't suppose there is already a simple callback for when device is authenticated and link encrypted, but not authorised?

Is there a way of introducing an authorization process after link is encrypted, that then allows access to characterisitics, without requiring individual read/write authorizations for all the characterisitics. Could I for example set a flag after device is authorized, and check that flag on each read/write request?

posted by Andrew Fox 30 Mar 2016

BLE stacks does not take care of authorization for you.

Authorization in BLE is fine grained. Authorization can be given by characteristic and by procedure. For instance, a client can be authorized to read a given characteristic but not t write it, another client can be authorized to read and write the same characteristic and another client can be unauthorized to read or write the same characteristic.

One common technique to authorize a client can be the following:

- Once the link is encrypted, the server will wait that the client register to indication from a specific characteristic in an authorization service.

- Then, the server will send a random challenge to the client.

- The client has to respond correctly to this challenge by writing to the characteristic otherwise it will be disconnected by the server and after several try will be blacklisted.

Once the client has responded correctly to the challenge, it is authorized to read and/or write characteristics.

That is just one way to do it, depending on your application it might not be the right solution but this is the general idea.

.

posted by Vincent (pan-) Coubard 30 Mar 2016

Vincent your suggestion sounds like exactly what I'm after. I had no idea that the server could specify security on a client by client basis. I have simply been setting read/write characterisitics and assumed that whichever client makes a successful pairing will have access to those chars.

I'm not clear on how to achieve what you suggest. Are these processes (or part of) built-in to the nordic/mbed stack, or do I neeed to implement from scratch? Would you please point me to starting point of determining when link is encrypted, and client has registered to receive notifications.

Thanks for your help.

posted by Andrew Fox 31 Mar 2016

Andrew,

These process are not part of the nordic stack nor BLE specification. It can be really tricky to bring security to device paired with the "just work" model.

You can use the API from the SecurityManager to handle link encryption. I strongly encourage you to look at it: https://github.com/ARMmbed/ble/blob/master/ble/SecurityManager.h

There is API to get the security state of a link, set the security of a link and also callbacks for when the security state of a link change.

If you want to catch when a client has registered to receive notifications/indications, you have to register a callback for such event by calling GattServer::onUpdatesEnabled.

posted by Vincent (pan-) Coubard 31 Mar 2016
8 years ago.

I think the easiest way of achieving this is by protecting the characteristics. For data that is written there already is `onDataWritten()`, where you can verify whether the device is authorized to do so, and for data read check out the answer to this question.

Hiding services is quite easy, just add them and don't advertise them. Device can still get them after GATT connect though, so you'll need to protect on characteristic level.