Return-Path: From: "Brian Gix" To: "'Vinicius Costa Gomes'" , References: <1291671832-13435-1-git-send-email-vinicius.gomes@openbossa.org> <1291671832-13435-9-git-send-email-vinicius.gomes@openbossa.org> In-Reply-To: <1291671832-13435-9-git-send-email-vinicius.gomes@openbossa.org> Subject: RE: [RFC v2 8/9] Bluetooth: Add support for LE Start Encryption Date: Tue, 7 Dec 2010 10:58:53 -0800 Message-ID: <003401cb9640$cb3b5e10$61b21a30$@org> MIME-Version: 1.0 Content-Type: text/plain; charset="us-ascii" Sender: linux-bluetooth-owner@vger.kernel.org List-ID: Hi Vinicius, > -----Original Message----- > From: linux-bluetooth-owner@vger.kernel.org [mailto:linux-bluetooth- > owner@vger.kernel.org] On Behalf Of Vinicius Costa Gomes > Sent: 06 December, 2010 1:44 PM > To: linux-bluetooth@vger.kernel.org > Cc: Vinicius Costa Gomes > Subject: [RFC v2 8/9] Bluetooth: Add support for LE Start Encryption > > This adds support for starting SMP Phase 2 Encryption, when the initial > SMP negotiation is successful. This adds the LE Start Encryption and LE > Long Term Key Request commands and related events. > > Signed-off-by: Vinicius Costa Gomes > --- > include/net/bluetooth/hci.h | 34 +++++++++++++++++++ > include/net/bluetooth/hci_core.h | 5 +++ > net/bluetooth/hci_conn.c | 47 ++++++++++++++++++++++++++ > net/bluetooth/hci_event.c | 67 > ++++++++++++++++++++++++++++++++++++++ > net/bluetooth/smp.c | 8 ++++- > 5 files changed, 160 insertions(+), 1 deletions(-) > > diff --git a/include/net/bluetooth/hci.h b/include/net/bluetooth/hci.h > index dff6ded..e6bed3f 100644 > --- a/include/net/bluetooth/hci.h > +++ b/include/net/bluetooth/hci.h > @@ -626,6 +626,33 @@ struct hci_cp_le_create_conn { > > #define HCI_OP_LE_CREATE_CONN_CANCEL 0x200e > > +#define HCI_OP_LE_START_ENC 0x2019 > +struct hci_cp_le_start_enc { > + __le16 handle; > + __u8 rand[8]; > + __le16 ediv; > + __u8 ltk[16]; > +} __packed; > + > +#define HCI_OP_LE_LTK_REPLY 0x201a > +struct hci_cp_le_ltk_reply { > + __le16 handle; > + __u8 ltk[16]; > +} __packed; > +struct hci_rp_le_ltk_reply { > + __u8 status; > + __le16 handle; > +} __packed; > + > +#define HCI_OP_LE_LTK_NEG_REPLY 0x201b > +struct hci_cp_le_ltk_neg_reply { > + __le16 handle; > +} __packed; > +struct hci_rp_le_ltk_neg_reply { > + __u8 status; > + __le16 handle; > +} __packed; > + > /* ---- HCI Events ---- */ > #define HCI_EV_INQUIRY_COMPLETE 0x01 > > @@ -897,6 +924,13 @@ struct hci_ev_le_conn_complete { > __u8 clk_accurancy; > } __packed; > > +#define HCI_EV_LE_LTK_REQ 0x05 > +struct hci_ev_le_ltk_req { > + __le16 handle; > + __u8 random[8]; > + __le16 ediv; > +} __packed; > + > /* Internal events generated by Bluetooth stack */ > #define HCI_EV_STACK_INTERNAL 0xfd > struct hci_ev_stack_internal { > diff --git a/include/net/bluetooth/hci_core.h > b/include/net/bluetooth/hci_core.h > index d0a9f5d..c6c44eb 100644 > --- a/include/net/bluetooth/hci_core.h > +++ b/include/net/bluetooth/hci_core.h > @@ -192,6 +192,7 @@ struct hci_conn { > __u8 sec_level; > __u8 power_save; > __u16 disc_timeout; > + __u8 ltk[16]; > unsigned long pend; > > unsigned int sent; > @@ -713,4 +714,8 @@ struct hci_sec_filter { > > void hci_req_complete(struct hci_dev *hdev, int result); > > +void hci_le_start_enc(struct hci_conn *conn, u8 ltk[16]); > +void hci_le_ltk_reply(struct hci_conn *conn, u8 ltk[16]); > +void hci_le_ltk_neg_reply(struct hci_conn *conn); > + > #endif /* __HCI_CORE_H */ > diff --git a/net/bluetooth/hci_conn.c b/net/bluetooth/hci_conn.c > index edfb48b..f919ddb 100644 > --- a/net/bluetooth/hci_conn.c > +++ b/net/bluetooth/hci_conn.c > @@ -183,6 +183,53 @@ void hci_setup_sync(struct hci_conn *conn, __u16 > handle) > hci_send_cmd(hdev, HCI_OP_SETUP_SYNC_CONN, sizeof(cp), &cp); > } > > +void hci_le_start_enc(struct hci_conn *conn, u8 ltk[16]) > +{ > + struct hci_dev *hdev = conn->hdev; > + struct hci_cp_le_start_enc cp; > + > + BT_DBG("%p", conn); > + > + memset(&cp, 0, sizeof(cp)); > + > + cp.handle = cpu_to_le16(conn->handle); > + memcpy(cp.ltk, ltk, 16); > + > + hci_send_cmd(hdev, HCI_OP_LE_START_ENC, sizeof(cp), &cp); > +} > +EXPORT_SYMBOL(hci_le_start_enc); This appears only useful for link encryption with the STK, as both the ediv random values are Zero. If this is how it was intended, the OK, however it may be more appropriate in smp.c > + > +void hci_le_ltk_reply(struct hci_conn *conn, u8 ltk[16]) > +{ > + struct hci_dev *hdev = conn->hdev; > + struct hci_cp_le_ltk_reply cp; > + > + BT_DBG("%p", conn); > + > + memset(&cp, 0, sizeof(cp)); > + > + cp.handle = cpu_to_le16(conn->handle); > + memcpy(&cp.ltk, ltk, sizeof(ltk)); > + > + hci_send_cmd(hdev, HCI_OP_LE_LTK_REPLY, sizeof(cp), &cp); > +} > +EXPORT_SYMBOL(hci_le_ltk_reply); > + > +void hci_le_ltk_neg_reply(struct hci_conn *conn) > +{ > + struct hci_dev *hdev = conn->hdev; > + struct hci_cp_le_ltk_neg_reply cp; > + > + BT_DBG("%p", conn); > + > + memset(&cp, 0, sizeof(cp)); > + > + cp.handle = cpu_to_le16(conn->handle); > + > + hci_send_cmd(hdev, HCI_OP_LE_LTK_NEG_REPLY, sizeof(cp), &cp); > +} > +EXPORT_SYMBOL(hci_le_ltk_neg_reply); > + > /* Device _must_ be locked */ > void hci_sco_setup(struct hci_conn *conn, __u8 status) > { > diff --git a/net/bluetooth/hci_event.c b/net/bluetooth/hci_event.c > index 55cdd6a..c90696f 100644 > --- a/net/bluetooth/hci_event.c > +++ b/net/bluetooth/hci_event.c > @@ -559,6 +559,30 @@ static void hci_cc_le_read_buffer_size(struct > hci_dev *hdev, > hci_req_complete(hdev, rp->status); > } > > +static void hci_cc_le_ltk_reply(struct hci_dev *hdev, struct sk_buff > *skb) > +{ > + struct hci_rp_le_ltk_reply *rp = (void *) skb->data; > + > + BT_DBG("%s status 0x%x", hdev->name, rp->status); > + > + if (rp->status) > + return; > + > + hci_req_complete(hdev, rp->status); > +} > + > +static void hci_cc_le_ltk_neg_reply(struct hci_dev *hdev, struct > sk_buff *skb) > +{ > + struct hci_rp_le_ltk_neg_reply *rp = (void *) skb->data; > + > + BT_DBG("%s status 0x%x", hdev->name, rp->status); > + > + if (rp->status) > + return; > + > + hci_req_complete(hdev, rp->status); > +} > + > static inline void hci_cs_inquiry(struct hci_dev *hdev, __u8 status) > { > BT_DBG("%s status 0x%x", hdev->name, status); > @@ -920,6 +944,11 @@ static void hci_cs_le_create_conn(struct hci_dev > *hdev, __u8 status) > hci_dev_unlock(hdev); > } > > +static void hci_cs_le_start_enc(struct hci_dev *hdev, u8 status) > +{ > + BT_DBG("%s status 0x%x", hdev->name, status); > +} > + > static inline void hci_inquiry_complete_evt(struct hci_dev *hdev, > struct sk_buff *skb) > { > __u8 status = *((__u8 *) skb->data); > @@ -1440,6 +1469,14 @@ static inline void hci_cmd_complete_evt(struct > hci_dev *hdev, struct sk_buff *sk > hci_cc_le_read_buffer_size(hdev, skb); > break; > > + case HCI_OP_LE_LTK_REPLY: > + hci_cc_le_ltk_reply(hdev, skb); > + break; > + > + case HCI_OP_LE_LTK_NEG_REPLY: > + hci_cc_le_ltk_neg_reply(hdev, skb); > + break; > + > default: > BT_DBG("%s opcode 0x%x", hdev->name, opcode); > break; > @@ -1510,6 +1547,10 @@ static inline void hci_cmd_status_evt(struct > hci_dev *hdev, struct sk_buff *skb) > hci_cs_le_create_conn(hdev, ev->status); > break; > > + case HCI_OP_LE_START_ENC: > + hci_cs_le_start_enc(hdev, ev->status); > + break; > + > default: > BT_DBG("%s opcode 0x%x", hdev->name, opcode); > break; > @@ -2013,6 +2054,28 @@ unlock: > hci_dev_unlock(hdev); > } > > +static inline void hci_le_ltk_request_evt(struct hci_dev *hdev, > + struct sk_buff *skb) > +{ > + struct hci_ev_le_ltk_req *ev = (void *) skb->data; > + struct hci_cp_le_ltk_reply cp; > + struct hci_conn *conn; > + > + BT_DBG("%s handle %d", hdev->name, cpu_to_le16(ev->handle)); > + > + hci_dev_lock(hdev); > + > + conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev- > >handle)); > + > + memset(&cp, 0, sizeof(cp)); > + cp.handle = cpu_to_le16(conn->handle); > + memcpy(cp.ltk, conn->ltk, sizeof(conn->ltk)); > + > + hci_send_cmd(hdev, HCI_OP_LE_LTK_REPLY, sizeof(cp), &cp); > + > + hci_dev_unlock(hdev); > +} Same basic problem here, except ediv and random should be checked for all Zeros, in which case it should be considered an STK request and rejected unless part of an intended SM Pairing procedure. If they are not zero, then they are the values that should be used to look up the LTK for the LTK_REPLY, because the BD ADDR of the remote device may have changed since the last time it was connected. > + > static inline void hci_le_meta_evt(struct hci_dev *hdev, struct > sk_buff *skb) > { > struct hci_ev_le_meta *le_ev = (void *) skb->data; > @@ -2024,6 +2087,10 @@ static inline void hci_le_meta_evt(struct > hci_dev *hdev, struct sk_buff *skb) > hci_le_conn_complete_evt(hdev, skb); > break; > > + case HCI_EV_LE_LTK_REQ: > + hci_le_ltk_request_evt(hdev, skb); > + break; > + > default: > break; > } > diff --git a/net/bluetooth/smp.c b/net/bluetooth/smp.c > index 7d7e8ad..d19b8a2 100644 > --- a/net/bluetooth/smp.c > +++ b/net/bluetooth/smp.c > @@ -289,7 +289,8 @@ static void smp_cmd_pairing_confirm(struct > l2cap_conn *conn, struct sk_buff *skb > > static void smp_cmd_pairing_random(struct l2cap_conn *conn, struct > sk_buff *skb) > { > - struct crypto_blkcipher *tfm = conn->hcon->hdev->tfm; > + struct hci_conn *hcon = conn->hcon; > + struct crypto_blkcipher *tfm = hcon->hdev->tfm; > int ret; > u8 k[16], key[16], res[16], random[16], confirm[16], buf[128]; > > @@ -297,6 +298,7 @@ static void smp_cmd_pairing_random(struct > l2cap_conn *conn, struct sk_buff *skb) > skb_pull(skb, 16); > > memset(k, 0, sizeof(k)); > + memset(hcon->ltk, 0, sizeof(hcon->ltk)); > > if (conn->hcon->out) > ret = smp_c1(tfm, k, random, conn->preq, conn->pres, 0, > @@ -320,6 +322,9 @@ static void smp_cmd_pairing_random(struct > l2cap_conn *conn, struct sk_buff *skb) > > if (conn->hcon->out) { > smp_s1(tfm, k, random, conn->prnd, key); > + swap128(key, hcon->ltk); > + > + hci_le_start_enc(conn->hcon, hcon->ltk); > > hex_dump_to_buffer(key, sizeof(key), 16, 1, buf, > sizeof(buf), 0); > BT_DBG("key %s", buf); > @@ -330,6 +335,7 @@ static void smp_cmd_pairing_random(struct > l2cap_conn *conn, struct sk_buff *skb) > smp_send_cmd(conn, SMP_CMD_PAIRING_RANDOM, 16, r); > > smp_s1(tfm, k, conn->prnd, random, key); > + swap128(key, hcon->ltk); > > hex_dump_to_buffer(key, sizeof(key), 16, 1, buf, > sizeof(buf), 0); > BT_DBG("key %s", buf); > -- > 1.7.3.2 > > -- > To unsubscribe from this list: send the line "unsubscribe linux- > bluetooth" in > the body of a message to majordomo@vger.kernel.org > More majordomo info at http://vger.kernel.org/majordomo-info.html