2022-08-23 22:11:36

by John Klug

[permalink] [raw]
Subject: What could cause pairing to fail when bluetoothctl is not running?

I have two different hosts on two different kernels with the same application written by me.

I tried to make BlueZ exactly the same, 5.64.

I see no difference in configuration.

The application sets trusted to true before pairing.

On one host, bluetoothctl must be running, even though there is no prompting to pair in bluetoothctl.

On the other host, pairing occurs without bluetoothctl running.

kernels are 5.4.199 versus 5.10.120.? 5.10.120 has the issue with a bluetoothctl requirement.



John Klug



2022-08-26 23:08:06

by John Klug

[permalink] [raw]
Subject: Re: What could cause pairing to fail when bluetoothctl is not running?

Maybe I need to create a pairing AgentManager, even though I don't use one?

I see that bluetoothctl causes some D-Bus transactions that may be relevant:

signal time=1661551309.565274 sender=:1.49 -> destination=(null destination) serial=27 path=/; interface=org.freedesktop.DBus.ObjectManager; member=InterfacesAdded
? ?object path "/org/bluez/agent"
? ?array [
? ? ? dict entry(
? ? ? ? ?string "org.freedesktop.DBus.Introspectable"
? ? ? ? ?array [
? ? ? ? ?]
? ? ? )
? ? ? dict entry(
? ? ? ? ?string "org.bluez.Agent1"
? ? ? ? ?array [
? ? ? ? ?]
? ? ? )
? ?]

method call time=1661551309.566053 sender=:1.49 -> destination=org.bluez serial=28 path=/org/bluez; interface=org.bluez.AgentManager1; member=RegisterAgent
? ?object path "/org/bluez/agent"
? ?string ""

method return time=1661551309.587789 sender=:1.49 -> destination=:1.1 serial=30 reply_serial=1096
? ?array [
? ? ? dict entry(
? ? ? ? ?object path "/org/bluez/agent"
? ? ? ? ?array [
? ? ? ? ? ? dict entry(
? ? ? ? ? ? ? ?string "org.freedesktop.DBus.Introspectable"
? ? ? ? ? ? ? ?array [
? ? ? ? ? ? ? ?]
? ? ? ? ? ? )
? ? ? ? ? ? dict entry(
? ? ? ? ? ? ? ?string "org.bluez.Agent1"
? ? ? ? ? ? ? ?array [
? ? ? ? ? ? ? ?]
? ? ? ? ? ? )
? ? ? ? ?]
? ? ? )
? ?]

John Klug

2022-08-29 09:54:39

by Bastien Nocera

[permalink] [raw]
Subject: Re: What could cause pairing to fail when bluetoothctl is not running?

On Fri, 2022-08-26 at 22:43 +0000, John Klug wrote:
> Maybe I need to create a pairing AgentManager, even though I don't
> use one?

You need a pairing agent otherwise all pairing attempts will be
rejected. This is a security feature.

The bluez-tools at:
https://github.com/khvzak/bluez-tools
can help if you want to automate pairing without writing new code (or
to experiment).

2022-08-30 22:22:41

by John Klug

[permalink] [raw]
Subject: Re: What could cause pairing to fail when bluetoothctl is not running?

I am now looking at what is going on with a sniffer.? For some reason in 5.10, the AuthReq always comes from the slave (BlueZ is the master, GATT client):

5.10 kernel which fails, leaving out empty PDU, L2CAP Fragments, etc. This sequence is reproducible.

Sent slave CONNECT_IND
Rcvd Security Request: AuthReq: Bonding, SecureConnection
Sent Pairing Failed: Pairing not Supported
Sent Pairing Failed: Pairing not Supported
Rcvd Exchange MTU Response ...
Sent Pairing Request: AuthReq: No Bonding, SecureConnection | Initiator Key(s): <none> | Responder key(s) IRK
Sent Control Opcode LL_LENGTH_RSP
Rcvd Pairing Response: AuthReq: No Bonding, SecureConnection | Initiator Key(s): <none> | Responder key(s)
Sent Pairing Public Key
Sent Read By Type Request, Sever Supported Features, Handles: ...
Recvd Pairing Public Key
Rcvd Pairing Confirm
Rcvd Error Response - Attribute Not Found, Handle: 0x0001 (Unknown)
Sent Pairing Random
Sent Read by Group Type Request, Gatt ...
Rcvd Pairing Random
Send Pairing Failed: Numeric Comparison Failed

