iOS SMP Pairing Request doesn't set SC Bit - ios

I'm using an iPhone XR to connect to my Linux 4.9 / Bluez 5.50 peripheral and want to use Bluetooth 4.2's Secure Connection pairing.
On my device, there are a couple of characteristics that require authentication, the agent for pairing is set up as "DisplayYesNo". After discovering the services and characteristics on the iPhone, I read a characteristic for the first time. As expected, a Bluetooth Pairing dialog pops up, but instead of asking me to compare numbers, I have to enter a passkey (that I show on the peripheral's display).
With btmon on the Linux side, I can see that after the "Insufficient Authentication" response from Linux, the iPhone sends a SMP Pairing Request, but doesn't set the SC bit. Everything works consistently, but I would have expected the iPhone to initiate pairing with SC enabled.
There is a rather brittle way to run the pairing with SC enabled: After the connection is established, Bluez' "battery" plugin runs on the Linux side, discovers the "Battery Service (0x180f)" on the iPhone and tries to read its characteristics. The iPhone responds with an Insufficient Authentication error by itself, Linux (as peripheral) sends an SMP Security Request with the SC bit set and then the iPhone issues a SMP Pairing Request with the SC bit set resulting in numeric comparison on both ends and public key exchange etc.
I can now "force" this second behavior by putting an arbitrary delay (3 seconds...) into the iOS app right after the successful connection before starting service and characteristic discovery and reading characteristics. That way the SC pairing due to the battery plugin likely has already started before I try to read from the authenticated characteristic within the app.
shudder What can I do to improve that?

Related

The fastest way to connect to a known BLE device with firemonkey

the examples I have seen of BLE connection with Delphi / Firemonkey always start with a search for devices, then go to a service discovery to only then do the pairing.
This entire process takes about 5 seconds. I wonder if there is a faster way to connect to an already known device with known services and quickly send a command.

When does iOS display "need to bond" dialog?

I am writing an iOS app that communicates with a BLE device that we are developing. Most communication does not require bonding, but there are some secure features where bonding will be required. I've put those secure features in a separate service which has been flagged as requiring bonding, and when I try to access that service iOS correctly starts the bonding process.
The problem I'm having, is that I want to be able to control exactly when this bonding takes place so I can design my UI appropriately. Most of the time, iOS waits until I try to access the secure service before it starts the bonding process, but I have also seen the bonding dialog appear shortly after I call CBPeripheral.DiscoverCharacteristics() and long before I actually use the secure service for anything. The bonding dialog seems to appear later if I'm re-running the app when I've already bonded once and then deleted the bonding both in iOS and the remote BLE device.
I'm guessing that iOS is caching the service/characteristic information, so after the first connection when I call CBPeripheral.DiscoverCharacteristics() it's not actually communicating with the remote BLE device, and thus isn't triggering the need to bond.
There's a discussion about how to clear the bluetooth cache on OSX, but nothing similar for iOS. I've tried this:
Unbond device in iOS
Turn off Bluetooth
Turn off iPad
Turn iPad back on
Turn Bluetooth back on
But the bonding request dialog still comes later, which I'm guessing means the cache didn't actually get cleared.
If the devices are unbonded and the peripheral sends an SMP "Security Request", it will show the popup.
It also shows it when you try to interact with a protected characteristic.

iOS Bluetooth BLE security and "Just works" association model

According to this document and this whitepaper, there are security measures designed to prevent passive eavesdropping a Bluetooth BLE connection. Is there a way to implement the secure connection between an iOS central manager and a peripheral device?
Specifically, I'm looking to implement "Just works association model". I want to know if it is possible with an iPhone.
For BLE connections, iOS supports "Just Works" and also "PIN" based pairing.
For Out-of-band (OOB) pairing, there is no public iOS API (albeit a private one that Apple uses itself for Handoff amongst other things, to seamlessly pair two Apple devices without user interaction.)
Note that both "Just Works" and "PIN" pairing is somewhat broken. If an eavesdropper were to listen in on the initial pairing process, it could brute force the exchanged keys easily.
iOS 8.2 added support for BT 4.2, which includes various improvements for BLE pairing and security in general. I haven't looked what parts iOS 8.2 supports though.
To kick off pairing:
an app that is using the peripheral needs to be in the foreground (this can be iOS' Settings)
after connecting,
send the "Slave Security Request" command from peripheral side (see the Bluetooth Specification),
or,
access a "protected" characteristic on a service implemented either by the peripheral or by the app -- this will make iOS automagically initiate the pairing process if the device was not yet bonded. This is what Apple recommends.
EDITED:
According to the table under Step 4 in this link, because your Central (smartphone) has both Keyboard and Display, the only way to perform Just Works pairing is if the sensor has no input and no output capabilities.
So, to do that, you must configure the sensor to send a Pairing Response with the IO Capabilities set to NoInputNoOutput.
That will force the Central (your iOS device) to perform Just Works pairing.

Does bluez support low energy pairing with ios devices?

I have been beating my head on the wall with this project. I have an app built to an iPhone 5 that needs to communicate with my mac via bluetooth low-energy, and I want to do it through linux using the bluez protocol. I have my mac dual booted with ubuntu 12.04 and my iPhone app is connectible (acting as a peripheral), which I verified with lightblue. So, my question is, basically, is this possible? Will bluez support this type of connection, or will it only work if I use a dongle?
I have tried many different permutations of bluez. My linux kernel is 3.11.0. I think I am currently running bluez 4.98. I can get the hcitool to sense my app, then I use gatttool -b -I -t random which gives me the [ ][MAC.......][LE]>
then I type connect, I get
[CON][MAC.......][LE]> for about 15 seconds and then the CON goes away. That was the best I could do. Actually, at this point I'm not even getting that anymore. I'm getting any one of 3 errors. Either connection refused (111), could not create connection, or device busy (16).
Anyway, any help is appreciated!
Thanks.
To quickly answer your question, yes BlueZ DOES support pairing with iOS devices. That being said, the way Bluetooth Low Energy works is that you only need pairing if you want to perform an action on a characteristic (i.e. reading, writing, or enabling indications/notifications), and that characteristic requires pairing for that action to be performed. In other words, I think that the errors you are seeing are unrelated to pairing (since they occur before you do anything to the characteristics). I recommend that you try resetting the hci device with the command:
hciconfig hciX reset
Where hciX is the local hci device you are using.
If that doesn't work, try using #hcidump or #btmon to read the raw hci data and possibly get a clearer picture of what exactly might be happening.
If you want to make sure that you have a local hci device (and therefore meaning you wouldn't need a dongle), run the following command
hcitool dev
This should display the local hci devices. If the response is empty, that means that your Linux system is not using Apple's Bluetooth hardware, and that you probably need a dongle.
Also, watch out for other common errors, i.e. are you sure that your peripheral device is connectable, does it have proper implementation of services and characteristics, does the peripheral device have a random address (hence the -t random option?), are you sure you can see it from your linux machine (e.g. with the #hcitool lescan command), and if you are using the gatttool command correctly. There are a couple of good bluez questions on this site that might be beneficial to look at:
Using Bluetooth Low Energy from The Command Line
Bluetooth Low Energy Listening for Notifications/Indications
Raspberry Pi iBeacon Connection Timing Out
Attribute Requires Authentication Before Read/Write
Finally, when it comes to pairing, you have to increase the security level by passing "--sec-level=medium" or "--sec-level=high", e.g.
gatttool --sec-level=high -t random -b <MAC Address> --primary
or
gatttool -l high -t random -b <MAC Address> --primary
This should initiate the pairing process, and then result in a pop-window to appear asking you to accept the pairing request
I hope that this helps,

iOS DHCP Request

I have observed from a wireless packet capture in my home network that anytime my iPhone device switches from asleep to active, and it is not attached to a power source, it sends a DHCP Request. I have validated this behavior with two different iPhones (with different iOS versions). I have also tested an Android device and this does not happen.
Hence this makes me wonder why does an iPhone need to send a DHCP Request, once switched from asleep to active, if the DHCP lease has not expired? In addition, why doesn't this happen in an Android device?
I am pretty sure this is not an issue related to a bug, such as the one reported in
http://www.net.princeton.edu/apple-ios/ios41-allows-lease-to-expire-keeps-using-IP-address.html
If the device thinks it has an unexpired lease, and the device's network interface has just brought up physical LINK, then that the client should start in the DHCP INIT-REBOOT state (or even INIT state).
Alternatively, if the device thinks it has an unexpired lease, and has kept LINK up continuously since going to sleep, then the client could start in the BOUND state when awaking.
Basically the main reason that the devices react differently is the way they handle the sleep mode (most iOS will disable the wireless interface, whereas in Android it is configurable in the menu).

Resources