Skip to content

Commit

Permalink
Bluetooth: Fix using RPA when address has been resolved
Browse files Browse the repository at this point in the history
When connecting to a device using an RPA if the address has been
resolved by the controller (types 0x02 and 0x03) the identity address
shall be used as the actual RPA in the advertisement won't be visible
to the host.

Signed-off-by: Luiz Augusto von Dentz <[email protected]>
Signed-off-by: Marcel Holtmann <[email protected]>
  • Loading branch information
Vudentz authored and holtmann committed Aug 30, 2021
1 parent 4ec4d63 commit d850bf0
Show file tree
Hide file tree
Showing 4 changed files with 43 additions and 30 deletions.
5 changes: 3 additions & 2 deletions include/net/bluetooth/hci_core.h
Original file line number Diff line number Diff line change
Expand Up @@ -1101,8 +1101,9 @@ struct hci_conn *hci_connect_le_scan(struct hci_dev *hdev, bdaddr_t *dst,
u16 conn_timeout,
enum conn_reasons conn_reason);
struct hci_conn *hci_connect_le(struct hci_dev *hdev, bdaddr_t *dst,
u8 dst_type, u8 sec_level, u16 conn_timeout,
u8 role, bdaddr_t *direct_rpa);
u8 dst_type, bool dst_resolved, u8 sec_level,
u16 conn_timeout, u8 role,
bdaddr_t *direct_rpa);
struct hci_conn *hci_connect_acl(struct hci_dev *hdev, bdaddr_t *dst,
u8 sec_level, u8 auth_type,
enum conn_reasons conn_reason);
Expand Down
33 changes: 19 additions & 14 deletions net/bluetooth/hci_conn.c
Original file line number Diff line number Diff line change
Expand Up @@ -1040,8 +1040,8 @@ static void hci_req_directed_advertising(struct hci_request *req,
}

struct hci_conn *hci_connect_le(struct hci_dev *hdev, bdaddr_t *dst,
u8 dst_type, u8 sec_level, u16 conn_timeout,
u8 role, bdaddr_t *direct_rpa)
u8 dst_type, bool dst_resolved, u8 sec_level,
u16 conn_timeout, u8 role, bdaddr_t *direct_rpa)
{
struct hci_conn_params *params;
struct hci_conn *conn;
Expand Down Expand Up @@ -1078,19 +1078,24 @@ struct hci_conn *hci_connect_le(struct hci_dev *hdev, bdaddr_t *dst,
return ERR_PTR(-EBUSY);
}

/* When given an identity address with existing identity
* resolving key, the connection needs to be established
* to a resolvable random address.
*
* Storing the resolvable random address is required here
* to handle connection failures. The address will later
* be resolved back into the original identity address
* from the connect request.
/* Check if the destination address has been resolved by the controller
* since if it did then the identity address shall be used.
*/
irk = hci_find_irk_by_addr(hdev, dst, dst_type);
if (irk && bacmp(&irk->rpa, BDADDR_ANY)) {
dst = &irk->rpa;
dst_type = ADDR_LE_DEV_RANDOM;
if (!dst_resolved) {
/* When given an identity address with existing identity
* resolving key, the connection needs to be established
* to a resolvable random address.
*
* Storing the resolvable random address is required here
* to handle connection failures. The address will later
* be resolved back into the original identity address
* from the connect request.
*/
irk = hci_find_irk_by_addr(hdev, dst, dst_type);
if (irk && bacmp(&irk->rpa, BDADDR_ANY)) {
dst = &irk->rpa;
dst_type = ADDR_LE_DEV_RANDOM;
}
}

if (conn) {
Expand Down
33 changes: 20 additions & 13 deletions net/bluetooth/hci_event.c
Original file line number Diff line number Diff line change
Expand Up @@ -2367,19 +2367,25 @@ static void hci_cs_disconnect(struct hci_dev *hdev, u8 status)
hci_dev_unlock(hdev);
}

static u8 ev_bdaddr_type(struct hci_dev *hdev, u8 type)
static u8 ev_bdaddr_type(struct hci_dev *hdev, u8 type, bool *resolved)
{
/* When using controller based address resolution, then the new
* address types 0x02 and 0x03 are used. These types need to be
* converted back into either public address or random address type
*/
switch (type) {
case ADDR_LE_DEV_PUBLIC_RESOLVED:
if (resolved)
*resolved = true;
return ADDR_LE_DEV_PUBLIC;
case ADDR_LE_DEV_RANDOM_RESOLVED:
if (resolved)
*resolved = true;
return ADDR_LE_DEV_RANDOM;
}

if (resolved)
*resolved = false;
return type;
}

Expand All @@ -2394,7 +2400,7 @@ static void cs_le_create_conn(struct hci_dev *hdev, bdaddr_t *peer_addr,
if (!conn)
return;

own_address_type = ev_bdaddr_type(hdev, own_address_type);
own_address_type = ev_bdaddr_type(hdev, own_address_type, NULL);

/* Store the initiator and responder address information which
* is needed for SMP. These values will not change during the
Expand Down Expand Up @@ -5284,7 +5290,7 @@ static void le_conn_complete_evt(struct hci_dev *hdev, u8 status,
conn->dst_type = irk->addr_type;
}

conn->dst_type = ev_bdaddr_type(hdev, conn->dst_type);
conn->dst_type = ev_bdaddr_type(hdev, conn->dst_type, NULL);

if (status) {
hci_le_conn_failed(conn, status);
Expand Down Expand Up @@ -5466,8 +5472,8 @@ static void hci_le_conn_update_complete_evt(struct hci_dev *hdev,
/* This function requires the caller holds hdev->lock */
static struct hci_conn *check_pending_le_conn(struct hci_dev *hdev,
bdaddr_t *addr,
u8 addr_type, u8 adv_type,
bdaddr_t *direct_rpa)
u8 addr_type, bool addr_resolved,
u8 adv_type, bdaddr_t *direct_rpa)
{
struct hci_conn *conn;
struct hci_conn_params *params;
Expand Down Expand Up @@ -5519,9 +5525,9 @@ static struct hci_conn *check_pending_le_conn(struct hci_dev *hdev,
}
}

conn = hci_connect_le(hdev, addr, addr_type, BT_SECURITY_LOW,
hdev->def_le_autoconnect_timeout, HCI_ROLE_MASTER,
direct_rpa);
conn = hci_connect_le(hdev, addr, addr_type, addr_resolved,
BT_SECURITY_LOW, hdev->def_le_autoconnect_timeout,
HCI_ROLE_MASTER, direct_rpa);
if (!IS_ERR(conn)) {
/* If HCI_AUTO_CONN_EXPLICIT is set, conn is already owned
* by higher layer that tried to connect, if no then
Expand Down Expand Up @@ -5562,7 +5568,7 @@ static void process_adv_report(struct hci_dev *hdev, u8 type, bdaddr_t *bdaddr,
struct discovery_state *d = &hdev->discovery;
struct smp_irk *irk;
struct hci_conn *conn;
bool match;
bool match, bdaddr_resolved;
u32 flags;
u8 *ptr;

Expand Down Expand Up @@ -5606,7 +5612,8 @@ static void process_adv_report(struct hci_dev *hdev, u8 type, bdaddr_t *bdaddr,
* controller address.
*/
if (direct_addr) {
direct_addr_type = ev_bdaddr_type(hdev, direct_addr_type);
direct_addr_type = ev_bdaddr_type(hdev, direct_addr_type,
&bdaddr_resolved);

/* Only resolvable random addresses are valid for these
* kind of reports and others can be ignored.
Expand Down Expand Up @@ -5635,15 +5642,15 @@ static void process_adv_report(struct hci_dev *hdev, u8 type, bdaddr_t *bdaddr,
bdaddr_type = irk->addr_type;
}

bdaddr_type = ev_bdaddr_type(hdev, bdaddr_type);
bdaddr_type = ev_bdaddr_type(hdev, bdaddr_type, &bdaddr_resolved);

/* Check if we have been requested to connect to this device.
*
* direct_addr is set only for directed advertising reports (it is NULL
* for advertising reports) and is already verified to be RPA above.
*/
conn = check_pending_le_conn(hdev, bdaddr, bdaddr_type, type,
direct_addr);
conn = check_pending_le_conn(hdev, bdaddr, bdaddr_type, bdaddr_resolved,
type, direct_addr);
if (!ext_adv && conn && type == LE_ADV_IND && len <= HCI_MAX_AD_LENGTH) {
/* Store report for later inclusion by
* mgmt_device_connected
Expand Down
2 changes: 1 addition & 1 deletion net/bluetooth/l2cap_core.c
Original file line number Diff line number Diff line change
Expand Up @@ -7902,7 +7902,7 @@ int l2cap_chan_connect(struct l2cap_chan *chan, __le16 psm, u16 cid,
dst_type = ADDR_LE_DEV_RANDOM;

if (hci_dev_test_flag(hdev, HCI_ADVERTISING))
hcon = hci_connect_le(hdev, dst, dst_type,
hcon = hci_connect_le(hdev, dst, dst_type, false,
chan->sec_level,
HCI_LE_CONN_TIMEOUT,
HCI_ROLE_SLAVE, NULL);
Expand Down

0 comments on commit d850bf0

Please sign in to comment.