The 5.4 kernel always works, but BlueZ/Linux sends the first AuthReq:

Sent Slave CONNECT_IND
Sent Pairing Request: AuthReq: No Bonding, SecureConnection | Initiator Key(s): <none> | Responder key(s)
Rcvd Pairing Response: AuthReq: No Bonding, SecureConnection | Initiator Key(s): <none> | Responder key(s)
Sent Read By Type Request, Sever Supported Features, Handles: ...
Rcvd Pairing Response: AuthReq: No Bonding, SecureConnection | Initiator Key(s): <none> | Responder
Sent Read by Group Type Request, Gatt ..
Rcvd Pairing Confirm
Rcvd Read by Group Type Response, Attribute ..
Sent Pairing Random
Sent Read by Group Type Request, Gatt ..
Rcvd Pairing Random
Sent Pairing DHKey Check

Should the program be sending a Pair using the Device API? Is there something else to cause the public key exchange? In the 5.4 case, the "Paired" property is always being set by the Device API.

2022-08-30 22:32:54

by Luiz Augusto von Dentz

[permalink] [raw]
Subject: Re: What could cause pairing to fail when bluetoothctl is not running?

Hi John,

On Tue, Aug 30, 2022 at 3:22 PM John Klug <[email protected]> wrote:
>
> I am now looking at what is going on with a sniffer. For some reason in 5.10, the AuthReq always comes from the slave (BlueZ is the master, GATT client):
>
> 5.10 kernel which fails, leaving out empty PDU, L2CAP Fragments, etc. This sequence is reproducible.
>
> Sent slave CONNECT_IND
> Rcvd Security Request: AuthReq: Bonding, SecureConnection
> Sent Pairing Failed: Pairing not Supported
> Sent Pairing Failed: Pairing not Supported
> Rcvd Exchange MTU Response ...
> Sent Pairing Request: AuthReq: No Bonding, SecureConnection | Initiator Key(s): <none> | Responder key(s) IRK
> Sent Control Opcode LL_LENGTH_RSP
> Rcvd Pairing Response: AuthReq: No Bonding, SecureConnection | Initiator Key(s): <none> | Responder key(s)
> Sent Pairing Public Key
> Sent Read By Type Request, Sever Supported Features, Handles: ...
> Recvd Pairing Public Key
> Rcvd Pairing Confirm
> Rcvd Error Response - Attribute Not Found, Handle: 0x0001 (Unknown)
> Sent Pairing Random
> Sent Read by Group Type Request, Gatt ...
> Rcvd Pairing Random
> Send Pairing Failed: Numeric Comparison Failed
>
> The 5.4 kernel always works, but BlueZ/Linux sends the first AuthReq:
>
> Sent Slave CONNECT_IND
> Sent Pairing Request: AuthReq: No Bonding, SecureConnection | Initiator Key(s): <none> | Responder key(s)
> Rcvd Pairing Response: AuthReq: No Bonding, SecureConnection | Initiator Key(s): <none> | Responder key(s)
> Sent Read By Type Request, Sever Supported Features, Handles: ...
> Rcvd Pairing Response: AuthReq: No Bonding, SecureConnection | Initiator Key(s): <none> | Responder
> Sent Read by Group Type Request, Gatt ..
> Rcvd Pairing Confirm
> Rcvd Read by Group Type Response, Attribute ..
> Sent Pairing Random
> Sent Read by Group Type Request, Gatt ..
> Rcvd Pairing Random
> Sent Pairing DHKey Check
>
> Should the program be sending a Pair using the Device API? Is there something else to cause the public key exchange? In the 5.4 case, the "Paired" property is always being set by the Device API.

Either way you need a pairing agent in case the device for some reason
removes its link key and then you need to repair, besides the agent
also does authorization when the device is not trusted, have you tried
just running bluetoothctl to see if that makes it work?

--
Luiz Augusto von Dentz

2022-08-31 00:19:17

by John Klug

[permalink] [raw]
Subject: Re: What could cause pairing to fail when bluetoothctl is not running?

Luiz Augusto von Dentz Wrote:
>have you tried
>just running bluetoothctl to see if that makes it work?

Yes that was the point of my title.? In 5.4 Linux I do not need bluetoothctl running, but in 5.10 I do.? This is a BLE GATT Client.? I do not save anything involving credentials, there are none for me to save. I always remove the device on disconnect because there are too many devices.? Connections are short lived. There is nothing to do for pairing except to exchange public keys.

I cannot let bluetoothctl run because I have an embedded device, and scans by bluetoothctl add to the CPU load, and I cannot turn scan off because I need to know when a new BLE device advertises. Devices are not advertising when there is nothing for me to do. I have a filter, but bluetoothctl ignores the filter, but my application works fine with the filter.

So if this is a new requirement in 5.10 Linux, I need to add an agent to my application.

Looking at the agent documentation:

https://git.kernel.org/pub/scm/bluetooth/bluez.git/tree/doc/agent-api.txt

Agent-api.txt says:
>It is not required by an application to register
>an agent. If an application does chooses to not
>register an agent, the default agent is used. This
>is on most cases a good idea. Only application
>like a pairing wizard should register their own
>agent.

Is this documentation obsolete as of 5.10?

When I run bluetoothctl, nothing happens in bluetoothctl during pairing (which is what I would expect). It just makes things work. If I create an agent, it should be a trivial one with NoInputNoOutput set. There is no pin. There is nothing to do.

Right now I am trying to determine what exactly needs to be done.


<html><head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8"></head><body><div style="font-family:Arial,Helvetica,sans-serif; font-size:12pt; color:rgb(0,0,0)"><br></div><hr tabindex="-1" style="display:inline-block; width:98%"><div id="divRplyFwdMsg" dir="ltr"><font face="Calibri, sans-serif" color="#000000" style="font-size:11pt"><b>From:</b> Luiz Augusto von Dentz &lt;[email protected]&gt;<br><b>Sent:</b> Tuesday, August 30, 2022 5:28 PM<br><b>To:</b> John Klug &lt;[email protected]&gt;<br><b>Cc:</b> Linux-Bluetooth MailingList &lt;[email protected]&gt;<br><b>Subject:</b> Re: What could cause pairing to fail when bluetoothctl is not running?</font> <div>&nbsp;</div></div><div class="BodyFragment"><font size="2"><span style="font-size:11pt"><div class="PlainText">Hi John,<br><br>On Tue, Aug 30, 2022 at 3:22 PM John Klug &lt;[email protected]&gt; wrote:<br>&gt;<br>&gt; I am now looking at what is going on with a sniffer.&nbsp; For some reason in 5.10, the AuthReq always comes from the slave (BlueZ is the master, GATT client):<br>&gt;<br>&gt; 5.10 kernel which fails, leaving out empty PDU, L2CAP Fragments, etc.&nbsp; This sequence is reproducible.<br>&gt;<br>&gt; Sent slave CONNECT_IND<br>&gt; Rcvd Security Request: AuthReq: Bonding, SecureConnection<br>&gt; Sent Pairing Failed: Pairing not Supported<br>&gt; Sent Pairing Failed: Pairing not Supported<br>&gt; Rcvd Exchange MTU Response ...<br>&gt; Sent Pairing Request: AuthReq: No Bonding, SecureConnection | Initiator Key(s): &lt;none&gt; | Responder key(s) IRK<br>&gt; Sent Control Opcode LL_LENGTH_RSP<br>&gt; Rcvd Pairing Response: AuthReq: No Bonding, SecureConnection | Initiator Key(s): &lt;none&gt; | Responder key(s)<br>&gt; Sent Pairing Public Key<br>&gt; Sent Read By Type Request, Sever Supported Features, Handles: ...<br>&gt; Recvd Pairing Public Key<br>&gt; Rcvd Pairing Confirm<br>&gt; Rcvd Error Response - Attribute Not Found, Handle: 0x0001 (Unknown)<br>&gt; Sent Pairing Random<br>&gt; Sent Read by Group Type Request, Gatt ...<br>&gt; Rcvd Pairing Random<br>&gt; Send Pairing Failed: Numeric Comparison Failed<br>&gt;<br>&gt; The 5.4 kernel always works, but BlueZ/Linux sends the first AuthReq:<br>&gt;<br>&gt; Sent Slave CONNECT_IND<br>&gt; Sent Pairing Request: AuthReq: No Bonding, SecureConnection | Initiator Key(s): &lt;none&gt; | Responder key(s)<br>&gt; Rcvd Pairing Response: AuthReq: No Bonding, SecureConnection | Initiator Key(s): &lt;none&gt; | Responder key(s)<br>&gt; Sent Read By Type Request, Sever Supported Features, Handles: ...<br>&gt; Rcvd Pairing Response: AuthReq: No Bonding, SecureConnection | Initiator Key(s): &lt;none&gt; | Responder<br>&gt; Sent Read by Group Type Request, Gatt ..<br>&gt; Rcvd Pairing Confirm<br>&gt; Rcvd Read by Group Type Response, Attribute ..<br>&gt; Sent Pairing Random<br>&gt; Sent Read by Group Type Request, Gatt ..<br>&gt; Rcvd Pairing Random<br>&gt; Sent Pairing DHKey Check<br>&gt;<br>&gt; Should the program be sending a Pair using the Device API?&nbsp; Is there something else to cause the public key exchange?&nbsp; In the 5.4 case, the &quot;Paired&quot; property is always being set by the Device API.<br><br>Either way you need a pairing agent in case the device for some reason<br>removes its link key and then you need to repair, besides the agent<br>also does authorization when the device is not trusted, have you tried<br>just running bluetoothctl to see if that makes it work?<br><br>-- <br>Luiz Augusto von Dentz<br></div></span></font></div></body></html>

2022-08-31 18:00:49

by John Klug

[permalink] [raw]
Subject: Re: What could cause pairing to fail when bluetoothctl is not running?

I am finally in business in Linux 5.10.

I built the old bt-agent, and started it with the NoInputNoOutput agent while running dbus-monitor.

I saw:

method call time=1661900193.562288 sender=:1.1182 -> destination=:1.1171 serial=23 path=/org/bluez; interface=org.bluez.AgentManager1; member=RegisterAgent
object path "/org/blueztools"
string "NoInputNoOutput"
method call time=1661900193.562697 sender=:1.1182 -> destination=:1.1171 serial=24 path=/org/bluez; interface=org.bluez.AgentManager1; member=RequestDefaultAgent
object path "/org/blueztools"

I wrote this code in GTK:

#include <gio/gio.h>
const gchar *AM1 = "org.bluez.AgentManager1";
const gchar *AGENT_PATH = "/org/bluez/agent";
GDBusConnection *con;

void bluez_register_agent(){
? ? GVariant *result;
? ? GError *error = NULL;
? ? result = g_dbus_connection_call_sync(con,
? ? ? ? "org.bluez",
? ? ? ? "/org/bluez",
? ? ? ? AM1,
? ? ? ? "RegisterAgent",
? ? ? ? g_variant_new("(os)",AGENT_PATH,"NoInputNoOutput"),
? ? ? ? NULL,
? ? ? ? G_DBUS_SIGNAL_FLAGS_NONE,
? ? ? ? -1,
? ? ? ? NULL,
? ? ? ? &error
? ? );
? ? if (error) {
? ? ? ? print_error(error);
? ? ? ? g_error_free(error);
? ? ? ? g_abort();
? ? ? ? error = NULL;
? ? }
? ? if (result) {
#ifdef VERBOSE_DEBUG
? ? ? ? gchar *result_text;
? ? ? ? result_text = g_variant_print(result,TRUE);
? ? ? ? g_print("%s\n",result_text);
? ? ? ? g_free(result_text);
#endif
? ? ? ? g_variant_unref(result);
? ? }

? ? result = g_dbus_connection_call_sync(con,
? ? "org.bluez",
? ? "/org/bluez",
? ? AM1,
? ? "RequestDefaultAgent",
? ? g_variant_new("(o)",AGENT_PATH),
? ? NULL,
? ? G_DBUS_SIGNAL_FLAGS_NONE,
? ? -1,
? ? NULL,
? ? &error
? ? );
? ? if (error) {
? ? ? ? print_error(error);
? ? ? ? g_error_free(error);
? ? ? ? g_abort();
? ? }
? ? if (result) {
#ifdef VERBOSE_DEBUG
? ? ? ? gchar *result_text;
? ? ? ? result_text = g_variant_print(result,TRUE);
? ? ? ? g_print("%s\n",result_text);
? ? ? ? g_free(result_text);
#endif
? ? ? ? g_variant_unref(result);
? ? }
}

Thanks for the help.


John Klug