blob: 605156f13899d45d0000513c3253254ace189982 [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>
Brian Gix2b64d152011-12-21 16:12:12 -080026#include <net/bluetooth/mgmt.h>
Anderson Brigliaeb492e02011-06-09 18:50:40 -030027#include <net/bluetooth/smp.h>
Anderson Brigliad22ef0b2011-06-09 18:50:44 -030028#include <linux/crypto.h>
Stephen Rothwellf70490e2011-06-23 12:58:55 +100029#include <linux/scatterlist.h>
Anderson Brigliad22ef0b2011-06-09 18:50:44 -030030#include <crypto/b128ops.h>
31
Marcel Holtmann17b02e62012-03-01 14:32:37 -080032#define SMP_TIMEOUT msecs_to_jiffies(30000)
Vinicius Costa Gomes5d3de7d2011-06-14 13:37:41 -030033
Johan Hedberg0fb07732012-10-11 16:26:06 +020034#define AUTH_REQ_MASK 0x07
35
Anderson Brigliad22ef0b2011-06-09 18:50:44 -030036static inline void swap128(u8 src[16], u8 dst[16])
37{
38 int i;
39 for (i = 0; i < 16; i++)
40 dst[15 - i] = src[i];
41}
42
43static inline void swap56(u8 src[7], u8 dst[7])
44{
45 int i;
46 for (i = 0; i < 7; i++)
47 dst[6 - i] = src[i];
48}
49
50static int smp_e(struct crypto_blkcipher *tfm, const u8 *k, u8 *r)
51{
52 struct blkcipher_desc desc;
53 struct scatterlist sg;
54 int err, iv_len;
55 unsigned char iv[128];
56
57 if (tfm == NULL) {
58 BT_ERR("tfm %p", tfm);
59 return -EINVAL;
60 }
61
62 desc.tfm = tfm;
63 desc.flags = 0;
64
65 err = crypto_blkcipher_setkey(tfm, k, 16);
66 if (err) {
67 BT_ERR("cipher setkey failed: %d", err);
68 return err;
69 }
70
71 sg_init_one(&sg, r, 16);
72
73 iv_len = crypto_blkcipher_ivsize(tfm);
74 if (iv_len) {
75 memset(&iv, 0xff, iv_len);
76 crypto_blkcipher_set_iv(tfm, iv, iv_len);
77 }
78
79 err = crypto_blkcipher_encrypt(&desc, &sg, &sg, 16);
80 if (err)
81 BT_ERR("Encrypt data error %d", err);
82
83 return err;
84}
85
86static int smp_c1(struct crypto_blkcipher *tfm, u8 k[16], u8 r[16],
87 u8 preq[7], u8 pres[7], u8 _iat, bdaddr_t *ia,
88 u8 _rat, bdaddr_t *ra, u8 res[16])
89{
90 u8 p1[16], p2[16];
91 int err;
92
93 memset(p1, 0, 16);
94
95 /* p1 = pres || preq || _rat || _iat */
96 swap56(pres, p1);
97 swap56(preq, p1 + 7);
98 p1[14] = _rat;
99 p1[15] = _iat;
100
101 memset(p2, 0, 16);
102
103 /* p2 = padding || ia || ra */
104 baswap((bdaddr_t *) (p2 + 4), ia);
105 baswap((bdaddr_t *) (p2 + 10), ra);
106
107 /* res = r XOR p1 */
108 u128_xor((u128 *) res, (u128 *) r, (u128 *) p1);
109
110 /* res = e(k, res) */
111 err = smp_e(tfm, k, res);
112 if (err) {
113 BT_ERR("Encrypt data error");
114 return err;
115 }
116
117 /* res = res XOR p2 */
118 u128_xor((u128 *) res, (u128 *) res, (u128 *) p2);
119
120 /* res = e(k, res) */
121 err = smp_e(tfm, k, res);
122 if (err)
123 BT_ERR("Encrypt data error");
124
125 return err;
126}
127
128static int smp_s1(struct crypto_blkcipher *tfm, u8 k[16],
129 u8 r1[16], u8 r2[16], u8 _r[16])
130{
131 int err;
132
133 /* Just least significant octets from r1 and r2 are considered */
134 memcpy(_r, r1 + 8, 8);
135 memcpy(_r + 8, r2 + 8, 8);
136
137 err = smp_e(tfm, k, _r);
138 if (err)
139 BT_ERR("Encrypt data error");
140
141 return err;
142}
143
144static int smp_rand(u8 *buf)
145{
146 get_random_bytes(buf, 16);
147
148 return 0;
149}
Anderson Brigliaeb492e02011-06-09 18:50:40 -0300150
151static struct sk_buff *smp_build_cmd(struct l2cap_conn *conn, u8 code,
152 u16 dlen, void *data)
153{
154 struct sk_buff *skb;
155 struct l2cap_hdr *lh;
156 int len;
157
158 len = L2CAP_HDR_SIZE + sizeof(code) + dlen;
159
160 if (len > conn->mtu)
161 return NULL;
162
163 skb = bt_skb_alloc(len, GFP_ATOMIC);
164 if (!skb)
165 return NULL;
166
167 lh = (struct l2cap_hdr *) skb_put(skb, L2CAP_HDR_SIZE);
168 lh->len = cpu_to_le16(sizeof(code) + dlen);
169 lh->cid = cpu_to_le16(L2CAP_CID_SMP);
170
171 memcpy(skb_put(skb, sizeof(code)), &code, sizeof(code));
172
173 memcpy(skb_put(skb, dlen), data, dlen);
174
175 return skb;
176}
177
178static void smp_send_cmd(struct l2cap_conn *conn, u8 code, u16 len, void *data)
179{
180 struct sk_buff *skb = smp_build_cmd(conn, code, len, data);
181
182 BT_DBG("code 0x%2.2x", code);
183
184 if (!skb)
185 return;
186
Luiz Augusto von Dentz73d80de2011-11-02 15:52:01 +0200187 skb->priority = HCI_PRIO_MAX;
188 hci_send_acl(conn->hchan, skb, 0);
Vinicius Costa Gomese2dcd112011-08-19 21:06:50 -0300189
Gustavo F. Padovan6c9d42a2011-12-20 10:57:27 -0200190 cancel_delayed_work_sync(&conn->security_timer);
Marcel Holtmann17b02e62012-03-01 14:32:37 -0800191 schedule_delayed_work(&conn->security_timer, SMP_TIMEOUT);
Anderson Brigliaeb492e02011-06-09 18:50:40 -0300192}
193
Brian Gix2b64d152011-12-21 16:12:12 -0800194static __u8 authreq_to_seclevel(__u8 authreq)
195{
196 if (authreq & SMP_AUTH_MITM)
197 return BT_SECURITY_HIGH;
198 else
199 return BT_SECURITY_MEDIUM;
200}
201
202static __u8 seclevel_to_authreq(__u8 sec_level)
203{
204 switch (sec_level) {
205 case BT_SECURITY_HIGH:
206 return SMP_AUTH_MITM | SMP_AUTH_BONDING;
207 case BT_SECURITY_MEDIUM:
208 return SMP_AUTH_BONDING;
209 default:
210 return SMP_AUTH_NONE;
211 }
212}
213
Vinicius Costa Gomesb8e66ea2011-06-09 18:50:52 -0300214static void build_pairing_cmd(struct l2cap_conn *conn,
Vinicius Costa Gomes54790f72011-07-07 18:59:38 -0300215 struct smp_cmd_pairing *req,
216 struct smp_cmd_pairing *rsp,
217 __u8 authreq)
Vinicius Costa Gomesb8e66ea2011-06-09 18:50:52 -0300218{
Brian Gix2b64d152011-12-21 16:12:12 -0800219 u8 dist_keys = 0;
Vinicius Costa Gomes54790f72011-07-07 18:59:38 -0300220
Johan Hedberga8b2d5c2012-01-08 23:11:15 +0200221 if (test_bit(HCI_PAIRABLE, &conn->hcon->hdev->dev_flags)) {
Vinicius Costa Gomesca10b5e2011-08-25 20:02:37 -0300222 dist_keys = SMP_DIST_ENC_KEY;
Vinicius Costa Gomes54790f72011-07-07 18:59:38 -0300223 authreq |= SMP_AUTH_BONDING;
Brian Gix2b64d152011-12-21 16:12:12 -0800224 } else {
225 authreq &= ~SMP_AUTH_BONDING;
Vinicius Costa Gomes54790f72011-07-07 18:59:38 -0300226 }
227
228 if (rsp == NULL) {
229 req->io_capability = conn->hcon->io_capability;
230 req->oob_flag = SMP_OOB_NOT_PRESENT;
231 req->max_key_size = SMP_MAX_ENC_KEY_SIZE;
Brian Gix2b64d152011-12-21 16:12:12 -0800232 req->init_key_dist = 0;
Vinicius Costa Gomes54790f72011-07-07 18:59:38 -0300233 req->resp_key_dist = dist_keys;
Johan Hedberg0fb07732012-10-11 16:26:06 +0200234 req->auth_req = (authreq & AUTH_REQ_MASK);
Vinicius Costa Gomes54790f72011-07-07 18:59:38 -0300235 return;
236 }
237
238 rsp->io_capability = conn->hcon->io_capability;
239 rsp->oob_flag = SMP_OOB_NOT_PRESENT;
240 rsp->max_key_size = SMP_MAX_ENC_KEY_SIZE;
Brian Gix2b64d152011-12-21 16:12:12 -0800241 rsp->init_key_dist = 0;
Vinicius Costa Gomes54790f72011-07-07 18:59:38 -0300242 rsp->resp_key_dist = req->resp_key_dist & dist_keys;
Johan Hedberg0fb07732012-10-11 16:26:06 +0200243 rsp->auth_req = (authreq & AUTH_REQ_MASK);
Vinicius Costa Gomesb8e66ea2011-06-09 18:50:52 -0300244}
245
Vinicius Costa Gomes3158c502011-06-14 13:37:42 -0300246static u8 check_enc_key_size(struct l2cap_conn *conn, __u8 max_key_size)
247{
Vinicius Costa Gomes1c1def02011-09-05 14:31:30 -0300248 struct smp_chan *smp = conn->smp_chan;
249
Vinicius Costa Gomes3158c502011-06-14 13:37:42 -0300250 if ((max_key_size > SMP_MAX_ENC_KEY_SIZE) ||
251 (max_key_size < SMP_MIN_ENC_KEY_SIZE))
252 return SMP_ENC_KEY_SIZE;
253
Vinicius Costa Gomesf7aa6112012-01-30 19:29:12 -0300254 smp->enc_key_size = max_key_size;
Vinicius Costa Gomes3158c502011-06-14 13:37:42 -0300255
256 return 0;
257}
258
Brian Gix4f957a72011-11-23 08:28:36 -0800259static void smp_failure(struct l2cap_conn *conn, u8 reason, u8 send)
260{
Johan Hedbergbab73cb2012-02-09 16:07:29 +0200261 struct hci_conn *hcon = conn->hcon;
262
Brian Gix4f957a72011-11-23 08:28:36 -0800263 if (send)
264 smp_send_cmd(conn, SMP_CMD_PAIRING_FAIL, sizeof(reason),
265 &reason);
266
Johan Hedberg51a8efd2012-01-16 06:10:31 +0200267 clear_bit(HCI_CONN_ENCRYPT_PEND, &conn->hcon->flags);
Johan Hedbergbab73cb2012-02-09 16:07:29 +0200268 mgmt_auth_failed(conn->hcon->hdev, conn->dst, hcon->type,
Gustavo F. Padovan04124682012-03-08 01:25:00 -0300269 hcon->dst_type, reason);
Vinicius Costa Gomesf1c09c02012-02-01 18:27:56 -0300270
Andre Guedes27d50462012-08-01 20:34:15 -0300271 cancel_delayed_work_sync(&conn->security_timer);
272
273 if (test_and_clear_bit(HCI_CONN_LE_SMP_PEND, &conn->hcon->flags))
Vinicius Costa Gomesf1c09c02012-02-01 18:27:56 -0300274 smp_chan_destroy(conn);
Brian Gix4f957a72011-11-23 08:28:36 -0800275}
276
Brian Gix2b64d152011-12-21 16:12:12 -0800277#define JUST_WORKS 0x00
278#define JUST_CFM 0x01
279#define REQ_PASSKEY 0x02
280#define CFM_PASSKEY 0x03
281#define REQ_OOB 0x04
282#define OVERLAP 0xFF
283
284static const u8 gen_method[5][5] = {
285 { JUST_WORKS, JUST_CFM, REQ_PASSKEY, JUST_WORKS, REQ_PASSKEY },
286 { JUST_WORKS, JUST_CFM, REQ_PASSKEY, JUST_WORKS, REQ_PASSKEY },
287 { CFM_PASSKEY, CFM_PASSKEY, REQ_PASSKEY, JUST_WORKS, CFM_PASSKEY },
288 { JUST_WORKS, JUST_CFM, JUST_WORKS, JUST_WORKS, JUST_CFM },
289 { CFM_PASSKEY, CFM_PASSKEY, REQ_PASSKEY, JUST_WORKS, OVERLAP },
290};
291
292static int tk_request(struct l2cap_conn *conn, u8 remote_oob, u8 auth,
293 u8 local_io, u8 remote_io)
294{
295 struct hci_conn *hcon = conn->hcon;
296 struct smp_chan *smp = conn->smp_chan;
297 u8 method;
298 u32 passkey = 0;
299 int ret = 0;
300
301 /* Initialize key for JUST WORKS */
302 memset(smp->tk, 0, sizeof(smp->tk));
303 clear_bit(SMP_FLAG_TK_VALID, &smp->smp_flags);
304
305 BT_DBG("tk_request: auth:%d lcl:%d rem:%d", auth, local_io, remote_io);
306
307 /* If neither side wants MITM, use JUST WORKS */
308 /* If either side has unknown io_caps, use JUST WORKS */
309 /* Otherwise, look up method from the table */
310 if (!(auth & SMP_AUTH_MITM) ||
311 local_io > SMP_IO_KEYBOARD_DISPLAY ||
312 remote_io > SMP_IO_KEYBOARD_DISPLAY)
313 method = JUST_WORKS;
314 else
Ido Yarivb3ff53f2012-03-05 20:07:08 +0200315 method = gen_method[remote_io][local_io];
Brian Gix2b64d152011-12-21 16:12:12 -0800316
317 /* If not bonding, don't ask user to confirm a Zero TK */
318 if (!(auth & SMP_AUTH_BONDING) && method == JUST_CFM)
319 method = JUST_WORKS;
320
321 /* If Just Works, Continue with Zero TK */
322 if (method == JUST_WORKS) {
323 set_bit(SMP_FLAG_TK_VALID, &smp->smp_flags);
324 return 0;
325 }
326
327 /* Not Just Works/Confirm results in MITM Authentication */
328 if (method != JUST_CFM)
329 set_bit(SMP_FLAG_MITM_AUTH, &smp->smp_flags);
330
331 /* If both devices have Keyoard-Display I/O, the master
332 * Confirms and the slave Enters the passkey.
333 */
334 if (method == OVERLAP) {
335 if (hcon->link_mode & HCI_LM_MASTER)
336 method = CFM_PASSKEY;
337 else
338 method = REQ_PASSKEY;
339 }
340
341 /* Generate random passkey. Not valid until confirmed. */
342 if (method == CFM_PASSKEY) {
343 u8 key[16];
344
345 memset(key, 0, sizeof(key));
346 get_random_bytes(&passkey, sizeof(passkey));
347 passkey %= 1000000;
348 put_unaligned_le32(passkey, key);
349 swap128(key, smp->tk);
350 BT_DBG("PassKey: %d", passkey);
351 }
352
353 hci_dev_lock(hcon->hdev);
354
355 if (method == REQ_PASSKEY)
Johan Hedberg272d90d2012-02-09 15:26:12 +0200356 ret = mgmt_user_passkey_request(hcon->hdev, conn->dst,
357 hcon->type, hcon->dst_type);
Brian Gix2b64d152011-12-21 16:12:12 -0800358 else
359 ret = mgmt_user_confirm_request(hcon->hdev, conn->dst,
Johan Hedberg272d90d2012-02-09 15:26:12 +0200360 hcon->type, hcon->dst_type,
Brian Gix2b64d152011-12-21 16:12:12 -0800361 cpu_to_le32(passkey), 0);
362
363 hci_dev_unlock(hcon->hdev);
364
365 return ret;
366}
367
Vinicius Costa Gomes8aab4752011-09-05 14:31:31 -0300368static void confirm_work(struct work_struct *work)
369{
370 struct smp_chan *smp = container_of(work, struct smp_chan, confirm);
371 struct l2cap_conn *conn = smp->conn;
372 struct crypto_blkcipher *tfm;
373 struct smp_cmd_pairing_confirm cp;
374 int ret;
375 u8 res[16], reason;
376
377 BT_DBG("conn %p", conn);
378
379 tfm = crypto_alloc_blkcipher("ecb(aes)", 0, CRYPTO_ALG_ASYNC);
380 if (IS_ERR(tfm)) {
381 reason = SMP_UNSPECIFIED;
382 goto error;
383 }
384
385 smp->tfm = tfm;
386
387 if (conn->hcon->out)
388 ret = smp_c1(tfm, smp->tk, smp->prnd, smp->preq, smp->prsp, 0,
Gustavo F. Padovan04124682012-03-08 01:25:00 -0300389 conn->src, conn->hcon->dst_type, conn->dst, res);
Vinicius Costa Gomes8aab4752011-09-05 14:31:31 -0300390 else
391 ret = smp_c1(tfm, smp->tk, smp->prnd, smp->preq, smp->prsp,
Gustavo F. Padovan04124682012-03-08 01:25:00 -0300392 conn->hcon->dst_type, conn->dst, 0, conn->src,
393 res);
Vinicius Costa Gomes8aab4752011-09-05 14:31:31 -0300394 if (ret) {
395 reason = SMP_UNSPECIFIED;
396 goto error;
397 }
398
Brian Gix2b64d152011-12-21 16:12:12 -0800399 clear_bit(SMP_FLAG_CFM_PENDING, &smp->smp_flags);
400
Vinicius Costa Gomes8aab4752011-09-05 14:31:31 -0300401 swap128(res, cp.confirm_val);
402 smp_send_cmd(smp->conn, SMP_CMD_PAIRING_CONFIRM, sizeof(cp), &cp);
403
404 return;
405
406error:
Brian Gix4f957a72011-11-23 08:28:36 -0800407 smp_failure(conn, reason, 1);
Vinicius Costa Gomes8aab4752011-09-05 14:31:31 -0300408}
409
410static void random_work(struct work_struct *work)
411{
412 struct smp_chan *smp = container_of(work, struct smp_chan, random);
413 struct l2cap_conn *conn = smp->conn;
414 struct hci_conn *hcon = conn->hcon;
415 struct crypto_blkcipher *tfm = smp->tfm;
416 u8 reason, confirm[16], res[16], key[16];
417 int ret;
418
419 if (IS_ERR_OR_NULL(tfm)) {
420 reason = SMP_UNSPECIFIED;
421 goto error;
422 }
423
424 BT_DBG("conn %p %s", conn, conn->hcon->out ? "master" : "slave");
425
426 if (hcon->out)
427 ret = smp_c1(tfm, smp->tk, smp->rrnd, smp->preq, smp->prsp, 0,
Gustavo F. Padovan04124682012-03-08 01:25:00 -0300428 conn->src, hcon->dst_type, conn->dst, res);
Vinicius Costa Gomes8aab4752011-09-05 14:31:31 -0300429 else
430 ret = smp_c1(tfm, smp->tk, smp->rrnd, smp->preq, smp->prsp,
Gustavo F. Padovan04124682012-03-08 01:25:00 -0300431 hcon->dst_type, conn->dst, 0, conn->src, res);
Vinicius Costa Gomes8aab4752011-09-05 14:31:31 -0300432 if (ret) {
433 reason = SMP_UNSPECIFIED;
434 goto error;
435 }
436
437 swap128(res, confirm);
438
439 if (memcmp(smp->pcnf, confirm, sizeof(smp->pcnf)) != 0) {
440 BT_ERR("Pairing failed (confirmation values mismatch)");
441 reason = SMP_CONFIRM_FAILED;
442 goto error;
443 }
444
445 if (hcon->out) {
446 u8 stk[16], rand[8];
447 __le16 ediv;
448
449 memset(rand, 0, sizeof(rand));
450 ediv = 0;
451
452 smp_s1(tfm, smp->tk, smp->rrnd, smp->prnd, key);
453 swap128(key, stk);
454
Vinicius Costa Gomesf7aa6112012-01-30 19:29:12 -0300455 memset(stk + smp->enc_key_size, 0,
Gustavo F. Padovan04124682012-03-08 01:25:00 -0300456 SMP_MAX_ENC_KEY_SIZE - smp->enc_key_size);
Vinicius Costa Gomes8aab4752011-09-05 14:31:31 -0300457
Johan Hedberg51a8efd2012-01-16 06:10:31 +0200458 if (test_and_set_bit(HCI_CONN_ENCRYPT_PEND, &hcon->flags)) {
Vinicius Costa Gomes8aab4752011-09-05 14:31:31 -0300459 reason = SMP_UNSPECIFIED;
460 goto error;
461 }
462
463 hci_le_start_enc(hcon, ediv, rand, stk);
Vinicius Costa Gomesf7aa6112012-01-30 19:29:12 -0300464 hcon->enc_key_size = smp->enc_key_size;
Vinicius Costa Gomes8aab4752011-09-05 14:31:31 -0300465 } else {
466 u8 stk[16], r[16], rand[8];
467 __le16 ediv;
468
469 memset(rand, 0, sizeof(rand));
470 ediv = 0;
471
472 swap128(smp->prnd, r);
473 smp_send_cmd(conn, SMP_CMD_PAIRING_RANDOM, sizeof(r), r);
474
475 smp_s1(tfm, smp->tk, smp->prnd, smp->rrnd, key);
476 swap128(key, stk);
477
Vinicius Costa Gomesf7aa6112012-01-30 19:29:12 -0300478 memset(stk + smp->enc_key_size, 0,
479 SMP_MAX_ENC_KEY_SIZE - smp->enc_key_size);
Vinicius Costa Gomes8aab4752011-09-05 14:31:31 -0300480
Vinicius Costa Gomesc9839a12012-02-02 21:08:01 -0300481 hci_add_ltk(hcon->hdev, conn->dst, hcon->dst_type,
Gustavo F. Padovan04124682012-03-08 01:25:00 -0300482 HCI_SMP_STK_SLAVE, 0, 0, stk, smp->enc_key_size,
483 ediv, rand);
Vinicius Costa Gomes8aab4752011-09-05 14:31:31 -0300484 }
485
486 return;
487
488error:
Brian Gix4f957a72011-11-23 08:28:36 -0800489 smp_failure(conn, reason, 1);
Vinicius Costa Gomes8aab4752011-09-05 14:31:31 -0300490}
491
492static struct smp_chan *smp_chan_create(struct l2cap_conn *conn)
493{
494 struct smp_chan *smp;
495
496 smp = kzalloc(sizeof(struct smp_chan), GFP_ATOMIC);
497 if (!smp)
498 return NULL;
499
500 INIT_WORK(&smp->confirm, confirm_work);
501 INIT_WORK(&smp->random, random_work);
502
503 smp->conn = conn;
504 conn->smp_chan = smp;
Brian Gix2b64d152011-12-21 16:12:12 -0800505 conn->hcon->smp_conn = conn;
Vinicius Costa Gomes8aab4752011-09-05 14:31:31 -0300506
507 hci_conn_hold(conn->hcon);
508
509 return smp;
510}
511
512void smp_chan_destroy(struct l2cap_conn *conn)
513{
Brian Gixc8eb9692011-11-23 08:28:35 -0800514 struct smp_chan *smp = conn->smp_chan;
515
Vinicius Costa Gomesf1c09c02012-02-01 18:27:56 -0300516 BUG_ON(!smp);
Brian Gixc8eb9692011-11-23 08:28:35 -0800517
518 if (smp->tfm)
519 crypto_free_blkcipher(smp->tfm);
520
521 kfree(smp);
522 conn->smp_chan = NULL;
Brian Gix2b64d152011-12-21 16:12:12 -0800523 conn->hcon->smp_conn = NULL;
Vinicius Costa Gomes8aab4752011-09-05 14:31:31 -0300524 hci_conn_put(conn->hcon);
525}
526
Brian Gix2b64d152011-12-21 16:12:12 -0800527int smp_user_confirm_reply(struct hci_conn *hcon, u16 mgmt_op, __le32 passkey)
528{
529 struct l2cap_conn *conn = hcon->smp_conn;
530 struct smp_chan *smp;
531 u32 value;
532 u8 key[16];
533
534 BT_DBG("");
535
536 if (!conn)
537 return -ENOTCONN;
538
539 smp = conn->smp_chan;
540
541 switch (mgmt_op) {
542 case MGMT_OP_USER_PASSKEY_REPLY:
543 value = le32_to_cpu(passkey);
544 memset(key, 0, sizeof(key));
545 BT_DBG("PassKey: %d", value);
546 put_unaligned_le32(value, key);
547 swap128(key, smp->tk);
548 /* Fall Through */
549 case MGMT_OP_USER_CONFIRM_REPLY:
550 set_bit(SMP_FLAG_TK_VALID, &smp->smp_flags);
551 break;
552 case MGMT_OP_USER_PASSKEY_NEG_REPLY:
553 case MGMT_OP_USER_CONFIRM_NEG_REPLY:
554 smp_failure(conn, SMP_PASSKEY_ENTRY_FAILED, 1);
555 return 0;
556 default:
557 smp_failure(conn, SMP_PASSKEY_ENTRY_FAILED, 1);
558 return -EOPNOTSUPP;
559 }
560
561 /* If it is our turn to send Pairing Confirm, do so now */
562 if (test_bit(SMP_FLAG_CFM_PENDING, &smp->smp_flags))
563 queue_work(hcon->hdev->workqueue, &smp->confirm);
564
565 return 0;
566}
567
Vinicius Costa Gomesda85e5e2011-06-09 18:50:53 -0300568static u8 smp_cmd_pairing_req(struct l2cap_conn *conn, struct sk_buff *skb)
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300569{
Vinicius Costa Gomes3158c502011-06-14 13:37:42 -0300570 struct smp_cmd_pairing rsp, *req = (void *) skb->data;
Vinicius Costa Gomes8aab4752011-09-05 14:31:31 -0300571 struct smp_chan *smp;
Vinicius Costa Gomes3158c502011-06-14 13:37:42 -0300572 u8 key_size;
Brian Gix2b64d152011-12-21 16:12:12 -0800573 u8 auth = SMP_AUTH_NONE;
Vinicius Costa Gomes8aab4752011-09-05 14:31:31 -0300574 int ret;
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300575
576 BT_DBG("conn %p", conn);
577
Brian Gix2b64d152011-12-21 16:12:12 -0800578 if (conn->hcon->link_mode & HCI_LM_MASTER)
579 return SMP_CMD_NOTSUPP;
580
Johan Hedberg51a8efd2012-01-16 06:10:31 +0200581 if (!test_and_set_bit(HCI_CONN_LE_SMP_PEND, &conn->hcon->flags))
Vinicius Costa Gomes8aab4752011-09-05 14:31:31 -0300582 smp = smp_chan_create(conn);
583
584 smp = conn->smp_chan;
Vinicius Costa Gomesd26a2342011-08-19 21:06:51 -0300585
Vinicius Costa Gomes1c1def02011-09-05 14:31:30 -0300586 smp->preq[0] = SMP_CMD_PAIRING_REQ;
587 memcpy(&smp->preq[1], req, sizeof(*req));
Vinicius Costa Gomes3158c502011-06-14 13:37:42 -0300588 skb_pull(skb, sizeof(*req));
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300589
Brian Gix2b64d152011-12-21 16:12:12 -0800590 /* We didn't start the pairing, so match remote */
591 if (req->auth_req & SMP_AUTH_BONDING)
592 auth = req->auth_req;
Vinicius Costa Gomesda85e5e2011-06-09 18:50:53 -0300593
Ido Yarivfdde0a22012-03-05 20:09:38 +0200594 conn->hcon->pending_sec_level = authreq_to_seclevel(auth);
595
Brian Gix2b64d152011-12-21 16:12:12 -0800596 build_pairing_cmd(conn, req, &rsp, auth);
Vinicius Costa Gomes3158c502011-06-14 13:37:42 -0300597
598 key_size = min(req->max_key_size, rsp.max_key_size);
599 if (check_enc_key_size(conn, key_size))
600 return SMP_ENC_KEY_SIZE;
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300601
Vinicius Costa Gomes8aab4752011-09-05 14:31:31 -0300602 ret = smp_rand(smp->prnd);
603 if (ret)
604 return SMP_UNSPECIFIED;
605
Vinicius Costa Gomes1c1def02011-09-05 14:31:30 -0300606 smp->prsp[0] = SMP_CMD_PAIRING_RSP;
607 memcpy(&smp->prsp[1], &rsp, sizeof(rsp));
Anderson Brigliaf01ead32011-06-09 18:50:45 -0300608
Vinicius Costa Gomes3158c502011-06-14 13:37:42 -0300609 smp_send_cmd(conn, SMP_CMD_PAIRING_RSP, sizeof(rsp), &rsp);
Vinicius Costa Gomesda85e5e2011-06-09 18:50:53 -0300610
Brian Gix2b64d152011-12-21 16:12:12 -0800611 /* Request setup of TK */
612 ret = tk_request(conn, 0, auth, rsp.io_capability, req->io_capability);
613 if (ret)
614 return SMP_UNSPECIFIED;
615
Vinicius Costa Gomesda85e5e2011-06-09 18:50:53 -0300616 return 0;
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300617}
618
Vinicius Costa Gomesda85e5e2011-06-09 18:50:53 -0300619static u8 smp_cmd_pairing_rsp(struct l2cap_conn *conn, struct sk_buff *skb)
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300620{
Vinicius Costa Gomes3158c502011-06-14 13:37:42 -0300621 struct smp_cmd_pairing *req, *rsp = (void *) skb->data;
Vinicius Costa Gomes1c1def02011-09-05 14:31:30 -0300622 struct smp_chan *smp = conn->smp_chan;
Vinicius Costa Gomes8aab4752011-09-05 14:31:31 -0300623 struct hci_dev *hdev = conn->hcon->hdev;
Brian Gix2b64d152011-12-21 16:12:12 -0800624 u8 key_size, auth = SMP_AUTH_NONE;
Anderson Briglia7d24ddc2011-06-09 18:50:46 -0300625 int ret;
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300626
627 BT_DBG("conn %p", conn);
628
Brian Gix2b64d152011-12-21 16:12:12 -0800629 if (!(conn->hcon->link_mode & HCI_LM_MASTER))
630 return SMP_CMD_NOTSUPP;
631
Vinicius Costa Gomes3158c502011-06-14 13:37:42 -0300632 skb_pull(skb, sizeof(*rsp));
Vinicius Costa Gomesda85e5e2011-06-09 18:50:53 -0300633
Vinicius Costa Gomes1c1def02011-09-05 14:31:30 -0300634 req = (void *) &smp->preq[1];
Vinicius Costa Gomes3158c502011-06-14 13:37:42 -0300635
636 key_size = min(req->max_key_size, rsp->max_key_size);
637 if (check_enc_key_size(conn, key_size))
638 return SMP_ENC_KEY_SIZE;
639
Vinicius Costa Gomes1c1def02011-09-05 14:31:30 -0300640 ret = smp_rand(smp->prnd);
Anderson Briglia7d24ddc2011-06-09 18:50:46 -0300641 if (ret)
Vinicius Costa Gomesda85e5e2011-06-09 18:50:53 -0300642 return SMP_UNSPECIFIED;
Anderson Briglia7d24ddc2011-06-09 18:50:46 -0300643
Vinicius Costa Gomes8aab4752011-09-05 14:31:31 -0300644 smp->prsp[0] = SMP_CMD_PAIRING_RSP;
645 memcpy(&smp->prsp[1], rsp, sizeof(*rsp));
Anderson Briglia7d24ddc2011-06-09 18:50:46 -0300646
Brian Gix2b64d152011-12-21 16:12:12 -0800647 if ((req->auth_req & SMP_AUTH_BONDING) &&
648 (rsp->auth_req & SMP_AUTH_BONDING))
649 auth = SMP_AUTH_BONDING;
650
651 auth |= (req->auth_req | rsp->auth_req) & SMP_AUTH_MITM;
652
653 ret = tk_request(conn, 0, auth, rsp->io_capability, req->io_capability);
654 if (ret)
655 return SMP_UNSPECIFIED;
656
657 set_bit(SMP_FLAG_CFM_PENDING, &smp->smp_flags);
658
659 /* Can't compose response until we have been confirmed */
660 if (!test_bit(SMP_FLAG_TK_VALID, &smp->smp_flags))
661 return 0;
662
Vinicius Costa Gomes8aab4752011-09-05 14:31:31 -0300663 queue_work(hdev->workqueue, &smp->confirm);
Vinicius Costa Gomesda85e5e2011-06-09 18:50:53 -0300664
665 return 0;
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300666}
667
Vinicius Costa Gomesda85e5e2011-06-09 18:50:53 -0300668static u8 smp_cmd_pairing_confirm(struct l2cap_conn *conn, struct sk_buff *skb)
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300669{
Vinicius Costa Gomes1c1def02011-09-05 14:31:30 -0300670 struct smp_chan *smp = conn->smp_chan;
Vinicius Costa Gomes8aab4752011-09-05 14:31:31 -0300671 struct hci_dev *hdev = conn->hcon->hdev;
Anderson Briglia7d24ddc2011-06-09 18:50:46 -0300672
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300673 BT_DBG("conn %p %s", conn, conn->hcon->out ? "master" : "slave");
674
Vinicius Costa Gomes1c1def02011-09-05 14:31:30 -0300675 memcpy(smp->pcnf, skb->data, sizeof(smp->pcnf));
676 skb_pull(skb, sizeof(smp->pcnf));
Anderson Briglia7d24ddc2011-06-09 18:50:46 -0300677
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300678 if (conn->hcon->out) {
Anderson Briglia7d24ddc2011-06-09 18:50:46 -0300679 u8 random[16];
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300680
Vinicius Costa Gomes1c1def02011-09-05 14:31:30 -0300681 swap128(smp->prnd, random);
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300682 smp_send_cmd(conn, SMP_CMD_PAIRING_RANDOM, sizeof(random),
Anderson Briglia7d24ddc2011-06-09 18:50:46 -0300683 random);
Brian Gix2b64d152011-12-21 16:12:12 -0800684 } else if (test_bit(SMP_FLAG_TK_VALID, &smp->smp_flags)) {
Vinicius Costa Gomes8aab4752011-09-05 14:31:31 -0300685 queue_work(hdev->workqueue, &smp->confirm);
Brian Gix2b64d152011-12-21 16:12:12 -0800686 } else {
687 set_bit(SMP_FLAG_CFM_PENDING, &smp->smp_flags);
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300688 }
Vinicius Costa Gomesda85e5e2011-06-09 18:50:53 -0300689
690 return 0;
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300691}
692
Vinicius Costa Gomesda85e5e2011-06-09 18:50:53 -0300693static u8 smp_cmd_pairing_random(struct l2cap_conn *conn, struct sk_buff *skb)
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300694{
Vinicius Costa Gomes1c1def02011-09-05 14:31:30 -0300695 struct smp_chan *smp = conn->smp_chan;
Vinicius Costa Gomes8aab4752011-09-05 14:31:31 -0300696 struct hci_dev *hdev = conn->hcon->hdev;
Anderson Briglia7d24ddc2011-06-09 18:50:46 -0300697
Vinicius Costa Gomes8aab4752011-09-05 14:31:31 -0300698 BT_DBG("conn %p", conn);
Anderson Briglia7d24ddc2011-06-09 18:50:46 -0300699
Vinicius Costa Gomes8aab4752011-09-05 14:31:31 -0300700 swap128(skb->data, smp->rrnd);
701 skb_pull(skb, sizeof(smp->rrnd));
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300702
Vinicius Costa Gomes8aab4752011-09-05 14:31:31 -0300703 queue_work(hdev->workqueue, &smp->random);
Vinicius Costa Gomesda85e5e2011-06-09 18:50:53 -0300704
705 return 0;
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300706}
707
Vinicius Costa Gomes988c5992011-08-25 20:02:28 -0300708static u8 smp_ltk_encrypt(struct l2cap_conn *conn)
709{
Vinicius Costa Gomesc9839a12012-02-02 21:08:01 -0300710 struct smp_ltk *key;
Vinicius Costa Gomes988c5992011-08-25 20:02:28 -0300711 struct hci_conn *hcon = conn->hcon;
712
Vinicius Costa Gomesc9839a12012-02-02 21:08:01 -0300713 key = hci_find_ltk_by_addr(hcon->hdev, conn->dst, hcon->dst_type);
Vinicius Costa Gomes988c5992011-08-25 20:02:28 -0300714 if (!key)
715 return 0;
716
Johan Hedberg51a8efd2012-01-16 06:10:31 +0200717 if (test_and_set_bit(HCI_CONN_ENCRYPT_PEND, &hcon->flags))
Vinicius Costa Gomes988c5992011-08-25 20:02:28 -0300718 return 1;
719
Vinicius Costa Gomesc9839a12012-02-02 21:08:01 -0300720 hci_le_start_enc(hcon, key->ediv, key->rand, key->val);
721 hcon->enc_key_size = key->enc_size;
Vinicius Costa Gomes988c5992011-08-25 20:02:28 -0300722
723 return 1;
724
725}
Vinicius Costa Gomesda85e5e2011-06-09 18:50:53 -0300726static u8 smp_cmd_security_req(struct l2cap_conn *conn, struct sk_buff *skb)
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300727{
728 struct smp_cmd_security_req *rp = (void *) skb->data;
729 struct smp_cmd_pairing cp;
Vinicius Costa Gomesf1cb9af2011-01-26 21:42:57 -0300730 struct hci_conn *hcon = conn->hcon;
Vinicius Costa Gomes8aab4752011-09-05 14:31:31 -0300731 struct smp_chan *smp;
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300732
733 BT_DBG("conn %p", conn);
734
Brian Gix2b64d152011-12-21 16:12:12 -0800735 hcon->pending_sec_level = authreq_to_seclevel(rp->auth_req);
Vinicius Costa Gomesfeb45eb2011-08-25 20:02:35 -0300736
Vinicius Costa Gomes988c5992011-08-25 20:02:28 -0300737 if (smp_ltk_encrypt(conn))
738 return 0;
739
Johan Hedberg51a8efd2012-01-16 06:10:31 +0200740 if (test_and_set_bit(HCI_CONN_LE_SMP_PEND, &hcon->flags))
Vinicius Costa Gomesda85e5e2011-06-09 18:50:53 -0300741 return 0;
Vinicius Costa Gomesf1cb9af2011-01-26 21:42:57 -0300742
Vinicius Costa Gomes8aab4752011-09-05 14:31:31 -0300743 smp = smp_chan_create(conn);
Vinicius Costa Gomesd26a2342011-08-19 21:06:51 -0300744
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300745 skb_pull(skb, sizeof(*rp));
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300746
Vinicius Costa Gomesda85e5e2011-06-09 18:50:53 -0300747 memset(&cp, 0, sizeof(cp));
Vinicius Costa Gomes54790f72011-07-07 18:59:38 -0300748 build_pairing_cmd(conn, &cp, NULL, rp->auth_req);
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300749
Vinicius Costa Gomes1c1def02011-09-05 14:31:30 -0300750 smp->preq[0] = SMP_CMD_PAIRING_REQ;
751 memcpy(&smp->preq[1], &cp, sizeof(cp));
Anderson Brigliaf01ead32011-06-09 18:50:45 -0300752
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300753 smp_send_cmd(conn, SMP_CMD_PAIRING_REQ, sizeof(cp), &cp);
Vinicius Costa Gomesf1cb9af2011-01-26 21:42:57 -0300754
Vinicius Costa Gomesda85e5e2011-06-09 18:50:53 -0300755 return 0;
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300756}
757
Vinicius Costa Gomes0fcc0802012-08-23 21:32:43 -0300758int smp_conn_security(struct hci_conn *hcon, __u8 sec_level)
Anderson Brigliaeb492e02011-06-09 18:50:40 -0300759{
Vinicius Costa Gomes0fcc0802012-08-23 21:32:43 -0300760 struct l2cap_conn *conn = hcon->l2cap_data;
Vinicius Costa Gomes1c1def02011-09-05 14:31:30 -0300761 struct smp_chan *smp = conn->smp_chan;
Brian Gix2b64d152011-12-21 16:12:12 -0800762 __u8 authreq;
Anderson Brigliaeb492e02011-06-09 18:50:40 -0300763
Vinicius Costa Gomes3a0259b2011-06-09 18:50:43 -0300764 BT_DBG("conn %p hcon %p level 0x%2.2x", conn, hcon, sec_level);
765
Andre Guedes2e65c9d2011-06-30 19:20:56 -0300766 if (!lmp_host_le_capable(hcon->hdev))
767 return 1;
768
Vinicius Costa Gomesf1cb9af2011-01-26 21:42:57 -0300769 if (sec_level == BT_SECURITY_LOW)
Anderson Brigliaeb492e02011-06-09 18:50:40 -0300770 return 1;
Vinicius Costa Gomesf1cb9af2011-01-26 21:42:57 -0300771
772 if (hcon->sec_level >= sec_level)
773 return 1;
774
Vinicius Costa Gomes988c5992011-08-25 20:02:28 -0300775 if (hcon->link_mode & HCI_LM_MASTER)
776 if (smp_ltk_encrypt(conn))
Vinicius Costa Gomes02bc7452011-07-07 18:59:41 -0300777 goto done;
Vinicius Costa Gomesd26a2342011-08-19 21:06:51 -0300778
Johan Hedberg51a8efd2012-01-16 06:10:31 +0200779 if (test_and_set_bit(HCI_CONN_LE_SMP_PEND, &hcon->flags))
Vinicius Costa Gomesd26a2342011-08-19 21:06:51 -0300780 return 0;
781
Vinicius Costa Gomes8aab4752011-09-05 14:31:31 -0300782 smp = smp_chan_create(conn);
Brian Gix2b64d152011-12-21 16:12:12 -0800783 if (!smp)
784 return 1;
785
786 authreq = seclevel_to_authreq(sec_level);
Vinicius Costa Gomesd26a2342011-08-19 21:06:51 -0300787
Vinicius Costa Gomesd26a2342011-08-19 21:06:51 -0300788 if (hcon->link_mode & HCI_LM_MASTER) {
789 struct smp_cmd_pairing cp;
Anderson Brigliaf01ead32011-06-09 18:50:45 -0300790
Brian Gix2b64d152011-12-21 16:12:12 -0800791 build_pairing_cmd(conn, &cp, NULL, authreq);
Vinicius Costa Gomes1c1def02011-09-05 14:31:30 -0300792 smp->preq[0] = SMP_CMD_PAIRING_REQ;
793 memcpy(&smp->preq[1], &cp, sizeof(cp));
Anderson Brigliaf01ead32011-06-09 18:50:45 -0300794
Anderson Brigliaeb492e02011-06-09 18:50:40 -0300795 smp_send_cmd(conn, SMP_CMD_PAIRING_REQ, sizeof(cp), &cp);
796 } else {
797 struct smp_cmd_security_req cp;
Brian Gix2b64d152011-12-21 16:12:12 -0800798 cp.auth_req = authreq;
Anderson Brigliaeb492e02011-06-09 18:50:40 -0300799 smp_send_cmd(conn, SMP_CMD_SECURITY_REQ, sizeof(cp), &cp);
800 }
801
Vinicius Costa Gomes02bc7452011-07-07 18:59:41 -0300802done:
Vinicius Costa Gomesf1cb9af2011-01-26 21:42:57 -0300803 hcon->pending_sec_level = sec_level;
Vinicius Costa Gomesf1cb9af2011-01-26 21:42:57 -0300804
Anderson Brigliaeb492e02011-06-09 18:50:40 -0300805 return 0;
806}
807
Vinicius Costa Gomes7034b912011-07-07 18:59:34 -0300808static int smp_cmd_encrypt_info(struct l2cap_conn *conn, struct sk_buff *skb)
809{
Vinicius Costa Gomes16b90832011-07-07 18:59:39 -0300810 struct smp_cmd_encrypt_info *rp = (void *) skb->data;
Vinicius Costa Gomes1c1def02011-09-05 14:31:30 -0300811 struct smp_chan *smp = conn->smp_chan;
Vinicius Costa Gomes16b90832011-07-07 18:59:39 -0300812
813 skb_pull(skb, sizeof(*rp));
814
Vinicius Costa Gomes1c1def02011-09-05 14:31:30 -0300815 memcpy(smp->tk, rp->ltk, sizeof(smp->tk));
Vinicius Costa Gomes16b90832011-07-07 18:59:39 -0300816
Vinicius Costa Gomes7034b912011-07-07 18:59:34 -0300817 return 0;
818}
819
820static int smp_cmd_master_ident(struct l2cap_conn *conn, struct sk_buff *skb)
821{
Vinicius Costa Gomes16b90832011-07-07 18:59:39 -0300822 struct smp_cmd_master_ident *rp = (void *) skb->data;
Vinicius Costa Gomes1c1def02011-09-05 14:31:30 -0300823 struct smp_chan *smp = conn->smp_chan;
Vinicius Costa Gomesc9839a12012-02-02 21:08:01 -0300824 struct hci_dev *hdev = conn->hcon->hdev;
825 struct hci_conn *hcon = conn->hcon;
826 u8 authenticated;
Vinicius Costa Gomes7034b912011-07-07 18:59:34 -0300827
Vinicius Costa Gomes16b90832011-07-07 18:59:39 -0300828 skb_pull(skb, sizeof(*rp));
829
Vinicius Costa Gomesc9839a12012-02-02 21:08:01 -0300830 hci_dev_lock(hdev);
831 authenticated = (conn->hcon->sec_level == BT_SECURITY_HIGH);
832 hci_add_ltk(conn->hcon->hdev, conn->dst, hcon->dst_type,
Gustavo F. Padovan04124682012-03-08 01:25:00 -0300833 HCI_SMP_LTK, 1, authenticated, smp->tk, smp->enc_key_size,
834 rp->ediv, rp->rand);
Vinicius Costa Gomes7034b912011-07-07 18:59:34 -0300835 smp_distribute_keys(conn, 1);
Vinicius Costa Gomesc9839a12012-02-02 21:08:01 -0300836 hci_dev_unlock(hdev);
Vinicius Costa Gomes7034b912011-07-07 18:59:34 -0300837
838 return 0;
839}
840
Anderson Brigliaeb492e02011-06-09 18:50:40 -0300841int smp_sig_channel(struct l2cap_conn *conn, struct sk_buff *skb)
842{
843 __u8 code = skb->data[0];
844 __u8 reason;
845 int err = 0;
846
Andre Guedes2e65c9d2011-06-30 19:20:56 -0300847 if (!lmp_host_le_capable(conn->hcon->hdev)) {
848 err = -ENOTSUPP;
849 reason = SMP_PAIRING_NOTSUPP;
850 goto done;
851 }
852
Anderson Brigliaeb492e02011-06-09 18:50:40 -0300853 skb_pull(skb, sizeof(code));
854
Johan Hedberga256a4c2013-01-29 10:44:23 -0600855 /*
856 * The SMP context must be initialized for all other PDUs except
857 * pairing and security requests. If we get any other PDU when
858 * not initialized simply disconnect (done if this function
859 * returns an error).
860 */
861 if (code != SMP_CMD_PAIRING_REQ && code != SMP_CMD_SECURITY_REQ &&
862 !conn->smp_chan) {
863 BT_ERR("Unexpected SMP command 0x%02x. Disconnecting.", code);
864 kfree_skb(skb);
865 return -ENOTSUPP;
866 }
867
Anderson Brigliaeb492e02011-06-09 18:50:40 -0300868 switch (code) {
869 case SMP_CMD_PAIRING_REQ:
Vinicius Costa Gomesda85e5e2011-06-09 18:50:53 -0300870 reason = smp_cmd_pairing_req(conn, skb);
Anderson Brigliaeb492e02011-06-09 18:50:40 -0300871 break;
872
873 case SMP_CMD_PAIRING_FAIL:
Brian Gix4f957a72011-11-23 08:28:36 -0800874 smp_failure(conn, skb->data[0], 0);
Vinicius Costa Gomesda85e5e2011-06-09 18:50:53 -0300875 reason = 0;
876 err = -EPERM;
Anderson Brigliaeb492e02011-06-09 18:50:40 -0300877 break;
878
879 case SMP_CMD_PAIRING_RSP:
Vinicius Costa Gomesda85e5e2011-06-09 18:50:53 -0300880 reason = smp_cmd_pairing_rsp(conn, skb);
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300881 break;
882
883 case SMP_CMD_SECURITY_REQ:
Vinicius Costa Gomesda85e5e2011-06-09 18:50:53 -0300884 reason = smp_cmd_security_req(conn, skb);
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300885 break;
886
Anderson Brigliaeb492e02011-06-09 18:50:40 -0300887 case SMP_CMD_PAIRING_CONFIRM:
Vinicius Costa Gomesda85e5e2011-06-09 18:50:53 -0300888 reason = smp_cmd_pairing_confirm(conn, skb);
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300889 break;
890
Anderson Brigliaeb492e02011-06-09 18:50:40 -0300891 case SMP_CMD_PAIRING_RANDOM:
Vinicius Costa Gomesda85e5e2011-06-09 18:50:53 -0300892 reason = smp_cmd_pairing_random(conn, skb);
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300893 break;
894
Anderson Brigliaeb492e02011-06-09 18:50:40 -0300895 case SMP_CMD_ENCRYPT_INFO:
Vinicius Costa Gomes7034b912011-07-07 18:59:34 -0300896 reason = smp_cmd_encrypt_info(conn, skb);
897 break;
898
Anderson Brigliaeb492e02011-06-09 18:50:40 -0300899 case SMP_CMD_MASTER_IDENT:
Vinicius Costa Gomes7034b912011-07-07 18:59:34 -0300900 reason = smp_cmd_master_ident(conn, skb);
901 break;
902
Anderson Brigliaeb492e02011-06-09 18:50:40 -0300903 case SMP_CMD_IDENT_INFO:
904 case SMP_CMD_IDENT_ADDR_INFO:
905 case SMP_CMD_SIGN_INFO:
Vinicius Costa Gomes7034b912011-07-07 18:59:34 -0300906 /* Just ignored */
907 reason = 0;
908 break;
909
Anderson Brigliaeb492e02011-06-09 18:50:40 -0300910 default:
911 BT_DBG("Unknown command code 0x%2.2x", code);
912
913 reason = SMP_CMD_NOTSUPP;
Vinicius Costa Gomes3a0259b2011-06-09 18:50:43 -0300914 err = -EOPNOTSUPP;
915 goto done;
916 }
917
918done:
919 if (reason)
Brian Gix4f957a72011-11-23 08:28:36 -0800920 smp_failure(conn, reason, 1);
Anderson Brigliaeb492e02011-06-09 18:50:40 -0300921
922 kfree_skb(skb);
923 return err;
924}
Vinicius Costa Gomes7034b912011-07-07 18:59:34 -0300925
926int smp_distribute_keys(struct l2cap_conn *conn, __u8 force)
927{
928 struct smp_cmd_pairing *req, *rsp;
Vinicius Costa Gomes1c1def02011-09-05 14:31:30 -0300929 struct smp_chan *smp = conn->smp_chan;
Vinicius Costa Gomes7034b912011-07-07 18:59:34 -0300930 __u8 *keydist;
931
932 BT_DBG("conn %p force %d", conn, force);
933
Johan Hedberg51a8efd2012-01-16 06:10:31 +0200934 if (!test_bit(HCI_CONN_LE_SMP_PEND, &conn->hcon->flags))
Vinicius Costa Gomesd26a2342011-08-19 21:06:51 -0300935 return 0;
936
Vinicius Costa Gomes1c1def02011-09-05 14:31:30 -0300937 rsp = (void *) &smp->prsp[1];
Vinicius Costa Gomes7034b912011-07-07 18:59:34 -0300938
939 /* The responder sends its keys first */
940 if (!force && conn->hcon->out && (rsp->resp_key_dist & 0x07))
941 return 0;
942
Vinicius Costa Gomes1c1def02011-09-05 14:31:30 -0300943 req = (void *) &smp->preq[1];
Vinicius Costa Gomes7034b912011-07-07 18:59:34 -0300944
945 if (conn->hcon->out) {
946 keydist = &rsp->init_key_dist;
947 *keydist &= req->init_key_dist;
948 } else {
949 keydist = &rsp->resp_key_dist;
950 *keydist &= req->resp_key_dist;
951 }
952
953
954 BT_DBG("keydist 0x%x", *keydist);
955
956 if (*keydist & SMP_DIST_ENC_KEY) {
957 struct smp_cmd_encrypt_info enc;
958 struct smp_cmd_master_ident ident;
Vinicius Costa Gomesc9839a12012-02-02 21:08:01 -0300959 struct hci_conn *hcon = conn->hcon;
960 u8 authenticated;
Vinicius Costa Gomes7034b912011-07-07 18:59:34 -0300961 __le16 ediv;
962
963 get_random_bytes(enc.ltk, sizeof(enc.ltk));
964 get_random_bytes(&ediv, sizeof(ediv));
965 get_random_bytes(ident.rand, sizeof(ident.rand));
966
967 smp_send_cmd(conn, SMP_CMD_ENCRYPT_INFO, sizeof(enc), &enc);
968
Vinicius Costa Gomesc9839a12012-02-02 21:08:01 -0300969 authenticated = hcon->sec_level == BT_SECURITY_HIGH;
970 hci_add_ltk(conn->hcon->hdev, conn->dst, hcon->dst_type,
Gustavo F. Padovan04124682012-03-08 01:25:00 -0300971 HCI_SMP_LTK_SLAVE, 1, authenticated,
972 enc.ltk, smp->enc_key_size, ediv, ident.rand);
Vinicius Costa Gomes16b90832011-07-07 18:59:39 -0300973
Vinicius Costa Gomes7034b912011-07-07 18:59:34 -0300974 ident.ediv = cpu_to_le16(ediv);
975
976 smp_send_cmd(conn, SMP_CMD_MASTER_IDENT, sizeof(ident), &ident);
977
978 *keydist &= ~SMP_DIST_ENC_KEY;
979 }
980
981 if (*keydist & SMP_DIST_ID_KEY) {
982 struct smp_cmd_ident_addr_info addrinfo;
983 struct smp_cmd_ident_info idinfo;
984
985 /* Send a dummy key */
986 get_random_bytes(idinfo.irk, sizeof(idinfo.irk));
987
988 smp_send_cmd(conn, SMP_CMD_IDENT_INFO, sizeof(idinfo), &idinfo);
989
990 /* Just public address */
991 memset(&addrinfo, 0, sizeof(addrinfo));
992 bacpy(&addrinfo.bdaddr, conn->src);
993
994 smp_send_cmd(conn, SMP_CMD_IDENT_ADDR_INFO, sizeof(addrinfo),
995 &addrinfo);
996
997 *keydist &= ~SMP_DIST_ID_KEY;
998 }
999
1000 if (*keydist & SMP_DIST_SIGN) {
1001 struct smp_cmd_sign_info sign;
1002
1003 /* Send a dummy key */
1004 get_random_bytes(sign.csrk, sizeof(sign.csrk));
1005
1006 smp_send_cmd(conn, SMP_CMD_SIGN_INFO, sizeof(sign), &sign);
1007
1008 *keydist &= ~SMP_DIST_SIGN;
1009 }
1010
Vinicius Costa Gomesd26a2342011-08-19 21:06:51 -03001011 if (conn->hcon->out || force) {
Johan Hedberg51a8efd2012-01-16 06:10:31 +02001012 clear_bit(HCI_CONN_LE_SMP_PEND, &conn->hcon->flags);
Gustavo F. Padovan6c9d42a2011-12-20 10:57:27 -02001013 cancel_delayed_work_sync(&conn->security_timer);
Vinicius Costa Gomes8aab4752011-09-05 14:31:31 -03001014 smp_chan_destroy(conn);
Vinicius Costa Gomesd26a2342011-08-19 21:06:51 -03001015 }
1016
Vinicius Costa Gomes7034b912011-07-07 18:59:34 -03001017 return 0;
1018}