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

Add support for Pin and Passkey Entry pairing on Linux and Windows #523

Closed

Conversation

bojanpotocnik
Copy link
Contributor

@bojanpotocnik bojanpotocnik commented Apr 22, 2021

This PR currently contains multiple commits so it is easier to follow what changes has been made, will squash before eventual merge.

  • Tested on Ubuntu 20.04 using BlueZ 5.55 and 5.58 with device using Passkey Entry pairing
venv/bin/python passkey_pairing.py
Device AA:BB:CC:53:12:6D was unpaired
Pairing...
Provide pin (1-16 characters) or passkey (0-999999) for AA:BB:CC:53:12:6D, or nothing to reject pairing: 112233
Executing <Handle MessageBus._message_reader() created at /usr/lib/python3.8/asyncio/selector_events.py:257> took 6.043 seconds
True
Paired
<bleak.backends.service.BleakGATTServiceCollection object at 0x7f92886a3c40>
00001801-0000-1000-8000-00805f9b34fb (Handle: 6): Generic Attribute Profile
	 00002a05-0000-1000-8000-00805f9b34fb (Handle: 7): Service Changed
		Value:  bytearray(b'\x01\x00\xff\xff')
0000xxxx-0000-1000-8000-00805f9b34fb (Handle: 10): Private Service
	 xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx (Handle: 11): Char only accessible when paired
		Value:  bytearray(b'')

Process finished with exit code 0
  • Need to test on Windows in the following days and implement missing parts there
  • Cannot test on Core Bluetooth. Moreover, if the case is the same as on iOS, app cannot use custom pairing methods - pairing is always done by the system wizard and system dialog is used for entering the passkey.

@dlech
Copy link
Collaborator

dlech commented Apr 22, 2021

Just curious, what is the use case for this? To have unattended connections? Or for use on headless systems?

will squash before eventual merge.

Please don't squash all of this into one commit. Having individual commits for each small change is just as helpful to future code archeologist as it is to pull request reviewers.

@bojanpotocnik
Copy link
Contributor Author

Just curious, what is the use case for this? To have unattended connections? Or for use on headless systems?

All of them in fact. I use bleak for (semi)automated testing of BLE devices, and most of them use some kind of secure pairing - and in this group I do not count Just Works pairing, because it provides no authentication or confirmation at all.

