2011-11-10 20:52:52

by Brian Gix

[permalink] [raw]
Subject: [PATCH 0/3] Bluetooth: Add Passkey Entry and User Confirm hooks for SMP

While I actually prefer Johan's method of adding the User Confirm MGMT code,
with it's code re-use between user_confirm_reply, and user_confirm_neg_reply,
I have broken the user_passkey_reply out from user_passkey_neg_reply, and
added an additional patch to hook in the HCI/SSP based usage of passkeys.

This makes sense, I suppose, since the regular and neg replies for passkeys
are different sizes.

Passkey's only come into play only if our OI_CAP happens to be
KeyboardOnly (for BR/EDR/LER) or DisplayKeyboard (LE only).

So the summary of the changes is:

1. Addition of BR/EDR vs LE breakout in user_confirm_reply
1.1 Adds SMP placeholder
1.2 Keeps Johan's confirm_reply & confirm_neg_reply structure.
1.2.1 Johan can defend or change that himself, but the existing code works.

2. Addition of user_passkey_reply, with both BR/EDR (SSP) and LE (SMP) handling
2.1 Adds approriate SSP HCI opcodes
2.2 Adds appropriate MGMT opcodes
2.3 Adds SMP placeholder
2.4 Seperate paths for passkey_reply & passkey_neg_reply

3. Addition of HCI event handling and forwarding for the appropriate BR/EDR SSP events


--
Brian Gix
[email protected]
Employee of Qualcomm Innovation Center, Inc.
Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum



2011-11-16 17:55:08

by Gustavo Padovan

[permalink] [raw]
Subject: Re: [PATCH 2/3] Bluetooth: Add MGMT opcode for User Passkey entry

* Brian Gix <[email protected]> [2011-11-10 12:52:54 -0800]:

> Signed-off-by: Brian Gix <[email protected]>


Same here, better commit message please.

Gustavo

2011-11-16 17:54:27

by Gustavo Padovan

[permalink] [raw]
Subject: Re: [PATCH 1/3] Bluetooth: Add SMP support to user_confirm_reply

* Brian Gix <[email protected]> [2011-11-10 12:52:53 -0800]:

> to enable User Confirmation during LE-SMP pairing.

Can I get a better commit message here as Marcel suggested?
And please use -v2, -v3 and so on to version your patch sets to help us
identify them.

Gustavo

2011-11-10 20:52:55

by Brian Gix

[permalink] [raw]
Subject: [PATCH 3/3] Bluetooth: Add User Passkey entry to HCI Events

Signed-off-by: Brian Gix <[email protected]>
---
include/net/bluetooth/hci.h | 5 +++
include/net/bluetooth/hci_core.h | 4 ++
net/bluetooth/hci_event.c | 62 ++++++++++++++++++++++++++++++++++++++
3 files changed, 71 insertions(+), 0 deletions(-)

diff --git a/include/net/bluetooth/hci.h b/include/net/bluetooth/hci.h
index ac107b5..d1af139 100644
--- a/include/net/bluetooth/hci.h
+++ b/include/net/bluetooth/hci.h
@@ -1084,6 +1084,11 @@ struct hci_ev_user_confirm_req {
__le32 passkey;
} __packed;

