Bluetooth: BR/EDR: Initiate authentication
Enables initiate authentication using possibility to change security level on link by calling internal security API. In case of failure resets pairing state flag to re-enable change security on subsequent authentication attempts. To verify the process of authentication run BT shell app from tests/bluetooth/shell folder and use commands like below: >br-connect xx:xx:xx:xx:xx:xx [Connected: xx:xx:xx:xx:xx:xx] >security 1 HCI log: > HCI Event: Connect Complete (0x03) plen 11 Status: Success (0x00) Handle: 11 Address: 00:13:17:72:8D:87 (GN Netcom A/S) Link type: ACL (0x01) Encryption: Disabled (0x00) < HCI Command: Authentication Requested (0x01|0x0011) plen 2 Handle: 11 > HCI Event: Command Status (0x0f) plen 4 Authentication Requested (0x01|0x0011) ncmd 1 Status: Success (0x00) > HCI Event: Link Key Request (0x17) plen 6 Address: 00:13:17:72:8D:87 (GN Netcom A/S) < HCI Command: Link Key Request Negative Reply (0x01|0x000c) plen 6 Address: 00:13:17:72:8D:87 (GN Netcom A/S) > HCI Event: Command Complete (0x0e) plen 10 Link Key Request Negative Reply (0x01|0x000c) ncmd 1 Status: Success (0x00) Address: 00:13:17:72:8D:87 (GN Netcom A/S) > HCI Event: PIN Code Request (0x16) plen 6 Address: 00:13:17:72:8D:87 (GN Netcom A/S) < HCI Command: PIN Code Request Reply (0x01|0x000d) plen 23 Address: 00:13:17:72:8D:87 (GN Netcom A/S) PIN length: 4 PIN code: 0000 > HCI Event: Command Complete (0x0e) plen 10 PIN Code Request Reply (0x01|0x000d) ncmd 1 Status: Success (0x00) Address: 00:13:17:72:8D:87 (GN Netcom A/S) > HCI Event: Link Key Notification (0x18) plen 23 Address: 00:13:17:72:8D:87 (GN Netcom A/S) Link key: d9ff76c09284c1ed369851f87d7ac623 Key type: Combination key (0x00) > HCI Event: Auth Complete (0x06) plen 3 Status: Success (0x00) Handle: 11 Change-Id: I2d383d34e19c04ead3fa254e5514d5c7f352a21e Signed-off-by: Arkadiusz Lichwa <arkadiusz.lichwa@tieto.com>
This commit is contained in:
parent
d458c616df
commit
9d9e349b31
4 changed files with 105 additions and 2 deletions
|
@ -257,6 +257,11 @@ struct bt_hci_rp_pin_code_neg_reply {
|
|||
bt_addr_t bdaddr;
|
||||
} __packed;
|
||||
|
||||
#define BT_HCI_OP_AUTH_REQUESTED BT_OP(BT_OGF_LINK_CTRL, 0x0011)
|
||||
struct bt_hci_cp_auth_requested {
|
||||
uint16_t handle;
|
||||
} __packed;
|
||||
|
||||
#define BT_HCI_OP_REMOTE_NAME_REQUEST BT_OP(BT_OGF_LINK_CTRL, 0x0019)
|
||||
struct bt_hci_cp_remote_name_request {
|
||||
bt_addr_t bdaddr;
|
||||
|
@ -609,6 +614,12 @@ struct bt_hci_evt_disconn_complete {
|
|||
uint8_t reason;
|
||||
} __packed;
|
||||
|
||||
#define BT_HCI_EVT_AUTH_COMPLETE 0x06
|
||||
struct bt_hci_evt_auth_complete {
|
||||
uint8_t status;
|
||||
uint16_t handle;
|
||||
} __packed;
|
||||
|
||||
#define BT_HCI_EVT_REMOTE_NAME_REQ_COMPLETE 0x07
|
||||
struct bt_hci_evt_remote_name_req_complete {
|
||||
uint8_t status;
|
||||
|
|
|
@ -527,6 +527,26 @@ static int bt_hci_connect_br_cancel(struct bt_conn *conn)
|
|||
|
||||
return err;
|
||||
}
|
||||
|
||||
static int conn_auth(struct bt_conn *conn)
|
||||
{
|
||||
struct bt_hci_cp_auth_requested *auth;
|
||||
struct net_buf *buf;
|
||||
|
||||
BT_DBG("");
|
||||
|
||||
buf = bt_hci_cmd_create(BT_HCI_OP_AUTH_REQUESTED, sizeof(*auth));
|
||||
if (!buf) {
|
||||
return -ENOBUFS;
|
||||
}
|
||||
|
||||
auth = net_buf_add(buf, sizeof(*auth));
|
||||
auth->handle = sys_cpu_to_le16(conn->handle);
|
||||
|
||||
atomic_set_bit(conn->flags, BT_CONN_BR_PAIRING_INITIATOR);
|
||||
|
||||
return bt_hci_cmd_send_sync(BT_HCI_OP_AUTH_REQUESTED, buf, NULL);
|
||||
}
|
||||
#endif /* CONFIG_BLUETOOTH_BREDR */
|
||||
|
||||
#if defined(CONFIG_BLUETOOTH_SMP)
|
||||
|
@ -598,7 +618,16 @@ static int start_security(struct bt_conn *conn)
|
|||
return -EBUSY;
|
||||
}
|
||||
|
||||
return -EPERM;
|
||||
if (conn->required_sec_level > BT_SECURITY_HIGH) {
|
||||
return -ENOTSUP;
|
||||
}
|
||||
|
||||
if (bt_conn_get_io_capa() == BT_IO_NO_INPUT_OUTPUT &&
|
||||
conn->required_sec_level > BT_SECURITY_MEDIUM) {
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
return conn_auth(conn);
|
||||
}
|
||||
#endif /* CONFIG_BLUETOOTH_BREDR */
|
||||
|
||||
|
|
|
@ -33,6 +33,7 @@ enum {
|
|||
BT_CONN_USER, /* user I/O when pairing */
|
||||
BT_CONN_BR_PAIRING, /* BR connection in pairing context */
|
||||
BT_CONN_BR_NOBOND, /* SSP no bond pairing tracker */
|
||||
BT_CONN_BR_PAIRING_INITIATOR, /* local host starts authentication */
|
||||
};
|
||||
|
||||
struct bt_conn_le {
|
||||
|
|
|
@ -1227,6 +1227,17 @@ static void link_key_req(struct net_buf *buf)
|
|||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* Enforce regenerate by controller stronger link key since found one
|
||||
* in database not covers requested security level.
|
||||
*/
|
||||
if (!atomic_test_bit(&conn->keys->flags, BT_KEYS_AUTHENTICATED) &&
|
||||
conn->required_sec_level > BT_SECURITY_MEDIUM) {
|
||||
link_key_neg_reply(&evt->bdaddr);
|
||||
bt_conn_unref(conn);
|
||||
return;
|
||||
}
|
||||
|
||||
link_key_reply(&evt->bdaddr, conn->keys->link_key.val);
|
||||
bt_conn_unref(conn);
|
||||
}
|
||||
|
@ -1289,6 +1300,7 @@ static void io_capa_req(struct net_buf *buf)
|
|||
struct net_buf *resp_buf;
|
||||
struct bt_conn *conn;
|
||||
struct bt_hci_cp_io_capability_reply *cp;
|
||||
uint8_t auth;
|
||||
|
||||
BT_DBG("");
|
||||
|
||||
|
@ -1306,10 +1318,26 @@ static void io_capa_req(struct net_buf *buf)
|
|||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* Set authentication requirements when acting as pairing initiator to
|
||||
* 'dedicated bond' with MITM protection set if local IO capa
|
||||
* potentially allows it, and for acceptor, based on local IO capa and
|
||||
* remote's authentication set.
|
||||
*/
|
||||
if (atomic_test_bit(conn->flags, BT_CONN_BR_PAIRING_INITIATOR)) {
|
||||
if (bt_conn_get_io_capa() != BT_IO_NO_INPUT_OUTPUT) {
|
||||
auth = BT_HCI_DEDICATED_BONDING_MITM;
|
||||
} else {
|
||||
auth = BT_HCI_DEDICATED_BONDING;
|
||||
}
|
||||
} else {
|
||||
auth = bt_conn_ssp_get_auth(conn);
|
||||
}
|
||||
|
||||
cp = net_buf_add(resp_buf, sizeof(*cp));
|
||||
bt_addr_copy(&cp->bdaddr, &evt->bdaddr);
|
||||
cp->capability = bt_conn_get_io_capa();
|
||||
cp->authentication = bt_conn_ssp_get_auth(conn);
|
||||
cp->authentication = auth;
|
||||
cp->oob_data = 0;
|
||||
bt_hci_cmd_send_sync(BT_HCI_OP_IO_CAPABILITY_REPLY, resp_buf, NULL);
|
||||
bt_conn_unref(conn);
|
||||
|
@ -1679,6 +1707,35 @@ check_names:
|
|||
discovery_results_size = 0;
|
||||
discovery_results_count = 0;
|
||||
}
|
||||
|
||||
static void auth_complete(struct net_buf *buf)
|
||||
{
|
||||
struct bt_hci_evt_auth_complete *evt = (void *)buf->data;
|
||||
struct bt_conn *conn;
|
||||
uint16_t handle = sys_le16_to_cpu(evt->handle);
|
||||
|
||||
BT_DBG("status %u, handle %u", evt->status, handle);
|
||||
|
||||
conn = bt_conn_lookup_handle(handle);
|
||||
if (!conn) {
|
||||
BT_ERR("Can't find conn for handle %u", handle);
|
||||
return;
|
||||
}
|
||||
|
||||
if (evt->status) {
|
||||
/*
|
||||
* Clear pairing flag since authentication failed for some
|
||||
* reasons.
|
||||
*/
|
||||
atomic_clear_bit(conn->flags, BT_CONN_BR_PAIRING);
|
||||
atomic_clear_bit(conn->flags, BT_CONN_BR_PAIRING_INITIATOR);
|
||||
|
||||
/* Reset required security level to current operational */
|
||||
conn->required_sec_level = conn->sec_level;
|
||||
}
|
||||
|
||||
bt_conn_unref(conn);
|
||||
}
|
||||
#endif /* CONFIG_BLUETOOTH_BREDR */
|
||||
|
||||
#if defined(CONFIG_BLUETOOTH_SMP) || defined(CONFIG_BLUETOOTH_BREDR)
|
||||
|
@ -1749,6 +1806,7 @@ static void hci_encrypt_change(struct net_buf *buf)
|
|||
} else {
|
||||
update_sec_level_br(conn);
|
||||
atomic_clear_bit(conn->flags, BT_CONN_BR_PAIRING);
|
||||
atomic_clear_bit(conn->flags, BT_CONN_BR_PAIRING_INITIATOR);
|
||||
#endif /* CONFIG_BLUETOOTH_BREDR */
|
||||
}
|
||||
|
||||
|
@ -2441,6 +2499,9 @@ static void hci_event(struct net_buf *buf)
|
|||
case BT_HCI_EVT_REMOTE_NAME_REQ_COMPLETE:
|
||||
remote_name_request_complete(buf);
|
||||
break;
|
||||
case BT_HCI_EVT_AUTH_COMPLETE:
|
||||
auth_complete(buf);
|
||||
break;
|
||||
#endif
|
||||
#if defined(CONFIG_BLUETOOTH_CONN)
|
||||
case BT_HCI_EVT_DISCONN_COMPLETE:
|
||||
|
@ -2916,6 +2977,7 @@ static int set_event_mask(void)
|
|||
ev->events[0] |= 0x01; /* Inquiry Complete */
|
||||
ev->events[0] |= 0x04; /* Connection Complete */
|
||||
ev->events[0] |= 0x08; /* Connection Request */
|
||||
ev->events[0] |= 0x20; /* Authentication Complete */
|
||||
ev->events[0] |= 0x40; /* Remote Name Request Complete */
|
||||
ev->events[2] |= 0x20; /* Pin Code Request */
|
||||
ev->events[2] |= 0x40; /* Link Key Request */
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue