Bluetoothctl without any user interaction - linux

Right now I can successfully pair and connect a phone to my machine without any user interaction in this way:
$bluetoothctl
#power on
#discoverable on
#pairable on
#agent NoInputNoOutput
#default-agent
from my phone I search for the BT device and it pairs and connectly automatically. Now I have two problems:
it still asks to authorize services:
Authorize service
[agent] Authorize service 0000110e-0000-1000-8000-00805f9b34fb (yes/no):
but this is not good because I've specified NoInputNoOutput!
how to trust a device? It's enough to type trust but I need to do this automatically for the same reason.
In general, is there any reliable C++ library to handle bluetooth connections and common profiles like A2DP and HFP?

I used bt-agent with NoInputNoOutput capabilities and that didn't ask for any permissions for A2DP and HFPprofiles.
bt-agent --capability=NoInputNoOutput
check the link for more details.
https://www.kynetics.com/docs/2018/pairing_agents_bluez/

Related

Setup password on a Bluez BLE beacon

I am running a BLE beacon in bluez5.52 on a linux machine(ubuntu 14.04) using the default gatt-service and the beacon using the btmgmt provided in the tools folder. Following are the commands I run to setup the beacon:
Terminal 1:
./gatt-service
Terminal 2
sudo ./btmgmt
add-adv -u 180d -u 180f -d 080954657374204C45 1
I am easily able to connect and disconnect with the beacon using BLE scanner app in android.
What I would like to do is setup a password for the beacon so that I am the only one who can connect to it. So far I have been unable to find any resources online that could help set that up. I have a decent understanding of the btmgmt and gatt-service code. I am looking for direction on what part of bluez code to look for to set up the password protection. Any leads, pseudo-code or partial code would help a lot.
Emil already mentioned pairing and bonding in the comments. This would definetly serve your purpose as you would be able to control who could connect to your peripheral.
A BLE characteristic can ask a connected device to authenticate before reading or writing which would result in a 'insufficient authentication error' if the device is not paired to your peripheral. A Android app is able to handle this error by displaying a pairing popup depending on the used pairing method.
So it is possible to have characteristics without security right next to one's that require pairing.
In case you still want to implement something like your mentioned password safety you should look into a 'authorized read'.
A characteristic which requires authorization first receives a read request and you can allow or deny it based on your own requirements. That means you can authorize yourself by sending a password to one characteristic and afterwards allow a read request on another characteristic. This would be even easier if you only accept one connection at a time.

Requiring/Implementing Bluetooth PassKey PassCode on Client Device

Is there a way in iOS or Android to set up a Bluetooth passkey passcode whenever another device wants to connect to my device via Bluetooth?
My application involves a BLE client connecting to a BLE server and the two devices will transmit data between each other. However, the data transmitted will be very sensitive security-wise. So beyond the standard encryption my goal is to not initiate data transmission until both devices have authenticated each other (e.g., with a passkey).
It seems like a Bluetooth passkey is something set up by the device manufacturer and not something able to be configured by the user. If so and there is no passkey pairing, would an acceptable alternative be to require a passkey to be exchanged (after the devices are paired) before the devices can transmit any sensitive data?
On a Android phone, assuming the phone is GATT server (which provides data for a client device to read), you can safeguard that data held in a characteristic by setting its read permission to PERMISSION_READ_ENCRYPTED_MITM .
For example, when you create a characteristic to be registered with the Bluetooth stack in Android, you do
BluetoothGattCharacteristic characteristic = new BluetoothGattCharacteristic(YOUR_UUID, BluetoothGattCharacteristic.PROPERTY_READ, BluetoothGattCharacteristic.PERMISSION_READ_ENCRYPTED_MITM)
In this way, anyone who wants to read the characteristic needs to create a secure bonding with your phone first, either by entering a passcode or compare two numerical values. The exact way for pairing is up to the Bluetooth stacks of both devices to negotiate (based on available IO on the client).
On the other hand, if the data you want to access is stored in a third remote device, and you don't need authentication (bonding/pairing) to read from it, and you cant access the firmware. Then you can not enforce secure transmission unilaterally from your phone.

Enforce bluetooth security and authentication using BlueZ

I'm using BlueZ 5.49 and trying to connect, pair, and pass information between two different bluetooth devices.
It's seems like i have problem with enforcing security and authentication between the two.
I'm configuring each hci device with:
hciconfig hci0 pscan auth encrypt which as i read, is setting the device to security mode 3.
In addition i'm creating manualy this path in both sides: /var/lib/bluetooth/<local_bdaddr>/<remote_bdaddr>/info with LinkKey.
I've noticed that if i'm creating the path for only one device, and then trying to connect using rfcomm connect from the device without the infofile, the connection succeed, even though the device is lacking the info file which containts the LinkKey.
If i'm trying rfcomm connect from the device with the info file i'm getting Key Exchange Error, which is acceptable since the other device doesn't have the key.
My base line is that it seems that security and authentication are not enforced.
Many Thanks,
Liad
Apparently hci device is by default set to work in Secure Simple Pairing also known
as sspmode. Simple Pairing originaly generated to support devices that can't insert pin code during pairing process (such as headset).
Hence when a device is in sspmode enabled, it use a default pin key - say 0000, and then based on the pin, generating LinkKey to encrypt and authenticate, and thus not truely enforcing authentication as i mentioned before.
The line hciconfig hci0 sspmode disable is disabling the Secure Simple Pairing mode, and finally enforce authentication using the static LinkKey you supply
in the info file which located in /var/lib/bluetooth/<your_mac>/<remote_mac>/info.

GATT client not working on BlueZ 5.19

I'm trying to get a GATT client working on a Linux system that's running BlueZ 5.19. Unfortunately, neither Python or glib are available on this system, so my only choice is using libdbus. And did I mention that I've never used D-Bus before? I have a GATT server on another system that provides and advertises a custom service by its 16-byte UUID. I'm trying to get my BlueZ-based system to access this service. I've verified that I can discover the server by the UUID that it advertises, and I can get BlueZ to connect to it. My client app has successfully called Bluez's RegisterProfile method, passing the UUID advertised by the server, but BlueZ never calls my NewConnection method. In the options of the RegisterProfile call, I'm setting "Role" to "client", "AutoConnect" to TRUE, and both "RequireAuthorization" and "RequireAuthentication" to FALSE. I am running bluetoothd with the -E (experimental) option.
If I run bluetoothd in the foreground with both the -E and debug option, this is what I see when I start my client app:
bluetoothd[2126]: src/profile.c:register_profile() sender :1.20
bluetoothd[2126]: src/profile.c:create_ext() Created "myRemoteControlProfile"
bluetoothd[2126]: src/profile.c:ext_device_probe() myRemoteControlProfile probed with UUID 119649b6-b656-22ae-e611-ba85a04effc5
bluetoothd[2126]: src/service.c:change_state() 0x950d0: device 24:71:89:09:AD:09 profile myRemoteControlProfile state changed: unavailable -> disconnected (0)
"myRemoteControlProfile" is the name of the profile I registered with Bluez, "119649b6-b656-22ae-e611-ba85a04effc5" is the UUID that I passed in the RegisterProfile call and 24:71:89:09:AD:09 is the GATT server I'm trying to interact with, so BlueZ seems to know that this remote device provides the service I'm looking for. When I watch on the server device, I never see BlueZ connecting to it. Isn't BlueZ supposed to connect to a device when it sees that the device offers the service that I passed in RegisterProfile? Why don't I get a NewConnection method call? What does it mean that my registered profile never gets past the "disconnected" state? I know that the GATT API was still considered experimental in BlueZ 5.19; should I even expect this to work? Thanks!
BTW, this problem is nearly identical to the one described in https://stackoverflow.com/questions/36480516/bluez5-37-org-bluez-profilemanager1-registerprofile-cant-detect-green-throttle . Unfortunately, no answers were offered there.
I've been able to work around this problem by upgrading to BlueZ 5.43. I still don't get a NewConnection method call, but if I detect the remote device by the UUID of the service it advertises and connect to it manually, all of the characteristics of the service now appear when I do GetManagedObjects on org.bluez, which didn't happen in BlueZ 5.19.

Can the Host provide the link key to the Controller with Bluetooth?

I was wondering whether the Host can provide the Link Key to the Controller with BR/EDR Bluetooth, and Bluetooth Low Energy (BLE). (v4.2)
The BT Core Spec v4.2 says:
7.1.10 Link Key Request Reply Command
Command OCF Command Parameters Return Parameters
HCI_Link_Key_Request_Reply 0x000B BD_ADDR, Link_Key Status, BD_ADDR
The Link_Key_Request_Reply command is used to reply to a Link Key
Request event from the Controller, and specifies the Link Key stored
on the Host to be used as the link key for the connection with the
other BR/EDR Controller specified by BD_ADDR. The Link Key Request
event will be generated when the BR/EDR Controller needs a Link Key
for a connection.
Source:
Bluetooth Core Specification v4.2
> Vol 2: Core System Package [BR/EDR Controller volume]
>> Part E: HOST CONTROLLER INTERFACE FUNCTIONAL SPECIFICATION
>>> 7.1.10 Link Key Request Reply Command
It seems to be only valid for BR/EDR (Classic Bluetooth) and not for Low Energy. However, the spec is not very well written and it might be that this part was not updated to imply a compatibility with BLE. Moreover, I can't simply use this command to make the Host send a Link Key to the controller; the controller must send a HCI_Link_Key_Request before.
Hence my question:
Can I make the Host provide the Link Key to the Controller for BR/EDR and BLE?
The HCI command you mentioned is used for BR/EDR. This is used only for authentication after the pairing was successfully done before. so once two devices are paired , on connection depends on the security Mode ( assuming security Mode 4 level 4), does a mutual authentication , This involves the controller asking the Host for the linkkey stored in the host earlier. The HCI command you mentioned is used to supply this linkkey stored in host back to controller. if the host doesn't have a linkkey then the host issues a HCI_Link_Key_Request_Negative_Reply this results in a failure on the initiator with Key or PIN missing error code.
in case of LE HCI_LE_Long_Term_Key_Request_Reply is used for the same purpose.
on your question about whether it is able to provide the linkkey without beeing asked for it , for BR/EDR you can use HCI_Write_Stored_Link_Key, but this is generally not very useful as on turning off bluetooth, the controller forgets the linkkey. on LE there doesn't seem to have an equivalent HCI interface.
Link key cannot be provided by host to controller, on authentication procedure, link key will be generated by controller and send to host(link key is generated using lot of parameters, please check BT Spec)

Resources