Revert "Bluetooth: SMP: Fix assumption of Central always being Initiator"

This reverts commit 35cecaecda.
This commit is contained in:
Ksawlii 2024-11-24 00:23:52 +01:00
parent a40772fae5
commit 0c4e79d991

View file

@ -914,7 +914,7 @@ static int tk_request(struct l2cap_conn *conn, u8 remote_oob, u8 auth,
* Confirms and the responder Enters the passkey.
*/
if (smp->method == OVERLAP) {
if (test_bit(SMP_FLAG_INITIATOR, &smp->flags))
if (hcon->role == HCI_ROLE_MASTER)
smp->method = CFM_PASSKEY;
else
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);
if (test_bit(SMP_FLAG_INITIATOR, &smp->flags))
if (conn->hcon->out)
SMP_ALLOW_CMD(smp, SMP_CMD_PAIRING_CONFIRM);
else
SMP_ALLOW_CMD(smp, SMP_CMD_PAIRING_RANDOM);
@ -980,8 +980,7 @@ static u8 smp_random(struct smp_chan *smp)
int ret;
bt_dev_dbg(conn->hcon->hdev, "conn %p %s", conn,
test_bit(SMP_FLAG_INITIATOR, &smp->flags) ? "initiator" :
"responder");
conn->hcon->out ? "initiator" : "responder");
ret = smp_c1(smp->tk, smp->rrnd, smp->preq, smp->prsp,
hcon->init_addr_type, &hcon->init_addr,
@ -995,7 +994,7 @@ static u8 smp_random(struct smp_chan *smp)
return SMP_CONFIRM_FAILED;
}
if (test_bit(SMP_FLAG_INITIATOR, &smp->flags)) {
if (hcon->out) {
u8 stk[16];
__le64 rand = 0;
__le16 ediv = 0;
@ -1245,15 +1244,14 @@ static void smp_distribute_keys(struct smp_chan *smp)
rsp = (void *) &smp->prsp[1];
/* The responder sends its keys first */
if (test_bit(SMP_FLAG_INITIATOR, &smp->flags) &&
(smp->remote_key_dist & KEY_DIST_MASK)) {
if (hcon->out && (smp->remote_key_dist & KEY_DIST_MASK)) {
smp_allow_key_dist(smp);
return;
}
req = (void *) &smp->preq[1];
if (test_bit(SMP_FLAG_INITIATOR, &smp->flags)) {
if (hcon->out) {
keydist = &rsp->init_key_dist;
*keydist &= req->init_key_dist;
} else {
@ -1422,7 +1420,7 @@ static int sc_mackey_and_ltk(struct smp_chan *smp, u8 mackey[16], u8 ltk[16])
struct hci_conn *hcon = smp->conn->hcon;
u8 *na, *nb, a[7], b[7];
if (test_bit(SMP_FLAG_INITIATOR, &smp->flags)) {
if (hcon->out) {
na = smp->prnd;
nb = smp->rrnd;
} else {
@ -1450,7 +1448,7 @@ static void sc_dhkey_check(struct smp_chan *smp)
a[6] = hcon->init_addr_type;
b[6] = hcon->resp_addr_type;
if (test_bit(SMP_FLAG_INITIATOR, &smp->flags)) {
if (hcon->out) {
local_addr = a;
remote_addr = b;
memcpy(io_cap, &smp->preq[1], 3);
@ -1529,7 +1527,7 @@ static u8 sc_passkey_round(struct smp_chan *smp, u8 smp_op)
/* The round is only complete when the initiator
* receives pairing random.
*/
if (!test_bit(SMP_FLAG_INITIATOR, &smp->flags)) {
if (!hcon->out) {
smp_send_cmd(conn, SMP_CMD_PAIRING_RANDOM,
sizeof(smp->prnd), smp->prnd);
if (smp->passkey_round == 20)
@ -1557,7 +1555,7 @@ static u8 sc_passkey_round(struct smp_chan *smp, u8 smp_op)
SMP_ALLOW_CMD(smp, SMP_CMD_PAIRING_RANDOM);
if (test_bit(SMP_FLAG_INITIATOR, &smp->flags)) {
if (hcon->out) {
smp_send_cmd(conn, SMP_CMD_PAIRING_RANDOM,
sizeof(smp->prnd), smp->prnd);
return 0;
@ -1568,7 +1566,7 @@ static u8 sc_passkey_round(struct smp_chan *smp, u8 smp_op)
case SMP_CMD_PUBLIC_KEY:
default:
/* Initiating device starts the round */
if (!test_bit(SMP_FLAG_INITIATOR, &smp->flags))
if (!hcon->out)
return 0;
bt_dev_dbg(hdev, "Starting passkey round %u",
@ -1613,7 +1611,7 @@ static int sc_user_reply(struct smp_chan *smp, u16 mgmt_op, __le32 passkey)
}
/* Initiator sends DHKey check first */
if (test_bit(SMP_FLAG_INITIATOR, &smp->flags)) {
if (hcon->out) {
sc_dhkey_check(smp);
SMP_ALLOW_CMD(smp, SMP_CMD_DHKEY_CHECK);
} else if (test_and_clear_bit(SMP_FLAG_DHKEY_PENDING, &smp->flags)) {
@ -1736,7 +1734,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 l2cap_chan *chan = conn->smp;
struct hci_dev *hdev = conn->hcon->hdev;
struct smp_chan *smp = chan->data;
struct smp_chan *smp;
u8 key_size, auth, sec_level;
int ret;
@ -1745,14 +1743,16 @@ static u8 smp_cmd_pairing_req(struct l2cap_conn *conn, struct sk_buff *skb)
if (skb->len < sizeof(*req))
return SMP_INVALID_PARAMS;
if (smp && test_bit(SMP_FLAG_INITIATOR, &smp->flags))
if (conn->hcon->role != HCI_ROLE_SLAVE)
return SMP_CMD_NOTSUPP;
if (!smp) {
if (!chan->data)
smp = smp_chan_create(conn);
if (!smp)
return SMP_UNSPECIFIED;
}
else
smp = chan->data;
if (!smp)
return SMP_UNSPECIFIED;
/* We didn't start the pairing, so match remote */
auth = req->auth_req & AUTH_REQ_MASK(hdev);
@ -1934,7 +1934,7 @@ static u8 smp_cmd_pairing_rsp(struct l2cap_conn *conn, struct sk_buff *skb)
if (skb->len < sizeof(*rsp))
return SMP_INVALID_PARAMS;
if (!test_bit(SMP_FLAG_INITIATOR, &smp->flags))
if (conn->hcon->role != HCI_ROLE_MASTER)
return SMP_CMD_NOTSUPP;
skb_pull(skb, sizeof(*rsp));
@ -2029,7 +2029,7 @@ static u8 sc_check_confirm(struct smp_chan *smp)
if (smp->method == REQ_PASSKEY || smp->method == DSP_PASSKEY)
return sc_passkey_round(smp, SMP_CMD_PAIRING_CONFIRM);
if (test_bit(SMP_FLAG_INITIATOR, &smp->flags)) {
if (conn->hcon->out) {
smp_send_cmd(conn, SMP_CMD_PAIRING_RANDOM, sizeof(smp->prnd),
smp->prnd);
SMP_ALLOW_CMD(smp, SMP_CMD_PAIRING_RANDOM);
@ -2051,7 +2051,7 @@ static int fixup_sc_false_positive(struct smp_chan *smp)
u8 auth;
/* The issue is only observed when we're in responder role */
if (test_bit(SMP_FLAG_INITIATOR, &smp->flags))
if (hcon->out)
return SMP_UNSPECIFIED;
if (hci_dev_test_flag(hdev, HCI_SC_ONLY)) {
@ -2087,8 +2087,7 @@ static u8 smp_cmd_pairing_confirm(struct l2cap_conn *conn, struct sk_buff *skb)
struct hci_dev *hdev = hcon->hdev;
bt_dev_dbg(hdev, "conn %p %s", conn,
test_bit(SMP_FLAG_INITIATOR, &smp->flags) ? "initiator" :
"responder");
hcon->out ? "initiator" : "responder");
if (skb->len < sizeof(smp->pcnf))
return SMP_INVALID_PARAMS;
@ -2110,7 +2109,7 @@ static u8 smp_cmd_pairing_confirm(struct l2cap_conn *conn, struct sk_buff *skb)
return ret;
}
if (test_bit(SMP_FLAG_INITIATOR, &smp->flags)) {
if (conn->hcon->out) {
smp_send_cmd(conn, SMP_CMD_PAIRING_RANDOM, sizeof(smp->prnd),
smp->prnd);
SMP_ALLOW_CMD(smp, SMP_CMD_PAIRING_RANDOM);
@ -2145,7 +2144,7 @@ static u8 smp_cmd_pairing_random(struct l2cap_conn *conn, struct sk_buff *skb)
if (!test_bit(SMP_FLAG_SC, &smp->flags))
return smp_random(smp);
if (test_bit(SMP_FLAG_INITIATOR, &smp->flags)) {
if (hcon->out) {
pkax = smp->local_pk;
pkbx = smp->remote_pk;
na = smp->prnd;
@ -2158,7 +2157,7 @@ static u8 smp_cmd_pairing_random(struct l2cap_conn *conn, struct sk_buff *skb)
}
if (smp->method == REQ_OOB) {
if (!test_bit(SMP_FLAG_INITIATOR, &smp->flags))
if (!hcon->out)
smp_send_cmd(conn, SMP_CMD_PAIRING_RANDOM,
sizeof(smp->prnd), smp->prnd);
SMP_ALLOW_CMD(smp, SMP_CMD_DHKEY_CHECK);
@ -2169,7 +2168,7 @@ static u8 smp_cmd_pairing_random(struct l2cap_conn *conn, struct sk_buff *skb)
if (smp->method == REQ_PASSKEY || smp->method == DSP_PASSKEY)
return sc_passkey_round(smp, SMP_CMD_PAIRING_RANDOM);
if (test_bit(SMP_FLAG_INITIATOR, &smp->flags)) {
if (hcon->out) {
u8 cfm[16];
err = smp_f4(smp->tfm_cmac, smp->remote_pk, smp->local_pk,
@ -2210,7 +2209,7 @@ mackey_and_ltk:
return SMP_UNSPECIFIED;
if (smp->method == REQ_OOB) {
if (test_bit(SMP_FLAG_INITIATOR, &smp->flags)) {
if (hcon->out) {
sc_dhkey_check(smp);
SMP_ALLOW_CMD(smp, SMP_CMD_DHKEY_CHECK);
}
@ -2284,27 +2283,10 @@ bool smp_sufficient_security(struct hci_conn *hcon, u8 sec_level,
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)
{
struct smp_cmd_security_req *rp = (void *) skb->data;
struct smp_cmd_pairing cp;
struct hci_conn *hcon = conn->hcon;
struct hci_dev *hdev = hcon->hdev;
struct smp_chan *smp;
@ -2353,22 +2335,18 @@ static u8 smp_cmd_security_req(struct l2cap_conn *conn, struct sk_buff *skb)
skb_pull(skb, sizeof(*rp));
smp_send_pairing_req(smp, auth);
memset(&cp, 0, sizeof(cp));
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;
}
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)
{
struct l2cap_conn *conn = hcon->l2cap_data;
@ -2437,11 +2415,23 @@ int smp_conn_security(struct hci_conn *hcon, __u8 sec_level)
authreq |= SMP_AUTH_MITM;
}
if (hcon->role == HCI_ROLE_MASTER)
smp_send_pairing_req(smp, authreq);
else
smp_send_security_req(smp, authreq);
if (hcon->role == HCI_ROLE_MASTER) {
struct smp_cmd_pairing cp;
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;
unlock:
@ -2692,6 +2682,8 @@ static int smp_cmd_sign_info(struct l2cap_conn *conn, struct sk_buff *skb)
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;
u8 local_mitm, remote_mitm, local_io, remote_io, method;
@ -2704,7 +2696,7 @@ static u8 sc_select_method(struct smp_chan *smp)
* the "struct smp_cmd_pairing" from them we need to skip the
* first byte which contains the opcode.
*/
if (test_bit(SMP_FLAG_INITIATOR, &smp->flags)) {
if (hcon->out) {
local = (void *) &smp->preq[1];
remote = (void *) &smp->prsp[1];
} else {
@ -2773,7 +2765,7 @@ static int smp_cmd_public_key(struct l2cap_conn *conn, struct sk_buff *skb)
/* Non-initiating device sends its public key after receiving
* the key from the initiating device.
*/
if (!test_bit(SMP_FLAG_INITIATOR, &smp->flags)) {
if (!hcon->out) {
err = sc_send_public_key(smp);
if (err)
return err;
@ -2835,7 +2827,7 @@ static int smp_cmd_public_key(struct l2cap_conn *conn, struct sk_buff *skb)
}
if (smp->method == REQ_OOB) {
if (test_bit(SMP_FLAG_INITIATOR, &smp->flags))
if (hcon->out)
smp_send_cmd(conn, SMP_CMD_PAIRING_RANDOM,
sizeof(smp->prnd), smp->prnd);
@ -2844,7 +2836,7 @@ static int smp_cmd_public_key(struct l2cap_conn *conn, struct sk_buff *skb)
return 0;
}
if (test_bit(SMP_FLAG_INITIATOR, &smp->flags))
if (hcon->out)
SMP_ALLOW_CMD(smp, SMP_CMD_PAIRING_CONFIRM);
if (smp->method == REQ_PASSKEY) {
@ -2859,7 +2851,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
* send the confirm value.
*/
if (test_bit(SMP_FLAG_INITIATOR, &smp->flags))
if (conn->hcon->out)
return 0;
err = smp_f4(smp->tfm_cmac, smp->local_pk, smp->remote_pk, smp->prnd,
@ -2893,7 +2885,7 @@ static int smp_cmd_dhkey_check(struct l2cap_conn *conn, struct sk_buff *skb)
a[6] = hcon->init_addr_type;
b[6] = hcon->resp_addr_type;
if (test_bit(SMP_FLAG_INITIATOR, &smp->flags)) {
if (hcon->out) {
local_addr = a;
remote_addr = b;
memcpy(io_cap, &smp->prsp[1], 3);
@ -2918,7 +2910,7 @@ static int smp_cmd_dhkey_check(struct l2cap_conn *conn, struct sk_buff *skb)
if (crypto_memneq(check->e, e, 16))
return SMP_DHKEY_CHECK_FAILED;
if (!test_bit(SMP_FLAG_INITIATOR, &smp->flags)) {
if (!hcon->out) {
if (test_bit(SMP_FLAG_WAIT_USER, &smp->flags)) {
set_bit(SMP_FLAG_DHKEY_PENDING, &smp->flags);
return 0;
@ -2930,7 +2922,7 @@ static int smp_cmd_dhkey_check(struct l2cap_conn *conn, struct sk_buff *skb)
sc_add_ltk(smp);
if (test_bit(SMP_FLAG_INITIATOR, &smp->flags)) {
if (hcon->out) {
hci_le_start_enc(hcon, 0, 0, smp->tk, smp->enc_key_size);
hcon->enc_key_size = smp->enc_key_size;
}
@ -3079,6 +3071,7 @@ static void bredr_pairing(struct l2cap_chan *chan)
struct l2cap_conn *conn = chan->conn;
struct hci_conn *hcon = conn->hcon;
struct hci_dev *hdev = hcon->hdev;
struct smp_cmd_pairing req;
struct smp_chan *smp;
bt_dev_dbg(hdev, "chan %p", chan);
@ -3130,7 +3123,14 @@ static void bredr_pairing(struct l2cap_chan *chan)
bt_dev_dbg(hdev, "starting SMP over BR/EDR");
smp_send_pairing_req(smp, 0x00);
/* Prepare and send the BR/EDR SMP Pairing Request */
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)