aboutsummaryrefslogtreecommitdiffstats
path: root/net/bluetooth
diff options
context:
space:
mode:
authorVinicius Costa Gomes <vinicius.gomes@openbossa.org>2011-06-09 17:50:47 -0400
committerGustavo F. Padovan <padovan@profusion.mobi>2011-06-13 14:48:25 -0400
commita7a595f675f1b33dc73167147321dba5c4395acc (patch)
treeee17d1ba777fd18ec7b666a356b00c131cb5f0f2 /net/bluetooth
parent7d24ddcc1140d2f796436e476c8d69469610588b (diff)
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 <vinicius.gomes@openbossa.org> Signed-off-by: Gustavo F. Padovan <padovan@profusion.mobi>
Diffstat (limited to 'net/bluetooth')
-rw-r--r--net/bluetooth/hci_conn.c49
-rw-r--r--net/bluetooth/hci_event.c67
-rw-r--r--net/bluetooth/smp.c16
3 files changed, 128 insertions, 4 deletions
diff --git a/net/bluetooth/hci_conn.c b/net/bluetooth/hci_conn.c
index 37f5a174f072..18193831bbf1 100644
--- a/net/bluetooth/hci_conn.c
+++ b/net/bluetooth/hci_conn.c
@@ -204,6 +204,55 @@ void hci_le_conn_update(struct hci_conn *conn, u16 min, u16 max,
204} 204}
205EXPORT_SYMBOL(hci_le_conn_update); 205EXPORT_SYMBOL(hci_le_conn_update);
206 206
207void hci_le_start_enc(struct hci_conn *conn, __le16 ediv, __u8 rand[8],
208 __u8 ltk[16])
209{
210 struct hci_dev *hdev = conn->hdev;
211 struct hci_cp_le_start_enc cp;
212
213 BT_DBG("%p", conn);
214
215 memset(&cp, 0, sizeof(cp));
216
217 cp.handle = cpu_to_le16(conn->handle);
218 memcpy(cp.ltk, ltk, sizeof(cp.ltk));
219 cp.ediv = ediv;
220 memcpy(cp.rand, rand, sizeof(rand));
221
222 hci_send_cmd(hdev, HCI_OP_LE_START_ENC, sizeof(cp), &cp);
223}
224EXPORT_SYMBOL(hci_le_start_enc);
225
226void hci_le_ltk_reply(struct hci_conn *conn, u8 ltk[16])
227{
228 struct hci_dev *hdev = conn->hdev;
229 struct hci_cp_le_ltk_reply cp;
230
231 BT_DBG("%p", conn);
232
233 memset(&cp, 0, sizeof(cp));
234
235 cp.handle = cpu_to_le16(conn->handle);
236 memcpy(cp.ltk, ltk, sizeof(ltk));
237
238 hci_send_cmd(hdev, HCI_OP_LE_LTK_REPLY, sizeof(cp), &cp);
239}
240EXPORT_SYMBOL(hci_le_ltk_reply);
241
242void hci_le_ltk_neg_reply(struct hci_conn *conn)
243{
244 struct hci_dev *hdev = conn->hdev;
245 struct hci_cp_le_ltk_neg_reply cp;
246
247 BT_DBG("%p", conn);
248
249 memset(&cp, 0, sizeof(cp));
250
251 cp.handle = cpu_to_le16(conn->handle);
252
253 hci_send_cmd(hdev, HCI_OP_LE_LTK_NEG_REPLY, sizeof(cp), &cp);
254}
255
207/* Device _must_ be locked */ 256/* Device _must_ be locked */
208void hci_sco_setup(struct hci_conn *conn, __u8 status) 257void hci_sco_setup(struct hci_conn *conn, __u8 status)
209{ 258{
diff --git a/net/bluetooth/hci_event.c b/net/bluetooth/hci_event.c
index 0f643f84131f..166fa113721c 100644
--- a/net/bluetooth/hci_event.c
+++ b/net/bluetooth/hci_event.c
@@ -868,6 +868,30 @@ static void hci_cc_le_set_scan_enable(struct hci_dev *hdev,
868 hci_dev_unlock(hdev); 868 hci_dev_unlock(hdev);
869} 869}
870 870
871static void hci_cc_le_ltk_reply(struct hci_dev *hdev, struct sk_buff *skb)
872{
873 struct hci_rp_le_ltk_reply *rp = (void *) skb->data;
874
875 BT_DBG("%s status 0x%x", hdev->name, rp->status);
876
877 if (rp->status)
878 return;
879
880 hci_req_complete(hdev, HCI_OP_LE_LTK_REPLY, rp->status);
881}
882
883static void hci_cc_le_ltk_neg_reply(struct hci_dev *hdev, struct sk_buff *skb)
884{
885 struct hci_rp_le_ltk_neg_reply *rp = (void *) skb->data;
886
887 BT_DBG("%s status 0x%x", hdev->name, rp->status);
888
889 if (rp->status)
890 return;
891
892 hci_req_complete(hdev, HCI_OP_LE_LTK_NEG_REPLY, rp->status);
893}
894
871static inline void hci_cs_inquiry(struct hci_dev *hdev, __u8 status) 895static inline void hci_cs_inquiry(struct hci_dev *hdev, __u8 status)
872{ 896{
873 BT_DBG("%s status 0x%x", hdev->name, status); 897 BT_DBG("%s status 0x%x", hdev->name, status);
@@ -1248,6 +1272,11 @@ static void hci_cs_le_create_conn(struct hci_dev *hdev, __u8 status)
1248 hci_dev_unlock(hdev); 1272 hci_dev_unlock(hdev);
1249} 1273}
1250 1274
1275static void hci_cs_le_start_enc(struct hci_dev *hdev, u8 status)
1276{
1277 BT_DBG("%s status 0x%x", hdev->name, status);
1278}
1279
1251static inline void hci_inquiry_complete_evt(struct hci_dev *hdev, struct sk_buff *skb) 1280static inline void hci_inquiry_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
1252{ 1281{
1253 __u8 status = *((__u8 *) skb->data); 1282 __u8 status = *((__u8 *) skb->data);
@@ -1856,6 +1885,14 @@ static inline void hci_cmd_complete_evt(struct hci_dev *hdev, struct sk_buff *sk
1856 hci_cc_le_set_scan_enable(hdev, skb); 1885 hci_cc_le_set_scan_enable(hdev, skb);
1857 break; 1886 break;
1858 1887
1888 case HCI_OP_LE_LTK_REPLY:
1889 hci_cc_le_ltk_reply(hdev, skb);
1890 break;
1891
1892 case HCI_OP_LE_LTK_NEG_REPLY:
1893 hci_cc_le_ltk_neg_reply(hdev, skb);
1894 break;
1895
1859 default: 1896 default:
1860 BT_DBG("%s opcode 0x%x", hdev->name, opcode); 1897 BT_DBG("%s opcode 0x%x", hdev->name, opcode);
1861 break; 1898 break;
@@ -1934,6 +1971,10 @@ static inline void hci_cmd_status_evt(struct hci_dev *hdev, struct sk_buff *skb)
1934 hci_cs_le_create_conn(hdev, ev->status); 1971 hci_cs_le_create_conn(hdev, ev->status);
1935 break; 1972 break;
1936 1973
1974 case HCI_OP_LE_START_ENC:
1975 hci_cs_le_start_enc(hdev, ev->status);
1976 break;
1977
1937 default: 1978 default:
1938 BT_DBG("%s opcode 0x%x", hdev->name, opcode); 1979 BT_DBG("%s opcode 0x%x", hdev->name, opcode);
1939 break; 1980 break;
@@ -2745,6 +2786,28 @@ static inline void hci_le_adv_report_evt(struct hci_dev *hdev,
2745 hci_dev_unlock(hdev); 2786 hci_dev_unlock(hdev);
2746} 2787}
2747 2788
2789static inline void hci_le_ltk_request_evt(struct hci_dev *hdev,
2790 struct sk_buff *skb)
2791{
2792 struct hci_ev_le_ltk_req *ev = (void *) skb->data;
2793 struct hci_cp_le_ltk_reply cp;
2794 struct hci_conn *conn;
2795
2796 BT_DBG("%s handle %d", hdev->name, cpu_to_le16(ev->handle));
2797
2798 hci_dev_lock(hdev);
2799
2800 conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
2801
2802 memset(&cp, 0, sizeof(cp));
2803 cp.handle = cpu_to_le16(conn->handle);
2804 memcpy(cp.ltk, conn->ltk, sizeof(conn->ltk));
2805
2806 hci_send_cmd(hdev, HCI_OP_LE_LTK_REPLY, sizeof(cp), &cp);
2807
2808 hci_dev_unlock(hdev);
2809}
2810
2748static inline void hci_le_meta_evt(struct hci_dev *hdev, struct sk_buff *skb) 2811static inline void hci_le_meta_evt(struct hci_dev *hdev, struct sk_buff *skb)
2749{ 2812{
2750 struct hci_ev_le_meta *le_ev = (void *) skb->data; 2813 struct hci_ev_le_meta *le_ev = (void *) skb->data;
@@ -2760,6 +2823,10 @@ static inline void hci_le_meta_evt(struct hci_dev *hdev, struct sk_buff *skb)
2760 hci_le_adv_report_evt(hdev, skb); 2823 hci_le_adv_report_evt(hdev, skb);
2761 break; 2824 break;
2762 2825
2826 case HCI_EV_LE_LTK_REQ:
2827 hci_le_ltk_request_evt(hdev, skb);
2828 break;
2829
2763 default: 2830 default:
2764 break; 2831 break;
2765 } 2832 }
diff --git a/net/bluetooth/smp.c b/net/bluetooth/smp.c
index 7a9a195c27d3..56828db68109 100644
--- a/net/bluetooth/smp.c
+++ b/net/bluetooth/smp.c
@@ -277,13 +277,16 @@ static void smp_cmd_pairing_confirm(struct l2cap_conn *conn,
277 277
278static void smp_cmd_pairing_random(struct l2cap_conn *conn, struct sk_buff *skb) 278static void smp_cmd_pairing_random(struct l2cap_conn *conn, struct sk_buff *skb)
279{ 279{
280 struct crypto_blkcipher *tfm = conn->hcon->hdev->tfm; 280 struct hci_conn *hcon = conn->hcon;
281 struct crypto_blkcipher *tfm = hcon->hdev->tfm;
281 int ret; 282 int ret;
282 u8 key[16], res[16], random[16], confirm[16], buf[128]; 283 u8 key[16], res[16], random[16], confirm[16], buf[128];
283 284
284 swap128(skb->data, random); 285 swap128(skb->data, random);
285 skb_pull(skb, sizeof(random)); 286 skb_pull(skb, sizeof(random));
286 287
288 memset(hcon->ltk, 0, sizeof(hcon->ltk));
289
287 if (conn->hcon->out) 290 if (conn->hcon->out)
288 ret = smp_c1(tfm, conn->tk, random, conn->preq, conn->prsp, 0, 291 ret = smp_c1(tfm, conn->tk, random, conn->preq, conn->prsp, 0,
289 conn->src, conn->hcon->dst_type, conn->dst, 292 conn->src, conn->hcon->dst_type, conn->dst,
@@ -309,11 +312,15 @@ static void smp_cmd_pairing_random(struct l2cap_conn *conn, struct sk_buff *skb)
309 } 312 }
310 313
311 if (conn->hcon->out) { 314 if (conn->hcon->out) {
315 __le16 ediv;
316 u8 rand[8];
317
312 smp_s1(tfm, conn->tk, random, conn->prnd, key); 318 smp_s1(tfm, conn->tk, random, conn->prnd, key);
319 swap128(key, hcon->ltk);
313 320
314 hex_dump_to_buffer(key, sizeof(key), 16, 1, buf, 321 memset(rand, 0, sizeof(rand));
315 sizeof(buf), 0); 322 ediv = 0;
316 BT_DBG("key %s", buf); 323 hci_le_start_enc(hcon, ediv, rand, hcon->ltk);
317 } else { 324 } else {
318 u8 r[16]; 325 u8 r[16];
319 326
@@ -321,6 +328,7 @@ static void smp_cmd_pairing_random(struct l2cap_conn *conn, struct sk_buff *skb)
321 smp_send_cmd(conn, SMP_CMD_PAIRING_RANDOM, sizeof(r), r); 328 smp_send_cmd(conn, SMP_CMD_PAIRING_RANDOM, sizeof(r), r);
322 329
323 smp_s1(tfm, conn->tk, conn->prnd, random, key); 330 smp_s1(tfm, conn->tk, conn->prnd, random, key);
331 swap128(key, hcon->ltk);
324 332
325 hex_dump_to_buffer(key, sizeof(key), 16, 1, buf, 333 hex_dump_to_buffer(key, sizeof(key), 16, 1, buf,
326 sizeof(buf), 0); 334 sizeof(buf), 0);