+#define HCI_EV_USER_PASSKEY_REQUEST 0x34
+struct hci_ev_user_passkey_req {
+ bdaddr_t bdaddr;
+} __packed;
+
#define HCI_EV_REMOTE_OOB_DATA_REQUEST 0x35
struct hci_ev_remote_oob_data_request {
bdaddr_t bdaddr;
diff --git a/include/net/bluetooth/hci_core.h b/include/net/bluetooth/hci_core.h
index 0a5a05d..943f4fc 100644
--- a/include/net/bluetooth/hci_core.h
+++ b/include/net/bluetooth/hci_core.h
@@ -931,6 +931,10 @@ int mgmt_user_confirm_reply_complete(struct hci_dev *hdev, bdaddr_t *bdaddr,
u8 status);
int mgmt_user_confirm_neg_reply_complete(struct hci_dev *hdev,
bdaddr_t *bdaddr, u8 status);
+int mgmt_user_passkey_reply_complete(struct hci_dev *hdev, bdaddr_t *bdaddr,
+ u8 status);
+int mgmt_user_passkey_neg_reply_complete(struct hci_dev *hdev,
+ bdaddr_t *bdaddr, u8 status);
int mgmt_auth_failed(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 status);
int mgmt_set_local_name_complete(struct hci_dev *hdev, u8 *name, u8 status);
int mgmt_read_local_oob_data_reply_complete(struct hci_dev *hdev, u8 *hash,
diff --git a/net/bluetooth/hci_event.c b/net/bluetooth/hci_event.c
index a89cf1f..3006058 100644
--- a/net/bluetooth/hci_event.c
+++ b/net/bluetooth/hci_event.c
@@ -927,6 +927,37 @@ static void hci_cc_user_confirm_neg_reply(struct hci_dev *hdev,
hci_dev_unlock(hdev);
}

+static void hci_cc_user_passkey_reply(struct hci_dev *hdev, struct sk_buff *skb)
+{
+ struct hci_rp_user_confirm_reply *rp = (void *) skb->data;
+
+ BT_DBG("%s status 0x%x", hdev->name, rp->status);
+
+ hci_dev_lock(hdev);
+
+ if (test_bit(HCI_MGMT, &hdev->flags))
+ mgmt_user_passkey_reply_complete(hdev, &rp->bdaddr,
+ rp->status);
+
+ hci_dev_unlock(hdev);
+}
+
+static void hci_cc_user_passkey_neg_reply(struct hci_dev *hdev,
+ struct sk_buff *skb)
+{
+ struct hci_rp_user_confirm_reply *rp = (void *) skb->data;
+
+ BT_DBG("%s status 0x%x", hdev->name, rp->status);
+
+ hci_dev_lock(hdev);
+
+ if (test_bit(HCI_MGMT, &hdev->flags))
+ mgmt_user_passkey_neg_reply_complete(hdev, &rp->bdaddr,
+ rp->status);
+
+ hci_dev_unlock(hdev);
+}
+
static void hci_cc_read_local_oob_data_reply(struct hci_dev *hdev,
struct sk_buff *skb)
{
@@ -2009,6 +2040,14 @@ static inline void hci_cmd_complete_evt(struct hci_dev *hdev, struct sk_buff *sk
hci_cc_user_confirm_neg_reply(hdev, skb);
break;

+ case HCI_OP_USER_PASSKEY_REPLY:
+ hci_cc_user_passkey_reply(hdev, skb);
+ break;
+
+ case HCI_OP_USER_PASSKEY_NEG_REPLY:
+ hci_cc_user_passkey_neg_reply(hdev, skb);
+ break;
+
case HCI_OP_LE_SET_SCAN_ENABLE:
hci_cc_le_set_scan_enable(hdev, skb);
break;
@@ -2768,6 +2807,25 @@ unlock:
hci_dev_unlock(hdev);
}

+static inline void hci_user_passkey_request_evt(struct hci_dev *hdev,
+ struct sk_buff *skb)
+{
+ struct hci_ev_user_passkey_req *ev = (void *) skb->data;
+
+ BT_DBG("%s", hdev->name);
+
+ hci_dev_lock(hdev);
+
+ /* Passkey Request is a degenerate case of User Confirm */
+ if (test_bit(HCI_MGMT, &hdev->flags))
+ mgmt_user_confirm_request(hdev, &ev->bdaddr, 0, 0);
+ else
+ hci_send_cmd(hdev, HCI_OP_USER_PASSKEY_NEG_REPLY,
+ sizeof(ev->bdaddr), &ev->bdaddr);
+
+ hci_dev_unlock(hdev);
+}
+
static inline void hci_simple_pair_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
{
struct hci_ev_simple_pair_complete *ev = (void *) skb->data;
@@ -3106,6 +3164,10 @@ void hci_event_packet(struct hci_dev *hdev, struct sk_buff *skb)
hci_user_confirm_request_evt(hdev, skb);
break;

+ case HCI_EV_USER_PASSKEY_REQUEST:
+ hci_user_passkey_request_evt(hdev, skb);
+ break;
+
case HCI_EV_SIMPLE_PAIR_COMPLETE:
hci_simple_pair_complete_evt(hdev, skb);
break;
--
1.7.7.2

--
Brian Gix
[email protected]
Employee of Qualcomm Innovation Center, Inc.
Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum

2011-11-10 20:52:54

by Brian Gix

[permalink] [raw]
Subject: [PATCH 2/3] Bluetooth: Add MGMT opcode for User Passkey entry

Signed-off-by: Brian Gix <[email protected]>
---
include/net/bluetooth/hci.h | 8 +++
include/net/bluetooth/mgmt.h | 11 +++
net/bluetooth/mgmt.c | 143 ++++++++++++++++++++++++++++++++++++++++++
3 files changed, 162 insertions(+), 0 deletions(-)

diff --git a/include/net/bluetooth/hci.h b/include/net/bluetooth/hci.h
index 139ce2a..ac107b5 100644
--- a/include/net/bluetooth/hci.h
+++ b/include/net/bluetooth/hci.h
@@ -453,6 +453,14 @@ struct hci_rp_user_confirm_reply {

#define HCI_OP_USER_CONFIRM_NEG_REPLY 0x042d

+#define HCI_OP_USER_PASSKEY_REPLY 0x042e
+struct hci_cp_user_passkey_reply {
+ bdaddr_t bdaddr;
+ __u32 passkey;
+} __packed;
+
+#define HCI_OP_USER_PASSKEY_NEG_REPLY 0x042f
+
#define HCI_OP_REMOTE_OOB_DATA_REPLY 0x0430
struct hci_cp_remote_oob_data_reply {
bdaddr_t bdaddr;
diff --git a/include/net/bluetooth/mgmt.h b/include/net/bluetooth/mgmt.h
index 3e320c9..d67683f 100644
--- a/include/net/bluetooth/mgmt.h
+++ b/include/net/bluetooth/mgmt.h
@@ -228,6 +228,17 @@ struct mgmt_cp_set_fast_connectable {
__u8 enable;
} __packed;

+#define MGMT_OP_USER_PASSKEY_REPLY 0x0020
+struct mgmt_cp_user_passkey_reply {
+ bdaddr_t bdaddr;
+ __le32 passkey;
+} __packed;
+
+#define MGMT_OP_USER_PASSKEY_NEG_REPLY 0x0021
+struct mgmt_cp_user_passkey_neg_reply {
+ bdaddr_t bdaddr;
+} __packed;
+
#define MGMT_EV_CMD_COMPLETE 0x0001
struct mgmt_ev_cmd_complete {
__le16 opcode;
diff --git a/net/bluetooth/mgmt.c b/net/bluetooth/mgmt.c
index 761d607..d5116c2 100644
--- a/net/bluetooth/mgmt.c
+++ b/net/bluetooth/mgmt.c
@@ -1482,6 +1482,128 @@ done:
return err;
}

+static int user_passkey_reply(struct sock *sk, u16 index, unsigned char *data,
+ u16 len)
+{
+ struct mgmt_cp_user_passkey_reply *cp = (void *) data;
+ struct pending_cmd *cmd;
+ struct hci_dev *hdev;
+ struct hci_conn *conn;
+ int err = 0;
+
+ BT_DBG("");
+
+ if (len != sizeof(*cp))
+ return cmd_status(sk, index, MGMT_OP_USER_PASSKEY_REPLY,
+ EINVAL);
+
+ hdev = hci_dev_get(index);
+ if (!hdev)
+ return cmd_status(sk, index, MGMT_OP_USER_PASSKEY_REPLY,
+ ENODEV);
+
+ hci_dev_lock_bh(hdev);
+
+ if (!test_bit(HCI_UP, &hdev->flags)) {
+ err = cmd_status(sk, index, MGMT_OP_USER_PASSKEY_REPLY,
+ ENETDOWN);
+ goto done;
+ }
+
+ /* Route command to HCI (if ACL Link) or SMP (if LE Link) */
+ conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &cp->bdaddr);
+ if (!conn) {
+ conn = hci_conn_hash_lookup_ba(hdev, LE_LINK, &cp->bdaddr);
+ if (!conn) {
+ err = cmd_status(sk, index, MGMT_OP_USER_PASSKEY_REPLY,
+ ENOTCONN);
+ goto done;
+ }
+
+ /* Forward Passkey response to SMP */
+
+ err = cmd_status(sk, index, MGMT_OP_USER_PASSKEY_REPLY, 0);
+ goto done;
+ }
+
+ cmd = mgmt_pending_add(sk, MGMT_OP_USER_PASSKEY_REPLY, hdev, data, len);
+ if (!cmd) {
+ err = -ENOMEM;
+ goto done;
+ }
+
+ err = hci_send_cmd(hdev, HCI_OP_USER_PASSKEY_REPLY, len, cp);
+ if (err < 0)
+ mgmt_pending_remove(cmd);
+
+done:
+ hci_dev_unlock_bh(hdev);
+ hci_dev_put(hdev);
+
+ return err;
+}
+
+static int user_passkey_neg_reply(struct sock *sk, u16 index,
+ unsigned char *data, u16 len)
+{
+ struct mgmt_cp_user_passkey_neg_reply *cp = (void *) data;
+ struct pending_cmd *cmd;
+ struct hci_dev *hdev;
+ struct hci_conn *conn;
+ int err = 0;
+
+ BT_DBG("");
+
+ if (len != sizeof(*cp))
+ return cmd_status(sk, index, MGMT_OP_USER_PASSKEY_NEG_REPLY,
+ EINVAL);
+
+ hdev = hci_dev_get(index);
+ if (!hdev)
+ return cmd_status(sk, index, MGMT_OP_USER_PASSKEY_NEG_REPLY,
+ ENODEV);
+
+ hci_dev_lock_bh(hdev);
+
+ if (!test_bit(HCI_UP, &hdev->flags)) {
+ err = cmd_status(sk, index, MGMT_OP_USER_PASSKEY_NEG_REPLY,
+ ENETDOWN);
+ goto done;
+ }
+
+ conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &cp->bdaddr);
+ if (!conn) {
+ conn = hci_conn_hash_lookup_ba(hdev, LE_LINK, &cp->bdaddr);
+ if (!conn) {
+ err = cmd_status(sk, index,
+ MGMT_OP_USER_PASSKEY_NEG_REPLY,
+ ENOTCONN);
+ goto done;
+ }
+
+ /* Forward Passkey response to SMP */
+
+ err = cmd_status(sk, index, MGMT_OP_USER_PASSKEY_NEG_REPLY, 0);
+ goto done;
+ }
+
+ cmd = mgmt_pending_add(sk, MGMT_OP_USER_PASSKEY_NEG_REPLY, hdev, data,
+ len);
+ if (!cmd) {
+ err = -ENOMEM;
+ goto done;
+ }
+
+ err = hci_send_cmd(hdev, HCI_OP_USER_PASSKEY_NEG_REPLY, len, cp);
+ if (err < 0)
+ mgmt_pending_remove(cmd);
+
+done:
+ hci_dev_unlock_bh(hdev);
+ hci_dev_put(hdev);
+
+ return err;
+}
static int set_local_name(struct sock *sk, u16 index, unsigned char *data,
u16 len)
{
@@ -1923,6 +2045,13 @@ int mgmt_control(struct sock *sk, struct msghdr *msg, size_t msglen)
case MGMT_OP_USER_CONFIRM_NEG_REPLY:
err = user_confirm_reply(sk, index, buf + sizeof(*hdr), len, 0);
break;
+ case MGMT_OP_USER_PASSKEY_REPLY:
+ err = user_passkey_reply(sk, index, buf + sizeof(*hdr), len);
+ break;
+ case MGMT_OP_USER_PASSKEY_NEG_REPLY:
+ err = user_passkey_neg_reply(sk, index, buf + sizeof(*hdr),
+ len);
+ break;
case MGMT_OP_SET_LOCAL_NAME:
err = set_local_name(sk, index, buf + sizeof(*hdr), len);
break;
@@ -2281,6 +2410,20 @@ int mgmt_user_confirm_neg_reply_complete(struct hci_dev *hdev,
MGMT_OP_USER_CONFIRM_NEG_REPLY);
}

+int mgmt_user_passkey_reply_complete(struct hci_dev *hdev, bdaddr_t *bdaddr,
+ u8 status)
+{
+ return confirm_reply_complete(hdev, bdaddr, status,
+ MGMT_OP_USER_PASSKEY_REPLY);
+}
+
+int mgmt_user_passkey_neg_reply_complete(struct hci_dev *hdev,
+ bdaddr_t *bdaddr, u8 status)
+{
+ return confirm_reply_complete(hdev, bdaddr, status,
+ MGMT_OP_USER_PASSKEY_NEG_REPLY);
+}
+
int mgmt_auth_failed(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 status)
{
struct mgmt_ev_auth_failed ev;
--
1.7.7.2

--
Brian Gix
[email protected]
Employee of Qualcomm Innovation Center, Inc.
Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum

2011-11-10 20:52:53

by Brian Gix

[permalink] [raw]
Subject: [PATCH 1/3] Bluetooth: Add SMP support to user_confirm_reply

to enable User Confirmation during LE-SMP pairing.

Signed-off-by: Brian Gix <[email protected]>
---
net/bluetooth/mgmt.c | 22 +++++++++++++++++++---
1 files changed, 19 insertions(+), 3 deletions(-)

diff --git a/net/bluetooth/mgmt.c b/net/bluetooth/mgmt.c
index a6720c6..761d607 100644
--- a/net/bluetooth/mgmt.c
+++ b/net/bluetooth/mgmt.c
@@ -1423,6 +1423,7 @@ static int user_confirm_reply(struct sock *sk, u16 index, unsigned char *data,
u16 mgmt_op, hci_op;
struct pending_cmd *cmd;
struct hci_dev *hdev;
+ struct hci_conn *conn;
int err;

BT_DBG("");
@@ -1446,20 +1447,35 @@ static int user_confirm_reply(struct sock *sk, u16 index, unsigned char *data,

if (!test_bit(HCI_UP, &hdev->flags)) {
err = cmd_status(sk, index, mgmt_op, ENETDOWN);
- goto failed;
+ goto done;
+ }
+
+ /* Route command to HCI (if ACL Link) or SMP (if LE Link) */
+ conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &cp->bdaddr);
+ if (!conn) {
+ conn = hci_conn_hash_lookup_ba(hdev, LE_LINK, &cp->bdaddr);
+ if (!conn) {
+ err = cmd_status(sk, index, mgmt_op, ENOTCONN);
+ goto done;
+ }
+
+ /* Forward Confirm response to SMP */
+
+ err = cmd_status(sk, index, mgmt_op, 0);
+ goto done;
}

cmd = mgmt_pending_add(sk, mgmt_op, hdev, data, len);
if (!cmd) {
err = -ENOMEM;
- goto failed;
+ goto done;
}

err = hci_send_cmd(hdev, hci_op, sizeof(cp->bdaddr), &cp->bdaddr);
if (err < 0)
mgmt_pending_remove(cmd);

-failed:
+done:
hci_dev_unlock_bh(hdev);
hci_dev_put(hdev);

--
1.7.7.2

--
Brian Gix
[email protected]
Employee of Qualcomm Innovation Center, Inc.
Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum