blob: 0ee2905a61792c5f725fc514a0ca390fef580262 [file] [log] [blame]
Anderson Brigliaeb492e02011-06-09 18:50:40 -03001/*
2 BlueZ - Bluetooth protocol stack for Linux
3 Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
4
5 This program is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License version 2 as
7 published by the Free Software Foundation;
8
9 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
10 OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
11 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF THIRD PARTY RIGHTS.
12 IN NO EVENT SHALL THE COPYRIGHT HOLDER(S) AND AUTHOR(S) BE LIABLE FOR ANY
13 CLAIM, OR ANY SPECIAL INDIRECT OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES
14 WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15 ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16 OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17
18 ALL LIABILITY, INCLUDING LIABILITY FOR INFRINGEMENT OF ANY PATENTS,
19 COPYRIGHTS, TRADEMARKS OR OTHER RIGHTS, RELATING TO USE OF THIS
20 SOFTWARE IS DISCLAIMED.
21*/
22
23#include <net/bluetooth/bluetooth.h>
24#include <net/bluetooth/hci_core.h>
25#include <net/bluetooth/l2cap.h>
26#include <net/bluetooth/smp.h>
Anderson Brigliad22ef0b2011-06-09 18:50:44 -030027#include <linux/crypto.h>
Stephen Rothwellf70490e2011-06-23 12:58:55 +100028#include <linux/scatterlist.h>
Anderson Brigliad22ef0b2011-06-09 18:50:44 -030029#include <crypto/b128ops.h>
30
Vinicius Costa Gomes5d3de7d2011-06-14 13:37:41 -030031#define SMP_TIMEOUT 30000 /* 30 seconds */
32
Anderson Brigliad22ef0b2011-06-09 18:50:44 -030033static inline void swap128(u8 src[16], u8 dst[16])
34{
35 int i;
36 for (i = 0; i < 16; i++)
37 dst[15 - i] = src[i];
38}
39
40static inline void swap56(u8 src[7], u8 dst[7])
41{
42 int i;
43 for (i = 0; i < 7; i++)
44 dst[6 - i] = src[i];
45}
46
47static int smp_e(struct crypto_blkcipher *tfm, const u8 *k, u8 *r)
48{
49 struct blkcipher_desc desc;
50 struct scatterlist sg;
51 int err, iv_len;
52 unsigned char iv[128];
53
54 if (tfm == NULL) {
55 BT_ERR("tfm %p", tfm);
56 return -EINVAL;
57 }
58
59 desc.tfm = tfm;
60 desc.flags = 0;
61
62 err = crypto_blkcipher_setkey(tfm, k, 16);
63 if (err) {
64 BT_ERR("cipher setkey failed: %d", err);
65 return err;
66 }
67
68 sg_init_one(&sg, r, 16);
69
70 iv_len = crypto_blkcipher_ivsize(tfm);
71 if (iv_len) {
72 memset(&iv, 0xff, iv_len);
73 crypto_blkcipher_set_iv(tfm, iv, iv_len);
74 }
75
76 err = crypto_blkcipher_encrypt(&desc, &sg, &sg, 16);
77 if (err)
78 BT_ERR("Encrypt data error %d", err);
79
80 return err;
81}
82
83static int smp_c1(struct crypto_blkcipher *tfm, u8 k[16], u8 r[16],
84 u8 preq[7], u8 pres[7], u8 _iat, bdaddr_t *ia,
85 u8 _rat, bdaddr_t *ra, u8 res[16])
86{
87 u8 p1[16], p2[16];
88 int err;
89
90 memset(p1, 0, 16);
91
92 /* p1 = pres || preq || _rat || _iat */
93 swap56(pres, p1);
94 swap56(preq, p1 + 7);
95 p1[14] = _rat;
96 p1[15] = _iat;
97
98 memset(p2, 0, 16);
99
100 /* p2 = padding || ia || ra */
101 baswap((bdaddr_t *) (p2 + 4), ia);
102 baswap((bdaddr_t *) (p2 + 10), ra);
103
104 /* res = r XOR p1 */
105 u128_xor((u128 *) res, (u128 *) r, (u128 *) p1);
106
107 /* res = e(k, res) */
108 err = smp_e(tfm, k, res);
109 if (err) {
110 BT_ERR("Encrypt data error");
111 return err;
112 }
113
114 /* res = res XOR p2 */
115 u128_xor((u128 *) res, (u128 *) res, (u128 *) p2);
116
117 /* res = e(k, res) */
118 err = smp_e(tfm, k, res);
119 if (err)
120 BT_ERR("Encrypt data error");
121
122 return err;
123}
124
125static int smp_s1(struct crypto_blkcipher *tfm, u8 k[16],
126 u8 r1[16], u8 r2[16], u8 _r[16])
127{
128 int err;
129
130 /* Just least significant octets from r1 and r2 are considered */
131 memcpy(_r, r1 + 8, 8);
132 memcpy(_r + 8, r2 + 8, 8);
133
134 err = smp_e(tfm, k, _r);
135 if (err)
136 BT_ERR("Encrypt data error");
137
138 return err;
139}
140
141static int smp_rand(u8 *buf)
142{
143 get_random_bytes(buf, 16);
144
145 return 0;
146}
Anderson Brigliaeb492e02011-06-09 18:50:40 -0300147
148static struct sk_buff *smp_build_cmd(struct l2cap_conn *conn, u8 code,
149 u16 dlen, void *data)
150{
151 struct sk_buff *skb;
152 struct l2cap_hdr *lh;
153 int len;
154
155 len = L2CAP_HDR_SIZE + sizeof(code) + dlen;
156
157 if (len > conn->mtu)
158 return NULL;
159
160 skb = bt_skb_alloc(len, GFP_ATOMIC);
161 if (!skb)
162 return NULL;
163
164 lh = (struct l2cap_hdr *) skb_put(skb, L2CAP_HDR_SIZE);
165 lh->len = cpu_to_le16(sizeof(code) + dlen);
166 lh->cid = cpu_to_le16(L2CAP_CID_SMP);
167
168 memcpy(skb_put(skb, sizeof(code)), &code, sizeof(code));
169
170 memcpy(skb_put(skb, dlen), data, dlen);
171
172 return skb;
173}
174
175static void smp_send_cmd(struct l2cap_conn *conn, u8 code, u16 len, void *data)
176{
177 struct sk_buff *skb = smp_build_cmd(conn, code, len, data);
178
179 BT_DBG("code 0x%2.2x", code);
180
181 if (!skb)
182 return;
183
Luiz Augusto von Dentz73d80de2011-11-02 15:52:01 +0200184 skb->priority = HCI_PRIO_MAX;
185 hci_send_acl(conn->hchan, skb, 0);
Vinicius Costa Gomese2dcd112011-08-19 21:06:50 -0300186
Gustavo F. Padovan6c9d42a2011-12-20 10:57:27 -0200187 cancel_delayed_work_sync(&conn->security_timer);
188 schedule_delayed_work(&conn->security_timer,
Vinicius Costa Gomese2dcd112011-08-19 21:06:50 -0300189 msecs_to_jiffies(SMP_TIMEOUT));
Anderson Brigliaeb492e02011-06-09 18:50:40 -0300190}
191
Vinicius Costa Gomesb8e66ea2011-06-09 18:50:52 -0300192static void build_pairing_cmd(struct l2cap_conn *conn,
Vinicius Costa Gomes54790f72011-07-07 18:59:38 -0300193 struct smp_cmd_pairing *req,
194 struct smp_cmd_pairing *rsp,
195 __u8 authreq)
Vinicius Costa Gomesb8e66ea2011-06-09 18:50:52 -0300196{
Vinicius Costa Gomes54790f72011-07-07 18:59:38 -0300197 u8 dist_keys;
198
199 dist_keys = 0;
200 if (test_bit(HCI_PAIRABLE, &conn->hcon->hdev->flags)) {
Vinicius Costa Gomesca10b5e2011-08-25 20:02:37 -0300201 dist_keys = SMP_DIST_ENC_KEY;
Vinicius Costa Gomes54790f72011-07-07 18:59:38 -0300202 authreq |= SMP_AUTH_BONDING;
203 }
204
205 if (rsp == NULL) {
206 req->io_capability = conn->hcon->io_capability;
207 req->oob_flag = SMP_OOB_NOT_PRESENT;
208 req->max_key_size = SMP_MAX_ENC_KEY_SIZE;
209 req->init_key_dist = dist_keys;
210 req->resp_key_dist = dist_keys;
211 req->auth_req = authreq;
212 return;
213 }
214
215 rsp->io_capability = conn->hcon->io_capability;
216 rsp->oob_flag = SMP_OOB_NOT_PRESENT;
217 rsp->max_key_size = SMP_MAX_ENC_KEY_SIZE;
218 rsp->init_key_dist = req->init_key_dist & dist_keys;
219 rsp->resp_key_dist = req->resp_key_dist & dist_keys;
220 rsp->auth_req = authreq;
Vinicius Costa Gomesb8e66ea2011-06-09 18:50:52 -0300221}
222
Vinicius Costa Gomes3158c502011-06-14 13:37:42 -0300223static u8 check_enc_key_size(struct l2cap_conn *conn, __u8 max_key_size)
224{
Vinicius Costa Gomes1c1def02011-09-05 14:31:30 -0300225 struct smp_chan *smp = conn->smp_chan;
226
Vinicius Costa Gomes3158c502011-06-14 13:37:42 -0300227 if ((max_key_size > SMP_MAX_ENC_KEY_SIZE) ||
228 (max_key_size < SMP_MIN_ENC_KEY_SIZE))
229 return SMP_ENC_KEY_SIZE;
230
Vinicius Costa Gomes1c1def02011-09-05 14:31:30 -0300231 smp->smp_key_size = max_key_size;
Vinicius Costa Gomes3158c502011-06-14 13:37:42 -0300232
233 return 0;
234}
235
Brian Gix4f957a72011-11-23 08:28:36 -0800236static void smp_failure(struct l2cap_conn *conn, u8 reason, u8 send)
237{
238 if (send)
239 smp_send_cmd(conn, SMP_CMD_PAIRING_FAIL, sizeof(reason),
240 &reason);
241
242 clear_bit(HCI_CONN_ENCRYPT_PEND, &conn->hcon->pend);
243 mgmt_auth_failed(conn->hcon->hdev, conn->dst, reason);
Gustavo F. Padovan6c9d42a2011-12-20 10:57:27 -0200244 cancel_delayed_work_sync(&conn->security_timer);
Brian Gix4f957a72011-11-23 08:28:36 -0800245 smp_chan_destroy(conn);
246}
247
Vinicius Costa Gomes8aab4752011-09-05 14:31:31 -0300248static void confirm_work(struct work_struct *work)
249{
250 struct smp_chan *smp = container_of(work, struct smp_chan, confirm);
251 struct l2cap_conn *conn = smp->conn;
252 struct crypto_blkcipher *tfm;
253 struct smp_cmd_pairing_confirm cp;
254 int ret;
255 u8 res[16], reason;
256
257 BT_DBG("conn %p", conn);
258
259 tfm = crypto_alloc_blkcipher("ecb(aes)", 0, CRYPTO_ALG_ASYNC);
260 if (IS_ERR(tfm)) {
261 reason = SMP_UNSPECIFIED;
262 goto error;
263 }
264
265 smp->tfm = tfm;
266
267 if (conn->hcon->out)
268 ret = smp_c1(tfm, smp->tk, smp->prnd, smp->preq, smp->prsp, 0,
269 conn->src, conn->hcon->dst_type, conn->dst,
270 res);
271 else
272 ret = smp_c1(tfm, smp->tk, smp->prnd, smp->preq, smp->prsp,
273 conn->hcon->dst_type, conn->dst, 0, conn->src,
274 res);
275 if (ret) {
276 reason = SMP_UNSPECIFIED;
277 goto error;
278 }
279
280 swap128(res, cp.confirm_val);
281 smp_send_cmd(smp->conn, SMP_CMD_PAIRING_CONFIRM, sizeof(cp), &cp);
282
283 return;
284
285error:
Brian Gix4f957a72011-11-23 08:28:36 -0800286 smp_failure(conn, reason, 1);
Vinicius Costa Gomes8aab4752011-09-05 14:31:31 -0300287}
288
289static void random_work(struct work_struct *work)
290{
291 struct smp_chan *smp = container_of(work, struct smp_chan, random);
292 struct l2cap_conn *conn = smp->conn;
293 struct hci_conn *hcon = conn->hcon;
294 struct crypto_blkcipher *tfm = smp->tfm;
295 u8 reason, confirm[16], res[16], key[16];
296 int ret;
297
298 if (IS_ERR_OR_NULL(tfm)) {
299 reason = SMP_UNSPECIFIED;
300 goto error;
301 }
302
303 BT_DBG("conn %p %s", conn, conn->hcon->out ? "master" : "slave");
304
305 if (hcon->out)
306 ret = smp_c1(tfm, smp->tk, smp->rrnd, smp->preq, smp->prsp, 0,
307 conn->src, hcon->dst_type, conn->dst,
308 res);
309 else
310 ret = smp_c1(tfm, smp->tk, smp->rrnd, smp->preq, smp->prsp,
311 hcon->dst_type, conn->dst, 0, conn->src,
312 res);
313 if (ret) {
314 reason = SMP_UNSPECIFIED;
315 goto error;
316 }
317
318 swap128(res, confirm);
319
320 if (memcmp(smp->pcnf, confirm, sizeof(smp->pcnf)) != 0) {
321 BT_ERR("Pairing failed (confirmation values mismatch)");
322 reason = SMP_CONFIRM_FAILED;
323 goto error;
324 }
325
326 if (hcon->out) {
327 u8 stk[16], rand[8];
328 __le16 ediv;
329
330 memset(rand, 0, sizeof(rand));
331 ediv = 0;
332
333 smp_s1(tfm, smp->tk, smp->rrnd, smp->prnd, key);
334 swap128(key, stk);
335
336 memset(stk + smp->smp_key_size, 0,
337 SMP_MAX_ENC_KEY_SIZE - smp->smp_key_size);
338
339 if (test_and_set_bit(HCI_CONN_ENCRYPT_PEND, &hcon->pend)) {
340 reason = SMP_UNSPECIFIED;
341 goto error;
342 }
343
344 hci_le_start_enc(hcon, ediv, rand, stk);
345 hcon->enc_key_size = smp->smp_key_size;
346 } else {
347 u8 stk[16], r[16], rand[8];
348 __le16 ediv;
349
350 memset(rand, 0, sizeof(rand));
351 ediv = 0;
352
353 swap128(smp->prnd, r);
354 smp_send_cmd(conn, SMP_CMD_PAIRING_RANDOM, sizeof(r), r);
355
356 smp_s1(tfm, smp->tk, smp->prnd, smp->rrnd, key);
357 swap128(key, stk);
358
359 memset(stk + smp->smp_key_size, 0,
360 SMP_MAX_ENC_KEY_SIZE - smp->smp_key_size);
361
362 hci_add_ltk(hcon->hdev, 0, conn->dst, smp->smp_key_size,
363 ediv, rand, stk);
364 }
365
366 return;
367
368error:
Brian Gix4f957a72011-11-23 08:28:36 -0800369 smp_failure(conn, reason, 1);
Vinicius Costa Gomes8aab4752011-09-05 14:31:31 -0300370}
371
372static struct smp_chan *smp_chan_create(struct l2cap_conn *conn)
373{
374 struct smp_chan *smp;
375
376 smp = kzalloc(sizeof(struct smp_chan), GFP_ATOMIC);
377 if (!smp)
378 return NULL;
379
380 INIT_WORK(&smp->confirm, confirm_work);
381 INIT_WORK(&smp->random, random_work);
382
383 smp->conn = conn;
384 conn->smp_chan = smp;
385
386 hci_conn_hold(conn->hcon);
387
388 return smp;
389}
390
391void smp_chan_destroy(struct l2cap_conn *conn)
392{
Brian Gixc8eb9692011-11-23 08:28:35 -0800393 struct smp_chan *smp = conn->smp_chan;
394
395 clear_bit(HCI_CONN_LE_SMP_PEND, &conn->hcon->pend);
396
397 if (smp->tfm)
398 crypto_free_blkcipher(smp->tfm);
399
400 kfree(smp);
401 conn->smp_chan = NULL;
Vinicius Costa Gomes8aab4752011-09-05 14:31:31 -0300402 hci_conn_put(conn->hcon);
403}
404
Vinicius Costa Gomesda85e5e2011-06-09 18:50:53 -0300405static u8 smp_cmd_pairing_req(struct l2cap_conn *conn, struct sk_buff *skb)
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300406{
Vinicius Costa Gomes3158c502011-06-14 13:37:42 -0300407 struct smp_cmd_pairing rsp, *req = (void *) skb->data;
Vinicius Costa Gomes8aab4752011-09-05 14:31:31 -0300408 struct smp_chan *smp;
Vinicius Costa Gomes3158c502011-06-14 13:37:42 -0300409 u8 key_size;
Vinicius Costa Gomes8aab4752011-09-05 14:31:31 -0300410 int ret;
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300411
412 BT_DBG("conn %p", conn);
413
Vinicius Costa Gomesd26a2342011-08-19 21:06:51 -0300414 if (!test_and_set_bit(HCI_CONN_LE_SMP_PEND, &conn->hcon->pend))
Vinicius Costa Gomes8aab4752011-09-05 14:31:31 -0300415 smp = smp_chan_create(conn);
416
417 smp = conn->smp_chan;
Vinicius Costa Gomesd26a2342011-08-19 21:06:51 -0300418
Vinicius Costa Gomes1c1def02011-09-05 14:31:30 -0300419 smp->preq[0] = SMP_CMD_PAIRING_REQ;
420 memcpy(&smp->preq[1], req, sizeof(*req));
Vinicius Costa Gomes3158c502011-06-14 13:37:42 -0300421 skb_pull(skb, sizeof(*req));
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300422
Vinicius Costa Gomes3158c502011-06-14 13:37:42 -0300423 if (req->oob_flag)
Vinicius Costa Gomesda85e5e2011-06-09 18:50:53 -0300424 return SMP_OOB_NOT_AVAIL;
425
426 /* We didn't start the pairing, so no requirements */
Vinicius Costa Gomes54790f72011-07-07 18:59:38 -0300427 build_pairing_cmd(conn, req, &rsp, SMP_AUTH_NONE);
Vinicius Costa Gomes3158c502011-06-14 13:37:42 -0300428
429 key_size = min(req->max_key_size, rsp.max_key_size);
430 if (check_enc_key_size(conn, key_size))
431 return SMP_ENC_KEY_SIZE;
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300432
Anderson Briglia7d24ddc2011-06-09 18:50:46 -0300433 /* Just works */
Vinicius Costa Gomes1c1def02011-09-05 14:31:30 -0300434 memset(smp->tk, 0, sizeof(smp->tk));
Anderson Briglia7d24ddc2011-06-09 18:50:46 -0300435
Vinicius Costa Gomes8aab4752011-09-05 14:31:31 -0300436 ret = smp_rand(smp->prnd);
437 if (ret)
438 return SMP_UNSPECIFIED;
439
Vinicius Costa Gomes1c1def02011-09-05 14:31:30 -0300440 smp->prsp[0] = SMP_CMD_PAIRING_RSP;
441 memcpy(&smp->prsp[1], &rsp, sizeof(rsp));
Anderson Brigliaf01ead32011-06-09 18:50:45 -0300442
Vinicius Costa Gomes3158c502011-06-14 13:37:42 -0300443 smp_send_cmd(conn, SMP_CMD_PAIRING_RSP, sizeof(rsp), &rsp);
Vinicius Costa Gomesda85e5e2011-06-09 18:50:53 -0300444
445 return 0;
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300446}
447
Vinicius Costa Gomesda85e5e2011-06-09 18:50:53 -0300448static u8 smp_cmd_pairing_rsp(struct l2cap_conn *conn, struct sk_buff *skb)
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300449{
Vinicius Costa Gomes3158c502011-06-14 13:37:42 -0300450 struct smp_cmd_pairing *req, *rsp = (void *) skb->data;
Vinicius Costa Gomes1c1def02011-09-05 14:31:30 -0300451 struct smp_chan *smp = conn->smp_chan;
Vinicius Costa Gomes8aab4752011-09-05 14:31:31 -0300452 struct hci_dev *hdev = conn->hcon->hdev;
453 u8 key_size;
Anderson Briglia7d24ddc2011-06-09 18:50:46 -0300454 int ret;
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300455
456 BT_DBG("conn %p", conn);
457
Vinicius Costa Gomes3158c502011-06-14 13:37:42 -0300458 skb_pull(skb, sizeof(*rsp));
Vinicius Costa Gomesda85e5e2011-06-09 18:50:53 -0300459
Vinicius Costa Gomes1c1def02011-09-05 14:31:30 -0300460 req = (void *) &smp->preq[1];
Vinicius Costa Gomes3158c502011-06-14 13:37:42 -0300461
462 key_size = min(req->max_key_size, rsp->max_key_size);
463 if (check_enc_key_size(conn, key_size))
464 return SMP_ENC_KEY_SIZE;
465
466 if (rsp->oob_flag)
Vinicius Costa Gomesda85e5e2011-06-09 18:50:53 -0300467 return SMP_OOB_NOT_AVAIL;
468
Anderson Briglia7d24ddc2011-06-09 18:50:46 -0300469 /* Just works */
Vinicius Costa Gomes1c1def02011-09-05 14:31:30 -0300470 memset(smp->tk, 0, sizeof(smp->tk));
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300471
Vinicius Costa Gomes1c1def02011-09-05 14:31:30 -0300472 ret = smp_rand(smp->prnd);
Anderson Briglia7d24ddc2011-06-09 18:50:46 -0300473 if (ret)
Vinicius Costa Gomesda85e5e2011-06-09 18:50:53 -0300474 return SMP_UNSPECIFIED;
Anderson Briglia7d24ddc2011-06-09 18:50:46 -0300475
Vinicius Costa Gomes8aab4752011-09-05 14:31:31 -0300476 smp->prsp[0] = SMP_CMD_PAIRING_RSP;
477 memcpy(&smp->prsp[1], rsp, sizeof(*rsp));
Anderson Briglia7d24ddc2011-06-09 18:50:46 -0300478
Vinicius Costa Gomes8aab4752011-09-05 14:31:31 -0300479 queue_work(hdev->workqueue, &smp->confirm);
Vinicius Costa Gomesda85e5e2011-06-09 18:50:53 -0300480
481 return 0;
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300482}
483
Vinicius Costa Gomesda85e5e2011-06-09 18:50:53 -0300484static u8 smp_cmd_pairing_confirm(struct l2cap_conn *conn, struct sk_buff *skb)
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300485{
Vinicius Costa Gomes1c1def02011-09-05 14:31:30 -0300486 struct smp_chan *smp = conn->smp_chan;
Vinicius Costa Gomes8aab4752011-09-05 14:31:31 -0300487 struct hci_dev *hdev = conn->hcon->hdev;
Anderson Briglia7d24ddc2011-06-09 18:50:46 -0300488
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300489 BT_DBG("conn %p %s", conn, conn->hcon->out ? "master" : "slave");
490
Vinicius Costa Gomes1c1def02011-09-05 14:31:30 -0300491 memcpy(smp->pcnf, skb->data, sizeof(smp->pcnf));
492 skb_pull(skb, sizeof(smp->pcnf));
Anderson Briglia7d24ddc2011-06-09 18:50:46 -0300493
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300494 if (conn->hcon->out) {
Anderson Briglia7d24ddc2011-06-09 18:50:46 -0300495 u8 random[16];
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300496
Vinicius Costa Gomes1c1def02011-09-05 14:31:30 -0300497 swap128(smp->prnd, random);
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300498 smp_send_cmd(conn, SMP_CMD_PAIRING_RANDOM, sizeof(random),
Anderson Briglia7d24ddc2011-06-09 18:50:46 -0300499 random);
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300500 } else {
Vinicius Costa Gomes8aab4752011-09-05 14:31:31 -0300501 queue_work(hdev->workqueue, &smp->confirm);
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300502 }
Vinicius Costa Gomesda85e5e2011-06-09 18:50:53 -0300503
504 return 0;
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300505}
506
Vinicius Costa Gomesda85e5e2011-06-09 18:50:53 -0300507static u8 smp_cmd_pairing_random(struct l2cap_conn *conn, struct sk_buff *skb)
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300508{
Vinicius Costa Gomes1c1def02011-09-05 14:31:30 -0300509 struct smp_chan *smp = conn->smp_chan;
Vinicius Costa Gomes8aab4752011-09-05 14:31:31 -0300510 struct hci_dev *hdev = conn->hcon->hdev;
Anderson Briglia7d24ddc2011-06-09 18:50:46 -0300511
Vinicius Costa Gomes8aab4752011-09-05 14:31:31 -0300512 BT_DBG("conn %p", conn);
Anderson Briglia7d24ddc2011-06-09 18:50:46 -0300513
Vinicius Costa Gomes8aab4752011-09-05 14:31:31 -0300514 swap128(skb->data, smp->rrnd);
515 skb_pull(skb, sizeof(smp->rrnd));
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300516
Vinicius Costa Gomes8aab4752011-09-05 14:31:31 -0300517 queue_work(hdev->workqueue, &smp->random);
Vinicius Costa Gomesda85e5e2011-06-09 18:50:53 -0300518
519 return 0;
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300520}
521
Vinicius Costa Gomes988c5992011-08-25 20:02:28 -0300522static u8 smp_ltk_encrypt(struct l2cap_conn *conn)
523{
524 struct link_key *key;
525 struct key_master_id *master;
526 struct hci_conn *hcon = conn->hcon;
527
528 key = hci_find_link_key_type(hcon->hdev, conn->dst,
529 HCI_LK_SMP_LTK);
530 if (!key)
531 return 0;
532
533 if (test_and_set_bit(HCI_CONN_ENCRYPT_PEND,
534 &hcon->pend))
535 return 1;
536
537 master = (void *) key->data;
538 hci_le_start_enc(hcon, master->ediv, master->rand,
539 key->val);
540 hcon->enc_key_size = key->pin_len;
541
542 return 1;
543
544}
Vinicius Costa Gomesda85e5e2011-06-09 18:50:53 -0300545static u8 smp_cmd_security_req(struct l2cap_conn *conn, struct sk_buff *skb)
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300546{
547 struct smp_cmd_security_req *rp = (void *) skb->data;
548 struct smp_cmd_pairing cp;
Vinicius Costa Gomesf1cb9af2011-01-26 21:42:57 -0300549 struct hci_conn *hcon = conn->hcon;
Vinicius Costa Gomes8aab4752011-09-05 14:31:31 -0300550 struct smp_chan *smp;
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300551
552 BT_DBG("conn %p", conn);
553
Vinicius Costa Gomesfeb45eb2011-08-25 20:02:35 -0300554 hcon->pending_sec_level = BT_SECURITY_MEDIUM;
555
Vinicius Costa Gomes988c5992011-08-25 20:02:28 -0300556 if (smp_ltk_encrypt(conn))
557 return 0;
558
Vinicius Costa Gomesd26a2342011-08-19 21:06:51 -0300559 if (test_and_set_bit(HCI_CONN_LE_SMP_PEND, &hcon->pend))
Vinicius Costa Gomesda85e5e2011-06-09 18:50:53 -0300560 return 0;
Vinicius Costa Gomesf1cb9af2011-01-26 21:42:57 -0300561
Vinicius Costa Gomes8aab4752011-09-05 14:31:31 -0300562 smp = smp_chan_create(conn);
Vinicius Costa Gomesd26a2342011-08-19 21:06:51 -0300563
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300564 skb_pull(skb, sizeof(*rp));
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300565
Vinicius Costa Gomesda85e5e2011-06-09 18:50:53 -0300566 memset(&cp, 0, sizeof(cp));
Vinicius Costa Gomes54790f72011-07-07 18:59:38 -0300567 build_pairing_cmd(conn, &cp, NULL, rp->auth_req);
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300568
Vinicius Costa Gomes1c1def02011-09-05 14:31:30 -0300569 smp->preq[0] = SMP_CMD_PAIRING_REQ;
570 memcpy(&smp->preq[1], &cp, sizeof(cp));
Anderson Brigliaf01ead32011-06-09 18:50:45 -0300571
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300572 smp_send_cmd(conn, SMP_CMD_PAIRING_REQ, sizeof(cp), &cp);
Vinicius Costa Gomesf1cb9af2011-01-26 21:42:57 -0300573
Vinicius Costa Gomesda85e5e2011-06-09 18:50:53 -0300574 return 0;
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300575}
576
Anderson Brigliaeb492e02011-06-09 18:50:40 -0300577int smp_conn_security(struct l2cap_conn *conn, __u8 sec_level)
578{
Vinicius Costa Gomes3a0259b2011-06-09 18:50:43 -0300579 struct hci_conn *hcon = conn->hcon;
Vinicius Costa Gomes1c1def02011-09-05 14:31:30 -0300580 struct smp_chan *smp = conn->smp_chan;
Anderson Brigliaeb492e02011-06-09 18:50:40 -0300581
Vinicius Costa Gomes3a0259b2011-06-09 18:50:43 -0300582 BT_DBG("conn %p hcon %p level 0x%2.2x", conn, hcon, sec_level);
583
Andre Guedes2e65c9d2011-06-30 19:20:56 -0300584 if (!lmp_host_le_capable(hcon->hdev))
585 return 1;
586
Vinicius Costa Gomesf1cb9af2011-01-26 21:42:57 -0300587 if (sec_level == BT_SECURITY_LOW)
Anderson Brigliaeb492e02011-06-09 18:50:40 -0300588 return 1;
Vinicius Costa Gomesf1cb9af2011-01-26 21:42:57 -0300589
590 if (hcon->sec_level >= sec_level)
591 return 1;
592
Vinicius Costa Gomes988c5992011-08-25 20:02:28 -0300593 if (hcon->link_mode & HCI_LM_MASTER)
594 if (smp_ltk_encrypt(conn))
Vinicius Costa Gomes02bc7452011-07-07 18:59:41 -0300595 goto done;
Vinicius Costa Gomesd26a2342011-08-19 21:06:51 -0300596
597 if (test_and_set_bit(HCI_CONN_LE_SMP_PEND, &hcon->pend))
598 return 0;
599
Vinicius Costa Gomes8aab4752011-09-05 14:31:31 -0300600 smp = smp_chan_create(conn);
Vinicius Costa Gomesd26a2342011-08-19 21:06:51 -0300601
Vinicius Costa Gomesd26a2342011-08-19 21:06:51 -0300602 if (hcon->link_mode & HCI_LM_MASTER) {
603 struct smp_cmd_pairing cp;
Anderson Brigliaf01ead32011-06-09 18:50:45 -0300604
Vinicius Costa Gomes0fb4eb62011-08-25 20:02:27 -0300605 build_pairing_cmd(conn, &cp, NULL, SMP_AUTH_NONE);
Vinicius Costa Gomes1c1def02011-09-05 14:31:30 -0300606 smp->preq[0] = SMP_CMD_PAIRING_REQ;
607 memcpy(&smp->preq[1], &cp, sizeof(cp));
Anderson Brigliaf01ead32011-06-09 18:50:45 -0300608
Anderson Brigliaeb492e02011-06-09 18:50:40 -0300609 smp_send_cmd(conn, SMP_CMD_PAIRING_REQ, sizeof(cp), &cp);
610 } else {
611 struct smp_cmd_security_req cp;
Vinicius Costa Gomes0fb4eb62011-08-25 20:02:27 -0300612 cp.auth_req = SMP_AUTH_NONE;
Anderson Brigliaeb492e02011-06-09 18:50:40 -0300613 smp_send_cmd(conn, SMP_CMD_SECURITY_REQ, sizeof(cp), &cp);
614 }
615
Vinicius Costa Gomes02bc7452011-07-07 18:59:41 -0300616done:
Vinicius Costa Gomesf1cb9af2011-01-26 21:42:57 -0300617 hcon->pending_sec_level = sec_level;
Vinicius Costa Gomesf1cb9af2011-01-26 21:42:57 -0300618
Anderson Brigliaeb492e02011-06-09 18:50:40 -0300619 return 0;
620}
621
Vinicius Costa Gomes7034b912011-07-07 18:59:34 -0300622static int smp_cmd_encrypt_info(struct l2cap_conn *conn, struct sk_buff *skb)
623{
Vinicius Costa Gomes16b90832011-07-07 18:59:39 -0300624 struct smp_cmd_encrypt_info *rp = (void *) skb->data;
Vinicius Costa Gomes1c1def02011-09-05 14:31:30 -0300625 struct smp_chan *smp = conn->smp_chan;
Vinicius Costa Gomes16b90832011-07-07 18:59:39 -0300626
627 skb_pull(skb, sizeof(*rp));
628
Vinicius Costa Gomes1c1def02011-09-05 14:31:30 -0300629 memcpy(smp->tk, rp->ltk, sizeof(smp->tk));
Vinicius Costa Gomes16b90832011-07-07 18:59:39 -0300630
Vinicius Costa Gomes7034b912011-07-07 18:59:34 -0300631 return 0;
632}
633
634static int smp_cmd_master_ident(struct l2cap_conn *conn, struct sk_buff *skb)
635{
Vinicius Costa Gomes16b90832011-07-07 18:59:39 -0300636 struct smp_cmd_master_ident *rp = (void *) skb->data;
Vinicius Costa Gomes1c1def02011-09-05 14:31:30 -0300637 struct smp_chan *smp = conn->smp_chan;
Vinicius Costa Gomes7034b912011-07-07 18:59:34 -0300638
Vinicius Costa Gomes16b90832011-07-07 18:59:39 -0300639 skb_pull(skb, sizeof(*rp));
640
Vinicius Costa Gomes1c1def02011-09-05 14:31:30 -0300641 hci_add_ltk(conn->hcon->hdev, 1, conn->src, smp->smp_key_size,
642 rp->ediv, rp->rand, smp->tk);
Vinicius Costa Gomes7034b912011-07-07 18:59:34 -0300643
644 smp_distribute_keys(conn, 1);
645
646 return 0;
647}
648
Anderson Brigliaeb492e02011-06-09 18:50:40 -0300649int smp_sig_channel(struct l2cap_conn *conn, struct sk_buff *skb)
650{
651 __u8 code = skb->data[0];
652 __u8 reason;
653 int err = 0;
654
Andre Guedes2e65c9d2011-06-30 19:20:56 -0300655 if (!lmp_host_le_capable(conn->hcon->hdev)) {
656 err = -ENOTSUPP;
657 reason = SMP_PAIRING_NOTSUPP;
658 goto done;
659 }
660
Anderson Brigliaeb492e02011-06-09 18:50:40 -0300661 skb_pull(skb, sizeof(code));
662
663 switch (code) {
664 case SMP_CMD_PAIRING_REQ:
Vinicius Costa Gomesda85e5e2011-06-09 18:50:53 -0300665 reason = smp_cmd_pairing_req(conn, skb);
Anderson Brigliaeb492e02011-06-09 18:50:40 -0300666 break;
667
668 case SMP_CMD_PAIRING_FAIL:
Brian Gix4f957a72011-11-23 08:28:36 -0800669 smp_failure(conn, skb->data[0], 0);
Vinicius Costa Gomesda85e5e2011-06-09 18:50:53 -0300670 reason = 0;
671 err = -EPERM;
Anderson Brigliaeb492e02011-06-09 18:50:40 -0300672 break;
673
674 case SMP_CMD_PAIRING_RSP:
Vinicius Costa Gomesda85e5e2011-06-09 18:50:53 -0300675 reason = smp_cmd_pairing_rsp(conn, skb);
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300676 break;
677
678 case SMP_CMD_SECURITY_REQ:
Vinicius Costa Gomesda85e5e2011-06-09 18:50:53 -0300679 reason = smp_cmd_security_req(conn, skb);
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300680 break;
681
Anderson Brigliaeb492e02011-06-09 18:50:40 -0300682 case SMP_CMD_PAIRING_CONFIRM:
Vinicius Costa Gomesda85e5e2011-06-09 18:50:53 -0300683 reason = smp_cmd_pairing_confirm(conn, skb);
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300684 break;
685
Anderson Brigliaeb492e02011-06-09 18:50:40 -0300686 case SMP_CMD_PAIRING_RANDOM:
Vinicius Costa Gomesda85e5e2011-06-09 18:50:53 -0300687 reason = smp_cmd_pairing_random(conn, skb);
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300688 break;
689
Anderson Brigliaeb492e02011-06-09 18:50:40 -0300690 case SMP_CMD_ENCRYPT_INFO:
Vinicius Costa Gomes7034b912011-07-07 18:59:34 -0300691 reason = smp_cmd_encrypt_info(conn, skb);
692 break;
693
Anderson Brigliaeb492e02011-06-09 18:50:40 -0300694 case SMP_CMD_MASTER_IDENT:
Vinicius Costa Gomes7034b912011-07-07 18:59:34 -0300695 reason = smp_cmd_master_ident(conn, skb);
696 break;
697
Anderson Brigliaeb492e02011-06-09 18:50:40 -0300698 case SMP_CMD_IDENT_INFO:
699 case SMP_CMD_IDENT_ADDR_INFO:
700 case SMP_CMD_SIGN_INFO:
Vinicius Costa Gomes7034b912011-07-07 18:59:34 -0300701 /* Just ignored */
702 reason = 0;
703 break;
704
Anderson Brigliaeb492e02011-06-09 18:50:40 -0300705 default:
706 BT_DBG("Unknown command code 0x%2.2x", code);
707
708 reason = SMP_CMD_NOTSUPP;
Vinicius Costa Gomes3a0259b2011-06-09 18:50:43 -0300709 err = -EOPNOTSUPP;
710 goto done;
711 }
712
713done:
714 if (reason)
Brian Gix4f957a72011-11-23 08:28:36 -0800715 smp_failure(conn, reason, 1);
Anderson Brigliaeb492e02011-06-09 18:50:40 -0300716
717 kfree_skb(skb);
718 return err;
719}
Vinicius Costa Gomes7034b912011-07-07 18:59:34 -0300720
721int smp_distribute_keys(struct l2cap_conn *conn, __u8 force)
722{
723 struct smp_cmd_pairing *req, *rsp;
Vinicius Costa Gomes1c1def02011-09-05 14:31:30 -0300724 struct smp_chan *smp = conn->smp_chan;
Vinicius Costa Gomes7034b912011-07-07 18:59:34 -0300725 __u8 *keydist;
726
727 BT_DBG("conn %p force %d", conn, force);
728
Vinicius Costa Gomesd26a2342011-08-19 21:06:51 -0300729 if (!test_bit(HCI_CONN_LE_SMP_PEND, &conn->hcon->pend))
730 return 0;
731
Vinicius Costa Gomes1c1def02011-09-05 14:31:30 -0300732 rsp = (void *) &smp->prsp[1];
Vinicius Costa Gomes7034b912011-07-07 18:59:34 -0300733
734 /* The responder sends its keys first */
735 if (!force && conn->hcon->out && (rsp->resp_key_dist & 0x07))
736 return 0;
737
Vinicius Costa Gomes1c1def02011-09-05 14:31:30 -0300738 req = (void *) &smp->preq[1];
Vinicius Costa Gomes7034b912011-07-07 18:59:34 -0300739
740 if (conn->hcon->out) {
741 keydist = &rsp->init_key_dist;
742 *keydist &= req->init_key_dist;
743 } else {
744 keydist = &rsp->resp_key_dist;
745 *keydist &= req->resp_key_dist;
746 }
747
748
749 BT_DBG("keydist 0x%x", *keydist);
750
751 if (*keydist & SMP_DIST_ENC_KEY) {
752 struct smp_cmd_encrypt_info enc;
753 struct smp_cmd_master_ident ident;
754 __le16 ediv;
755
756 get_random_bytes(enc.ltk, sizeof(enc.ltk));
757 get_random_bytes(&ediv, sizeof(ediv));
758 get_random_bytes(ident.rand, sizeof(ident.rand));
759
760 smp_send_cmd(conn, SMP_CMD_ENCRYPT_INFO, sizeof(enc), &enc);
761
Vinicius Costa Gomes1c1def02011-09-05 14:31:30 -0300762 hci_add_ltk(conn->hcon->hdev, 1, conn->dst, smp->smp_key_size,
Vinicius Costa Gomes726b4ff2011-07-08 18:31:45 -0300763 ediv, ident.rand, enc.ltk);
Vinicius Costa Gomes16b90832011-07-07 18:59:39 -0300764
Vinicius Costa Gomes7034b912011-07-07 18:59:34 -0300765 ident.ediv = cpu_to_le16(ediv);
766
767 smp_send_cmd(conn, SMP_CMD_MASTER_IDENT, sizeof(ident), &ident);
768
769 *keydist &= ~SMP_DIST_ENC_KEY;
770 }
771
772 if (*keydist & SMP_DIST_ID_KEY) {
773 struct smp_cmd_ident_addr_info addrinfo;
774 struct smp_cmd_ident_info idinfo;
775
776 /* Send a dummy key */
777 get_random_bytes(idinfo.irk, sizeof(idinfo.irk));
778
779 smp_send_cmd(conn, SMP_CMD_IDENT_INFO, sizeof(idinfo), &idinfo);
780
781 /* Just public address */
782 memset(&addrinfo, 0, sizeof(addrinfo));
783 bacpy(&addrinfo.bdaddr, conn->src);
784
785 smp_send_cmd(conn, SMP_CMD_IDENT_ADDR_INFO, sizeof(addrinfo),
786 &addrinfo);
787
788 *keydist &= ~SMP_DIST_ID_KEY;
789 }
790
791 if (*keydist & SMP_DIST_SIGN) {
792 struct smp_cmd_sign_info sign;
793
794 /* Send a dummy key */
795 get_random_bytes(sign.csrk, sizeof(sign.csrk));
796
797 smp_send_cmd(conn, SMP_CMD_SIGN_INFO, sizeof(sign), &sign);
798
799 *keydist &= ~SMP_DIST_SIGN;
800 }
801
Vinicius Costa Gomesd26a2342011-08-19 21:06:51 -0300802 if (conn->hcon->out || force) {
803 clear_bit(HCI_CONN_LE_SMP_PEND, &conn->hcon->pend);
Gustavo F. Padovan6c9d42a2011-12-20 10:57:27 -0200804 cancel_delayed_work_sync(&conn->security_timer);
Vinicius Costa Gomes8aab4752011-09-05 14:31:31 -0300805 smp_chan_destroy(conn);
Vinicius Costa Gomesd26a2342011-08-19 21:06:51 -0300806 }
807
Vinicius Costa Gomes7034b912011-07-07 18:59:34 -0300808 return 0;
809}