Even if pairing with simple devices which have some preset 0000 or 1234 passkey, callback is required. - Oh, I get your question now: I could use bluetoothctl and system pairing dialog, but when developing BLE devices from 0 up, I need to re-pair device hundreds times a day. I have made totally custom D-Bus interface in the meantime (also tried to integrate it, but it was not possible with txdbus #218), but it is not async... and would really like to use bleak because is the best for everything else.

Also one other use case which is not possible with manual pairing at all: BLE device has some algorithm in the secure area, which generates TOTP tokens and belonging pairing passkeys. Such "TOTP" token is advertised in advertising data and changes every 10 seconds. Host needs to scan this token, send it via cloud API to the server (which is the only other location containing this algorithm) to get the matching pairing passkey, initiate pairing and use this passkey. Such thing is not possible to do manually.

Please don't squash all of this into one commit. Having individual commits for each small change is just as helpful to future code archeologist as it is to pull request reviewers.

I agree, but I will tidy them up (e.g. changes from last commit shall be rebased to the commits responsible for them). I've just read that in the contributing guidelines.

This agent currently does nothing, it just logs method calls to
check if it is properly registered.

Signed-off-by: Bojan Potočnik <[email protected]>
Also pairingAgent is moved to BleakClient class for easier access

Signed-off-by: Bojan Potočnik <[email protected]>
Also modify example to use this callback and retrieve passkey from the
user.

Signed-off-by: Bojan Potočnik <[email protected]>
Ensure that if no callback is provided, pairing works as before, meaning
that Just Works pairing requests are confirmed.

Signed-off-by: Bojan Potočnik <[email protected]>
Signed-off-by: Bojan Potočnik <[email protected]>
@bojanpotocnik bojanpotocnik force-pushed the develop-passkey_pairing_bluez branch from 45e3f75 to b30b7c2 Compare April 25, 2021 22:17
@asafs932
Copy link

asafs932 commented May 10, 2021

This PR currently contains multiple commits so it is easier to follow what changes has been made, will squash before eventual merge.

i tested the code with my esp32 device, on my linux system and can approve it worked good for me!
@bojanpotocnik do you know when a new version of bleak will be released with this content? or whats the process?
Thanks!

@hbldh is it possible to release a version with this content? if not public version then a private version package would realy appreciate it.

*forgive me about my duplicated questions about the release, i dont really know whats the process.

@bojanpotocnik
Copy link
Contributor Author

bojanpotocnik commented May 10, 2021

@asafs932 thank you for testing. I went to test this on Windows but develop (even base, not this PR) branch throws some other unrelated error, but I did not have time to debug any further. I can this and then next week.

I think that this needs some more thinking for actual release. And there is a problem with CoreBluetooth - as far as my iPhone experience goes, pairing is handled by the system and you cannot provide the passkey using custom code. So even if this code is added, it will never work on CoreBluetooth (I hope that someone can correct me). In any case, I do not own any CoreBluetooth device to test.

I can tidy it up and implement it for Windows in the next few days, remove Draft label and then wait for any additional comments and feedback. Or, if we are OK with some feature being supported only on one platform (Bluez), I can ignore Windows for now and do it faster.

@asafs932
Copy link

asafs932 commented May 10, 2021

@asafs932 thank you for testing. I went to test this on Windows but develop (even base, not this PR) branch throws some other unrelated error, but I did not have time to debug any further. I can this and then next week.

I think that this needs some more thinking for actual release. And there is a problem with CoreBluetooth - as far as my iPhone experience goes, pairing is handled by the system and you cannot provide the passkey using custom code. So even if this code is added, it will never work on CoreBluetooth (I hope that someone can correct me). In any case, I do not own any CoreBluetooth device to test.

I can tidy it up and implement it for Windows in the next few days, remove Draft label and then wait for any additional comments and feedback. Or, if we are OK with some feature being supported only on one platform (Bluez), I can ignore Windows for now and do it faster.

@bojanpotocnik thanks for the fast response and the kind explanation.
just my opinion - if we know that on linux +Bluez its working, maybe release this functionality for linux faster and do a 2nd PR that adds support for windows?

btw this is the pop up that asked me for the passkey entry:
image

@bojanpotocnik
Copy link
Contributor Author

Do I assume correctly, that you did not provide the pair(callback=) parameter? In that case everything is OK - but if you did provide the callback, then it shall be invoked instead of this popup.

@asafs932
Copy link

asafs932 commented May 10, 2021

i did:

my connection code:

            client = BleakClient(device_address)
            await client.connect()
            await client.pair(callback=self.get_passkey)

the callback func:

    @staticmethod
    def get_passkey(
            device: str, pin: Union[None, str], passkey: Union[None, int]
    ) -> Union[bool, int, str, None]:
        """
        :param device: peer device address
        :param pin: (1-16 characters)
        :param passkey: 6 digit password (0-999999)
        :return: Return None if psk is empty string
        """
        # Retrieve passkey by asking the user like OS pairing wizard would do
        psk = input(
            f"Provide pin (1-16 characters) or passkey (0-999999) for {device}, or nothing to reject pairing: "
        )
        return psk or None

so it shouldnt raise the pop up?

i tried now without the callback and same behavior (pop up rise), what am i doing wrong? is it possible to avoid the pop up and insert the passkey in code?
@bojanpotocnik

@bojanpotocnik
Copy link
Contributor Author

bojanpotocnik commented May 12, 2021

You are doing nothing wrong. But the whole point of this PR is to provide the passkey programmatically, so there shall be no popup. Looks like custom pairing agent is being registered and system agent is used instead.
Can you put this

import os
os.environ["BLEAK_LOGGING"] = "1"

on the very beginning of the file (before you import bleak) and then paste the log output here? And if you can, also try running it with sudo.

@asafs932
Copy link

asafs932 commented May 18, 2021

You are doing nothing wrong. But the whole point of this PR is to provide the passkey programmatically, so there shall be no popup. Looks like custom pairing agent is being registered and system agent is used instead.
Can you put this

import os
os.environ["BLEAK_LOGGING"] = "1"

on the very beginning of the file (before you import bleak) and then paste the log output here? And if you can, also try running it with sudo.

without sudo:@bojanpotocnik

2021-05-18 14:38:44,887 bleak.backends.bluezdbus.client DEBUG: Connection successful (/org/bluez/hci0/dev_30_AE_A4_DF_10_7E)
2021-05-18 14:38:44,887 bleak.backends.bluezdbus.client DEBUG: Waiting for ServicesResolved (/org/bluez/hci0/dev_30_AE_A4_DF_10_7E)
2021-05-18 14:38:45,388 - Camera v2 Bluetooth LE App - INFO - Pairing....
2021-05-18 14:38:45,387 bleak.backends.bluezdbus.client DEBUG: received D-Bus signal: org.freedesktop.DBus.Properties.PropertiesChanged (/org/bluez/hci0/dev_30_AE_A4_DF_10_7E): ['org.bluez.Device1', {'ServicesResolved': <dbus_next.signature.Variant ('b', True)>}, []]
2021-05-18 14:38:45,394 bleak.backends.bluezdbus.client DEBUG: Pairing to BLE device @ 30:AE:A4:DF:10:7E with hci0
2021-05-18 14:38:45,405 bleak.backends.bluezdbus.client DEBUG: received D-Bus signal: org.freedesktop.DBus.Properties.PropertiesChanged (/org/bluez/hci0/dev_30_AE_A4_DF_10_7E): ['org.bluez.Device1', {'Paired': <dbus_next.signature.Variant ('b', True)>}, []]
2021-05-18 14:38:45,408 - Camera v2 Bluetooth LE App - INFO - True.
2021-05-18 14:38:45,409 - Camera v2 Bluetooth LE App - INFO - Paired.
2021-05-18 14:38:45,409 - Camera v2 Bluetooth LE App - INFO - connection success.

with sudo its the same:

2021-05-18 14:47:35,292 bleak.backends.bluezdbus.client DEBUG: Connection successful (/org/bluez/hci0/dev_30_AE_A4_DF_10_7E)
2021-05-18 14:47:35,292 bleak.backends.bluezdbus.client DEBUG: Waiting for ServicesResolved (/org/bluez/hci0/dev_30_AE_A4_DF_10_7E)
2021-05-18 14:47:39,377 bleak.backends.bluezdbus.client DEBUG: received D-Bus signal: org.freedesktop.DBus.Properties.PropertiesChanged (/org/bluez/hci0/dev_30_AE_A4_DF_10_7E): ['org.bluez.Device1', {'ServicesResolved': <dbus_next.signature.Variant ('b', True)>}, []]
2021-05-18 14:47:39,378 - Camera v2 Bluetooth LE App - INFO - Pairing....
2021-05-18 14:47:39,382 - Camera v2 Bluetooth LE App - INFO - True.
2021-05-18 14:47:39,382 - Camera v2 Bluetooth LE App - INFO - Paired.
2021-05-18 14:47:39,383 - Camera v2 Bluetooth LE App - INFO - connection success.

@MaxLutton
Copy link

Hi @bojanpotocnik

Great work here. Have you had a chance to try this out on Windows? I have a requirement to automate testing pairing to an embedded device with a pin and am hoping your fork will help with that.

If you haven't been able to test it yet, I'd be happy to help in any way I can.

jpeters-ml added a commit to jpeters-ml/bleak that referenced this pull request Sep 20, 2021
Builds on PR hbldh#523 to include pairing for Windowns with both
dotnet and winrt backends. Updated timeout in connect to use
the same timeout as provided to the connect function.
jpeters-ml added a commit to jpeters-ml/bleak that referenced this pull request Sep 20, 2021
Added windows pairing to .NET and WinRT backends, following the process
started in PR hbldh#523.
@dlech
Copy link
Collaborator

dlech commented Oct 11, 2021

Superseded by #640 which builds on this PR.

@dlech dlech closed this Oct 11, 2021
@bojanpotocnik bojanpotocnik deleted the develop-passkey_pairing_bluez branch November 15, 2022 10:25
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants