Bluetooth: SMP: Fix assumption of Central always being Initiator
[ Upstream commit 28cd47f75185c4818b0fb1b46f2f02faaba96376 ] SMP initiator role shall be considered the one that initiates the pairing procedure with SMP_CMD_PAIRING_REQ: BLUETOOTH CORE SPECIFICATION Version 5.3 | Vol 3, Part H page 1557: Figure 2.1: LE pairing phases Note that by sending SMP_CMD_SECURITY_REQ it doesn't change the role to be Initiator. Link: https://github.com/bluez/bluez/issues/567 Fixes: b28b4943660f ("Bluetooth: Add strict checks for allowed SMP PDUs") Signed-off-by: Luiz Augusto von Dentz <luiz.von.dentz@intel.com> Signed-off-by: Sasha Levin <sashal@kernel.org>
This commit is contained in:
parent
bafa10dcb6
commit
35cecaecda
1 changed files with 73 additions and 73 deletions
|
@ -914,7 +914,7 @@ static int tk_request(struct l2cap_conn *conn, u8 remote_oob, u8 auth,
|
||||||
* Confirms and the responder Enters the passkey.
|
* Confirms and the responder Enters the passkey.
|
||||||
*/
|
*/
|
||||||
if (smp->method == OVERLAP) {
|
if (smp->method == OVERLAP) {
|
||||||
if (hcon->role == HCI_ROLE_MASTER)
|
if (test_bit(SMP_FLAG_INITIATOR, &smp->flags))
|
||||||
smp->method = CFM_PASSKEY;
|
smp->method = CFM_PASSKEY;
|
||||||
else
|
else
|
||||||
smp->method = REQ_PASSKEY;
|
smp->method = REQ_PASSKEY;
|
||||||
|
@ -964,7 +964,7 @@ static u8 smp_confirm(struct smp_chan *smp)
|
||||||
|
|
||||||
smp_send_cmd(smp->conn, SMP_CMD_PAIRING_CONFIRM, sizeof(cp), &cp);
|
smp_send_cmd(smp->conn, SMP_CMD_PAIRING_CONFIRM, sizeof(cp), &cp);
|
||||||
|
|
||||||
if (conn->hcon->out)
|
if (test_bit(SMP_FLAG_INITIATOR, &smp->flags))
|
||||||
SMP_ALLOW_CMD(smp, SMP_CMD_PAIRING_CONFIRM);
|
SMP_ALLOW_CMD(smp, SMP_CMD_PAIRING_CONFIRM);
|
||||||
else
|
else
|
||||||
SMP_ALLOW_CMD(smp, SMP_CMD_PAIRING_RANDOM);
|
SMP_ALLOW_CMD(smp, SMP_CMD_PAIRING_RANDOM);
|
||||||
|
@ -980,7 +980,8 @@ static u8 smp_random(struct smp_chan *smp)
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
bt_dev_dbg(conn->hcon->hdev, "conn %p %s", conn,
|
bt_dev_dbg(conn->hcon->hdev, "conn %p %s", conn,
|
||||||
conn->hcon->out ? "initiator" : "responder");
|
test_bit(SMP_FLAG_INITIATOR, &smp->flags) ? "initiator" :
|
||||||
|
"responder");
|
||||||
|
|
||||||
ret = smp_c1(smp->tk, smp->rrnd, smp->preq, smp->prsp,
|
ret = smp_c1(smp->tk, smp->rrnd, smp->preq, smp->prsp,
|
||||||
hcon->init_addr_type, &hcon->init_addr,
|
hcon->init_addr_type, &hcon->init_addr,
|
||||||
|
@ -994,7 +995,7 @@ static u8 smp_random(struct smp_chan *smp)
|
||||||
return SMP_CONFIRM_FAILED;
|
return SMP_CONFIRM_FAILED;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (hcon->out) {
|
if (test_bit(SMP_FLAG_INITIATOR, &smp->flags)) {
|
||||||
u8 stk[16];
|
u8 stk[16];
|
||||||
__le64 rand = 0;
|
__le64 rand = 0;
|
||||||
__le16 ediv = 0;
|
__le16 ediv = 0;
|
||||||
|
@ -1251,14 +1252,15 @@ static void smp_distribute_keys(struct smp_chan *smp)
|
||||||
rsp = (void *) &smp->prsp[1];
|
rsp = (void *) &smp->prsp[1];
|
||||||
|
|
||||||
/* The responder sends its keys first */
|
/* The responder sends its keys first */
|
||||||
if (hcon->out && (smp->remote_key_dist & KEY_DIST_MASK)) {
|
if (test_bit(SMP_FLAG_INITIATOR, &smp->flags) &&
|
||||||
|
(smp->remote_key_dist & KEY_DIST_MASK)) {
|
||||||
smp_allow_key_dist(smp);
|
smp_allow_key_dist(smp);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
req = (void *) &smp->preq[1];
|
req = (void *) &smp->preq[1];
|
||||||
|
|
||||||
if (hcon->out) {
|
if (test_bit(SMP_FLAG_INITIATOR, &smp->flags)) {
|
||||||
keydist = &rsp->init_key_dist;
|
keydist = &rsp->init_key_dist;
|
||||||
*keydist &= req->init_key_dist;
|
*keydist &= req->init_key_dist;
|
||||||
} else {
|
} else {
|
||||||
|
@ -1427,7 +1429,7 @@ static int sc_mackey_and_ltk(struct smp_chan *smp, u8 mackey[16], u8 ltk[16])
|
||||||
struct hci_conn *hcon = smp->conn->hcon;
|
struct hci_conn *hcon = smp->conn->hcon;
|
||||||
u8 *na, *nb, a[7], b[7];
|
u8 *na, *nb, a[7], b[7];
|
||||||
|
|
||||||
if (hcon->out) {
|
if (test_bit(SMP_FLAG_INITIATOR, &smp->flags)) {
|
||||||
na = smp->prnd;
|
na = smp->prnd;
|
||||||
nb = smp->rrnd;
|
nb = smp->rrnd;
|
||||||
} else {
|
} else {
|
||||||
|
@ -1455,7 +1457,7 @@ static void sc_dhkey_check(struct smp_chan *smp)
|
||||||
a[6] = hcon->init_addr_type;
|
a[6] = hcon->init_addr_type;
|
||||||
b[6] = hcon->resp_addr_type;
|
b[6] = hcon->resp_addr_type;
|
||||||
|
|
||||||
if (hcon->out) {
|
if (test_bit(SMP_FLAG_INITIATOR, &smp->flags)) {
|
||||||
local_addr = a;
|
local_addr = a;
|
||||||
remote_addr = b;
|
remote_addr = b;
|
||||||
memcpy(io_cap, &smp->preq[1], 3);
|
memcpy(io_cap, &smp->preq[1], 3);
|
||||||
|
@ -1534,7 +1536,7 @@ static u8 sc_passkey_round(struct smp_chan *smp, u8 smp_op)
|
||||||
/* The round is only complete when the initiator
|
/* The round is only complete when the initiator
|
||||||
* receives pairing random.
|
* receives pairing random.
|
||||||
*/
|
*/
|
||||||
if (!hcon->out) {
|
if (!test_bit(SMP_FLAG_INITIATOR, &smp->flags)) {
|
||||||
smp_send_cmd(conn, SMP_CMD_PAIRING_RANDOM,
|
smp_send_cmd(conn, SMP_CMD_PAIRING_RANDOM,
|
||||||
sizeof(smp->prnd), smp->prnd);
|
sizeof(smp->prnd), smp->prnd);
|
||||||
if (smp->passkey_round == 20)
|
if (smp->passkey_round == 20)
|
||||||
|
@ -1562,7 +1564,7 @@ static u8 sc_passkey_round(struct smp_chan *smp, u8 smp_op)
|
||||||
|
|
||||||
SMP_ALLOW_CMD(smp, SMP_CMD_PAIRING_RANDOM);
|
SMP_ALLOW_CMD(smp, SMP_CMD_PAIRING_RANDOM);
|
||||||
|
|
||||||
if (hcon->out) {
|
if (test_bit(SMP_FLAG_INITIATOR, &smp->flags)) {
|
||||||
smp_send_cmd(conn, SMP_CMD_PAIRING_RANDOM,
|
smp_send_cmd(conn, SMP_CMD_PAIRING_RANDOM,
|
||||||
sizeof(smp->prnd), smp->prnd);
|
sizeof(smp->prnd), smp->prnd);
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -1573,7 +1575,7 @@ static u8 sc_passkey_round(struct smp_chan *smp, u8 smp_op)
|
||||||
case SMP_CMD_PUBLIC_KEY:
|
case SMP_CMD_PUBLIC_KEY:
|
||||||
default:
|
default:
|
||||||
/* Initiating device starts the round */
|
/* Initiating device starts the round */
|
||||||
if (!hcon->out)
|
if (!test_bit(SMP_FLAG_INITIATOR, &smp->flags))
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
bt_dev_dbg(hdev, "Starting passkey round %u",
|
bt_dev_dbg(hdev, "Starting passkey round %u",
|
||||||
|
@ -1618,7 +1620,7 @@ static int sc_user_reply(struct smp_chan *smp, u16 mgmt_op, __le32 passkey)
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Initiator sends DHKey check first */
|
/* Initiator sends DHKey check first */
|
||||||
if (hcon->out) {
|
if (test_bit(SMP_FLAG_INITIATOR, &smp->flags)) {
|
||||||
sc_dhkey_check(smp);
|
sc_dhkey_check(smp);
|
||||||
SMP_ALLOW_CMD(smp, SMP_CMD_DHKEY_CHECK);
|
SMP_ALLOW_CMD(smp, SMP_CMD_DHKEY_CHECK);
|
||||||
} else if (test_and_clear_bit(SMP_FLAG_DHKEY_PENDING, &smp->flags)) {
|
} else if (test_and_clear_bit(SMP_FLAG_DHKEY_PENDING, &smp->flags)) {
|
||||||
|
@ -1741,7 +1743,7 @@ static u8 smp_cmd_pairing_req(struct l2cap_conn *conn, struct sk_buff *skb)
|
||||||
struct smp_cmd_pairing rsp, *req = (void *) skb->data;
|
struct smp_cmd_pairing rsp, *req = (void *) skb->data;
|
||||||
struct l2cap_chan *chan = conn->smp;
|
struct l2cap_chan *chan = conn->smp;
|
||||||
struct hci_dev *hdev = conn->hcon->hdev;
|
struct hci_dev *hdev = conn->hcon->hdev;
|
||||||
struct smp_chan *smp;
|
struct smp_chan *smp = chan->data;
|
||||||
u8 key_size, auth, sec_level;
|
u8 key_size, auth, sec_level;
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
|
@ -1750,16 +1752,14 @@ static u8 smp_cmd_pairing_req(struct l2cap_conn *conn, struct sk_buff *skb)
|
||||||
if (skb->len < sizeof(*req))
|
if (skb->len < sizeof(*req))
|
||||||
return SMP_INVALID_PARAMS;
|
return SMP_INVALID_PARAMS;
|
||||||
|
|
||||||
if (conn->hcon->role != HCI_ROLE_SLAVE)
|
if (smp && test_bit(SMP_FLAG_INITIATOR, &smp->flags))
|
||||||
return SMP_CMD_NOTSUPP;
|
return SMP_CMD_NOTSUPP;
|
||||||
|
|
||||||
if (!chan->data)
|
if (!smp) {
|
||||||
smp = smp_chan_create(conn);
|
smp = smp_chan_create(conn);
|
||||||
else
|
|
||||||
smp = chan->data;
|
|
||||||
|
|
||||||
if (!smp)
|
if (!smp)
|
||||||
return SMP_UNSPECIFIED;
|
return SMP_UNSPECIFIED;
|
||||||
|
}
|
||||||
|
|
||||||
/* We didn't start the pairing, so match remote */
|
/* We didn't start the pairing, so match remote */
|
||||||
auth = req->auth_req & AUTH_REQ_MASK(hdev);
|
auth = req->auth_req & AUTH_REQ_MASK(hdev);
|
||||||
|
@ -1941,7 +1941,7 @@ static u8 smp_cmd_pairing_rsp(struct l2cap_conn *conn, struct sk_buff *skb)
|
||||||
if (skb->len < sizeof(*rsp))
|
if (skb->len < sizeof(*rsp))
|
||||||
return SMP_INVALID_PARAMS;
|
return SMP_INVALID_PARAMS;
|
||||||
|
|
||||||
if (conn->hcon->role != HCI_ROLE_MASTER)
|
if (!test_bit(SMP_FLAG_INITIATOR, &smp->flags))
|
||||||
return SMP_CMD_NOTSUPP;
|
return SMP_CMD_NOTSUPP;
|
||||||
|
|
||||||
skb_pull(skb, sizeof(*rsp));
|
skb_pull(skb, sizeof(*rsp));
|
||||||
|
@ -2036,7 +2036,7 @@ static u8 sc_check_confirm(struct smp_chan *smp)
|
||||||
if (smp->method == REQ_PASSKEY || smp->method == DSP_PASSKEY)
|
if (smp->method == REQ_PASSKEY || smp->method == DSP_PASSKEY)
|
||||||
return sc_passkey_round(smp, SMP_CMD_PAIRING_CONFIRM);
|
return sc_passkey_round(smp, SMP_CMD_PAIRING_CONFIRM);
|
||||||
|
|
||||||
if (conn->hcon->out) {
|
if (test_bit(SMP_FLAG_INITIATOR, &smp->flags)) {
|
||||||
smp_send_cmd(conn, SMP_CMD_PAIRING_RANDOM, sizeof(smp->prnd),
|
smp_send_cmd(conn, SMP_CMD_PAIRING_RANDOM, sizeof(smp->prnd),
|
||||||
smp->prnd);
|
smp->prnd);
|
||||||
SMP_ALLOW_CMD(smp, SMP_CMD_PAIRING_RANDOM);
|
SMP_ALLOW_CMD(smp, SMP_CMD_PAIRING_RANDOM);
|
||||||
|
@ -2058,7 +2058,7 @@ static int fixup_sc_false_positive(struct smp_chan *smp)
|
||||||
u8 auth;
|
u8 auth;
|
||||||
|
|
||||||
/* The issue is only observed when we're in responder role */
|
/* The issue is only observed when we're in responder role */
|
||||||
if (hcon->out)
|
if (test_bit(SMP_FLAG_INITIATOR, &smp->flags))
|
||||||
return SMP_UNSPECIFIED;
|
return SMP_UNSPECIFIED;
|
||||||
|
|
||||||
if (hci_dev_test_flag(hdev, HCI_SC_ONLY)) {
|
if (hci_dev_test_flag(hdev, HCI_SC_ONLY)) {
|
||||||
|
@ -2094,7 +2094,8 @@ static u8 smp_cmd_pairing_confirm(struct l2cap_conn *conn, struct sk_buff *skb)
|
||||||
struct hci_dev *hdev = hcon->hdev;
|
struct hci_dev *hdev = hcon->hdev;
|
||||||
|
|
||||||
bt_dev_dbg(hdev, "conn %p %s", conn,
|
bt_dev_dbg(hdev, "conn %p %s", conn,
|
||||||
hcon->out ? "initiator" : "responder");
|
test_bit(SMP_FLAG_INITIATOR, &smp->flags) ? "initiator" :
|
||||||
|
"responder");
|
||||||
|
|
||||||
if (skb->len < sizeof(smp->pcnf))
|
if (skb->len < sizeof(smp->pcnf))
|
||||||
return SMP_INVALID_PARAMS;
|
return SMP_INVALID_PARAMS;
|
||||||
|
@ -2116,7 +2117,7 @@ static u8 smp_cmd_pairing_confirm(struct l2cap_conn *conn, struct sk_buff *skb)
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (conn->hcon->out) {
|
if (test_bit(SMP_FLAG_INITIATOR, &smp->flags)) {
|
||||||
smp_send_cmd(conn, SMP_CMD_PAIRING_RANDOM, sizeof(smp->prnd),
|
smp_send_cmd(conn, SMP_CMD_PAIRING_RANDOM, sizeof(smp->prnd),
|
||||||
smp->prnd);
|
smp->prnd);
|
||||||
SMP_ALLOW_CMD(smp, SMP_CMD_PAIRING_RANDOM);
|
SMP_ALLOW_CMD(smp, SMP_CMD_PAIRING_RANDOM);
|
||||||
|
@ -2151,7 +2152,7 @@ static u8 smp_cmd_pairing_random(struct l2cap_conn *conn, struct sk_buff *skb)
|
||||||
if (!test_bit(SMP_FLAG_SC, &smp->flags))
|
if (!test_bit(SMP_FLAG_SC, &smp->flags))
|
||||||
return smp_random(smp);
|
return smp_random(smp);
|
||||||
|
|
||||||
if (hcon->out) {
|
if (test_bit(SMP_FLAG_INITIATOR, &smp->flags)) {
|
||||||
pkax = smp->local_pk;
|
pkax = smp->local_pk;
|
||||||
pkbx = smp->remote_pk;
|
pkbx = smp->remote_pk;
|
||||||
na = smp->prnd;
|
na = smp->prnd;
|
||||||
|
@ -2164,7 +2165,7 @@ static u8 smp_cmd_pairing_random(struct l2cap_conn *conn, struct sk_buff *skb)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (smp->method == REQ_OOB) {
|
if (smp->method == REQ_OOB) {
|
||||||
if (!hcon->out)
|
if (!test_bit(SMP_FLAG_INITIATOR, &smp->flags))
|
||||||
smp_send_cmd(conn, SMP_CMD_PAIRING_RANDOM,
|
smp_send_cmd(conn, SMP_CMD_PAIRING_RANDOM,
|
||||||
sizeof(smp->prnd), smp->prnd);
|
sizeof(smp->prnd), smp->prnd);
|
||||||
SMP_ALLOW_CMD(smp, SMP_CMD_DHKEY_CHECK);
|
SMP_ALLOW_CMD(smp, SMP_CMD_DHKEY_CHECK);
|
||||||
|
@ -2175,7 +2176,7 @@ static u8 smp_cmd_pairing_random(struct l2cap_conn *conn, struct sk_buff *skb)
|
||||||
if (smp->method == REQ_PASSKEY || smp->method == DSP_PASSKEY)
|
if (smp->method == REQ_PASSKEY || smp->method == DSP_PASSKEY)
|
||||||
return sc_passkey_round(smp, SMP_CMD_PAIRING_RANDOM);
|
return sc_passkey_round(smp, SMP_CMD_PAIRING_RANDOM);
|
||||||
|
|
||||||
if (hcon->out) {
|
if (test_bit(SMP_FLAG_INITIATOR, &smp->flags)) {
|
||||||
u8 cfm[16];
|
u8 cfm[16];
|
||||||
|
|
||||||
err = smp_f4(smp->tfm_cmac, smp->remote_pk, smp->local_pk,
|
err = smp_f4(smp->tfm_cmac, smp->remote_pk, smp->local_pk,
|
||||||
|
@ -2216,7 +2217,7 @@ mackey_and_ltk:
|
||||||
return SMP_UNSPECIFIED;
|
return SMP_UNSPECIFIED;
|
||||||
|
|
||||||
if (smp->method == REQ_OOB) {
|
if (smp->method == REQ_OOB) {
|
||||||
if (hcon->out) {
|
if (test_bit(SMP_FLAG_INITIATOR, &smp->flags)) {
|
||||||
sc_dhkey_check(smp);
|
sc_dhkey_check(smp);
|
||||||
SMP_ALLOW_CMD(smp, SMP_CMD_DHKEY_CHECK);
|
SMP_ALLOW_CMD(smp, SMP_CMD_DHKEY_CHECK);
|
||||||
}
|
}
|
||||||
|
@ -2290,10 +2291,27 @@ bool smp_sufficient_security(struct hci_conn *hcon, u8 sec_level,
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void smp_send_pairing_req(struct smp_chan *smp, __u8 auth)
|
||||||
|
{
|
||||||
|
struct smp_cmd_pairing cp;
|
||||||
|
|
||||||
|
if (smp->conn->hcon->type == ACL_LINK)
|
||||||
|
build_bredr_pairing_cmd(smp, &cp, NULL);
|
||||||
|
else
|
||||||
|
build_pairing_cmd(smp->conn, &cp, NULL, auth);
|
||||||
|
|
||||||
|
smp->preq[0] = SMP_CMD_PAIRING_REQ;
|
||||||
|
memcpy(&smp->preq[1], &cp, sizeof(cp));
|
||||||
|
|
||||||
|
smp_send_cmd(smp->conn, SMP_CMD_PAIRING_REQ, sizeof(cp), &cp);
|
||||||
|
SMP_ALLOW_CMD(smp, SMP_CMD_PAIRING_RSP);
|
||||||
|
|
||||||
|
set_bit(SMP_FLAG_INITIATOR, &smp->flags);
|
||||||
|
}
|
||||||
|
|
||||||
static u8 smp_cmd_security_req(struct l2cap_conn *conn, struct sk_buff *skb)
|
static u8 smp_cmd_security_req(struct l2cap_conn *conn, struct sk_buff *skb)
|
||||||
{
|
{
|
||||||
struct smp_cmd_security_req *rp = (void *) skb->data;
|
struct smp_cmd_security_req *rp = (void *) skb->data;
|
||||||
struct smp_cmd_pairing cp;
|
|
||||||
struct hci_conn *hcon = conn->hcon;
|
struct hci_conn *hcon = conn->hcon;
|
||||||
struct hci_dev *hdev = hcon->hdev;
|
struct hci_dev *hdev = hcon->hdev;
|
||||||
struct smp_chan *smp;
|
struct smp_chan *smp;
|
||||||
|
@ -2342,18 +2360,22 @@ static u8 smp_cmd_security_req(struct l2cap_conn *conn, struct sk_buff *skb)
|
||||||
|
|
||||||
skb_pull(skb, sizeof(*rp));
|
skb_pull(skb, sizeof(*rp));
|
||||||
|
|
||||||
memset(&cp, 0, sizeof(cp));
|
smp_send_pairing_req(smp, auth);
|
||||||
build_pairing_cmd(conn, &cp, NULL, auth);
|
|
||||||
|
|
||||||
smp->preq[0] = SMP_CMD_PAIRING_REQ;
|
|
||||||
memcpy(&smp->preq[1], &cp, sizeof(cp));
|
|
||||||
|
|
||||||
smp_send_cmd(conn, SMP_CMD_PAIRING_REQ, sizeof(cp), &cp);
|
|
||||||
SMP_ALLOW_CMD(smp, SMP_CMD_PAIRING_RSP);
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void smp_send_security_req(struct smp_chan *smp, __u8 auth)
|
||||||
|
{
|
||||||
|
struct smp_cmd_security_req cp;
|
||||||
|
|
||||||
|
cp.auth_req = auth;
|
||||||
|
smp_send_cmd(smp->conn, SMP_CMD_SECURITY_REQ, sizeof(cp), &cp);
|
||||||
|
SMP_ALLOW_CMD(smp, SMP_CMD_PAIRING_REQ);
|
||||||
|
|
||||||
|
clear_bit(SMP_FLAG_INITIATOR, &smp->flags);
|
||||||
|
}
|
||||||
|
|
||||||
int smp_conn_security(struct hci_conn *hcon, __u8 sec_level)
|
int smp_conn_security(struct hci_conn *hcon, __u8 sec_level)
|
||||||
{
|
{
|
||||||
struct l2cap_conn *conn = hcon->l2cap_data;
|
struct l2cap_conn *conn = hcon->l2cap_data;
|
||||||
|
@ -2422,23 +2444,11 @@ int smp_conn_security(struct hci_conn *hcon, __u8 sec_level)
|
||||||
authreq |= SMP_AUTH_MITM;
|
authreq |= SMP_AUTH_MITM;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (hcon->role == HCI_ROLE_MASTER) {
|
if (hcon->role == HCI_ROLE_MASTER)
|
||||||
struct smp_cmd_pairing cp;
|
smp_send_pairing_req(smp, authreq);
|
||||||
|
else
|
||||||
|
smp_send_security_req(smp, authreq);
|
||||||
|
|
||||||
build_pairing_cmd(conn, &cp, NULL, authreq);
|
|
||||||
smp->preq[0] = SMP_CMD_PAIRING_REQ;
|
|
||||||
memcpy(&smp->preq[1], &cp, sizeof(cp));
|
|
||||||
|
|
||||||
smp_send_cmd(conn, SMP_CMD_PAIRING_REQ, sizeof(cp), &cp);
|
|
||||||
SMP_ALLOW_CMD(smp, SMP_CMD_PAIRING_RSP);
|
|
||||||
} else {
|
|
||||||
struct smp_cmd_security_req cp;
|
|
||||||
cp.auth_req = authreq;
|
|
||||||
smp_send_cmd(conn, SMP_CMD_SECURITY_REQ, sizeof(cp), &cp);
|
|
||||||
SMP_ALLOW_CMD(smp, SMP_CMD_PAIRING_REQ);
|
|
||||||
}
|
|
||||||
|
|
||||||
set_bit(SMP_FLAG_INITIATOR, &smp->flags);
|
|
||||||
ret = 0;
|
ret = 0;
|
||||||
|
|
||||||
unlock:
|
unlock:
|
||||||
|
@ -2689,8 +2699,6 @@ static int smp_cmd_sign_info(struct l2cap_conn *conn, struct sk_buff *skb)
|
||||||
|
|
||||||
static u8 sc_select_method(struct smp_chan *smp)
|
static u8 sc_select_method(struct smp_chan *smp)
|
||||||
{
|
{
|
||||||
struct l2cap_conn *conn = smp->conn;
|
|
||||||
struct hci_conn *hcon = conn->hcon;
|
|
||||||
struct smp_cmd_pairing *local, *remote;
|
struct smp_cmd_pairing *local, *remote;
|
||||||
u8 local_mitm, remote_mitm, local_io, remote_io, method;
|
u8 local_mitm, remote_mitm, local_io, remote_io, method;
|
||||||
|
|
||||||
|
@ -2703,7 +2711,7 @@ static u8 sc_select_method(struct smp_chan *smp)
|
||||||
* the "struct smp_cmd_pairing" from them we need to skip the
|
* the "struct smp_cmd_pairing" from them we need to skip the
|
||||||
* first byte which contains the opcode.
|
* first byte which contains the opcode.
|
||||||
*/
|
*/
|
||||||
if (hcon->out) {
|
if (test_bit(SMP_FLAG_INITIATOR, &smp->flags)) {
|
||||||
local = (void *) &smp->preq[1];
|
local = (void *) &smp->preq[1];
|
||||||
remote = (void *) &smp->prsp[1];
|
remote = (void *) &smp->prsp[1];
|
||||||
} else {
|
} else {
|
||||||
|
@ -2772,7 +2780,7 @@ static int smp_cmd_public_key(struct l2cap_conn *conn, struct sk_buff *skb)
|
||||||
/* Non-initiating device sends its public key after receiving
|
/* Non-initiating device sends its public key after receiving
|
||||||
* the key from the initiating device.
|
* the key from the initiating device.
|
||||||
*/
|
*/
|
||||||
if (!hcon->out) {
|
if (!test_bit(SMP_FLAG_INITIATOR, &smp->flags)) {
|
||||||
err = sc_send_public_key(smp);
|
err = sc_send_public_key(smp);
|
||||||
if (err)
|
if (err)
|
||||||
return err;
|
return err;
|
||||||
|
@ -2834,7 +2842,7 @@ static int smp_cmd_public_key(struct l2cap_conn *conn, struct sk_buff *skb)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (smp->method == REQ_OOB) {
|
if (smp->method == REQ_OOB) {
|
||||||
if (hcon->out)
|
if (test_bit(SMP_FLAG_INITIATOR, &smp->flags))
|
||||||
smp_send_cmd(conn, SMP_CMD_PAIRING_RANDOM,
|
smp_send_cmd(conn, SMP_CMD_PAIRING_RANDOM,
|
||||||
sizeof(smp->prnd), smp->prnd);
|
sizeof(smp->prnd), smp->prnd);
|
||||||
|
|
||||||
|
@ -2843,7 +2851,7 @@ static int smp_cmd_public_key(struct l2cap_conn *conn, struct sk_buff *skb)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (hcon->out)
|
if (test_bit(SMP_FLAG_INITIATOR, &smp->flags))
|
||||||
SMP_ALLOW_CMD(smp, SMP_CMD_PAIRING_CONFIRM);
|
SMP_ALLOW_CMD(smp, SMP_CMD_PAIRING_CONFIRM);
|
||||||
|
|
||||||
if (smp->method == REQ_PASSKEY) {
|
if (smp->method == REQ_PASSKEY) {
|
||||||
|
@ -2858,7 +2866,7 @@ static int smp_cmd_public_key(struct l2cap_conn *conn, struct sk_buff *skb)
|
||||||
/* The Initiating device waits for the non-initiating device to
|
/* The Initiating device waits for the non-initiating device to
|
||||||
* send the confirm value.
|
* send the confirm value.
|
||||||
*/
|
*/
|
||||||
if (conn->hcon->out)
|
if (test_bit(SMP_FLAG_INITIATOR, &smp->flags))
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
err = smp_f4(smp->tfm_cmac, smp->local_pk, smp->remote_pk, smp->prnd,
|
err = smp_f4(smp->tfm_cmac, smp->local_pk, smp->remote_pk, smp->prnd,
|
||||||
|
@ -2892,7 +2900,7 @@ static int smp_cmd_dhkey_check(struct l2cap_conn *conn, struct sk_buff *skb)
|
||||||
a[6] = hcon->init_addr_type;
|
a[6] = hcon->init_addr_type;
|
||||||
b[6] = hcon->resp_addr_type;
|
b[6] = hcon->resp_addr_type;
|
||||||
|
|
||||||
if (hcon->out) {
|
if (test_bit(SMP_FLAG_INITIATOR, &smp->flags)) {
|
||||||
local_addr = a;
|
local_addr = a;
|
||||||
remote_addr = b;
|
remote_addr = b;
|
||||||
memcpy(io_cap, &smp->prsp[1], 3);
|
memcpy(io_cap, &smp->prsp[1], 3);
|
||||||
|
@ -2917,7 +2925,7 @@ static int smp_cmd_dhkey_check(struct l2cap_conn *conn, struct sk_buff *skb)
|
||||||
if (crypto_memneq(check->e, e, 16))
|
if (crypto_memneq(check->e, e, 16))
|
||||||
return SMP_DHKEY_CHECK_FAILED;
|
return SMP_DHKEY_CHECK_FAILED;
|
||||||
|
|
||||||
if (!hcon->out) {
|
if (!test_bit(SMP_FLAG_INITIATOR, &smp->flags)) {
|
||||||
if (test_bit(SMP_FLAG_WAIT_USER, &smp->flags)) {
|
if (test_bit(SMP_FLAG_WAIT_USER, &smp->flags)) {
|
||||||
set_bit(SMP_FLAG_DHKEY_PENDING, &smp->flags);
|
set_bit(SMP_FLAG_DHKEY_PENDING, &smp->flags);
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -2929,7 +2937,7 @@ static int smp_cmd_dhkey_check(struct l2cap_conn *conn, struct sk_buff *skb)
|
||||||
|
|
||||||
sc_add_ltk(smp);
|
sc_add_ltk(smp);
|
||||||
|
|
||||||
if (hcon->out) {
|
if (test_bit(SMP_FLAG_INITIATOR, &smp->flags)) {
|
||||||
hci_le_start_enc(hcon, 0, 0, smp->tk, smp->enc_key_size);
|
hci_le_start_enc(hcon, 0, 0, smp->tk, smp->enc_key_size);
|
||||||
hcon->enc_key_size = smp->enc_key_size;
|
hcon->enc_key_size = smp->enc_key_size;
|
||||||
}
|
}
|
||||||
|
@ -3078,7 +3086,6 @@ static void bredr_pairing(struct l2cap_chan *chan)
|
||||||
struct l2cap_conn *conn = chan->conn;
|
struct l2cap_conn *conn = chan->conn;
|
||||||
struct hci_conn *hcon = conn->hcon;
|
struct hci_conn *hcon = conn->hcon;
|
||||||
struct hci_dev *hdev = hcon->hdev;
|
struct hci_dev *hdev = hcon->hdev;
|
||||||
struct smp_cmd_pairing req;
|
|
||||||
struct smp_chan *smp;
|
struct smp_chan *smp;
|
||||||
|
|
||||||
bt_dev_dbg(hdev, "chan %p", chan);
|
bt_dev_dbg(hdev, "chan %p", chan);
|
||||||
|
@ -3130,14 +3137,7 @@ static void bredr_pairing(struct l2cap_chan *chan)
|
||||||
|
|
||||||
bt_dev_dbg(hdev, "starting SMP over BR/EDR");
|
bt_dev_dbg(hdev, "starting SMP over BR/EDR");
|
||||||
|
|
||||||
/* Prepare and send the BR/EDR SMP Pairing Request */
|
smp_send_pairing_req(smp, 0x00);
|
||||||
build_bredr_pairing_cmd(smp, &req, NULL);
|
|
||||||
|
|
||||||
smp->preq[0] = SMP_CMD_PAIRING_REQ;
|
|
||||||
memcpy(&smp->preq[1], &req, sizeof(req));
|
|
||||||
|
|
||||||
smp_send_cmd(conn, SMP_CMD_PAIRING_REQ, sizeof(req), &req);
|
|
||||||
SMP_ALLOW_CMD(smp, SMP_CMD_PAIRING_RSP);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void smp_resume_cb(struct l2cap_chan *chan)
|
static void smp_resume_cb(struct l2cap_chan *chan)
|
||||||
|
|
Loading…
Add table
Reference in a new issue