blob: 8f56282c247d0abc2f7dd7633ad2f141e682711f [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
Anderson Brigliad22ef0b2011-06-09 18:50:44 -030034static inline void swap128(u8 src[16], u8 dst[16])
35{
36 int i;
37 for (i = 0; i < 16; i++)
38 dst[15 - i] = src[i];
39}
40
41static inline void swap56(u8 src[7], u8 dst[7])
42{
43 int i;
44 for (i = 0; i < 7; i++)
45 dst[6 - i] = src[i];
46}
47
48static int smp_e(struct crypto_blkcipher *tfm, const u8 *k, u8 *r)
49{
50 struct blkcipher_desc desc;
51 struct scatterlist sg;
52 int err, iv_len;
53 unsigned char iv[128];
54
55 if (tfm == NULL) {
56 BT_ERR("tfm %p", tfm);
57 return -EINVAL;
58 }
59
60 desc.tfm = tfm;
61 desc.flags = 0;
62
63 err = crypto_blkcipher_setkey(tfm, k, 16);
64 if (err) {
65 BT_ERR("cipher setkey failed: %d", err);
66 return err;
67 }
68
69 sg_init_one(&sg, r, 16);
70
71 iv_len = crypto_blkcipher_ivsize(tfm);
72 if (iv_len) {
73 memset(&iv, 0xff, iv_len);
74 crypto_blkcipher_set_iv(tfm, iv, iv_len);
75 }
76
77 err = crypto_blkcipher_encrypt(&desc, &sg, &sg, 16);
78 if (err)
79 BT_ERR("Encrypt data error %d", err);
80
81 return err;
82}
83
84static int smp_c1(struct crypto_blkcipher *tfm, u8 k[16], u8 r[16],
85 u8 preq[7], u8 pres[7], u8 _iat, bdaddr_t *ia,
86 u8 _rat, bdaddr_t *ra, u8 res[16])
87{
88 u8 p1[16], p2[16];
89 int err;
90
91 memset(p1, 0, 16);
92
93 /* p1 = pres || preq || _rat || _iat */
94 swap56(pres, p1);
95 swap56(preq, p1 + 7);
96 p1[14] = _rat;
97 p1[15] = _iat;
98
99 memset(p2, 0, 16);
100
101 /* p2 = padding || ia || ra */
102 baswap((bdaddr_t *) (p2 + 4), ia);
103 baswap((bdaddr_t *) (p2 + 10), ra);
104
105 /* res = r XOR p1 */
106 u128_xor((u128 *) res, (u128 *) r, (u128 *) p1);
107
108 /* res = e(k, res) */
109 err = smp_e(tfm, k, res);
110 if (err) {
111 BT_ERR("Encrypt data error");
112 return err;
113 }
114
115 /* res = res XOR p2 */
116 u128_xor((u128 *) res, (u128 *) res, (u128 *) p2);
117
118 /* res = e(k, res) */
119 err = smp_e(tfm, k, res);
120 if (err)
121 BT_ERR("Encrypt data error");
122
123 return err;
124}
125
126static int smp_s1(struct crypto_blkcipher *tfm, u8 k[16],
127 u8 r1[16], u8 r2[16], u8 _r[16])
128{
129 int err;
130
131 /* Just least significant octets from r1 and r2 are considered */
132 memcpy(_r, r1 + 8, 8);
133 memcpy(_r + 8, r2 + 8, 8);
134
135 err = smp_e(tfm, k, _r);
136 if (err)
137 BT_ERR("Encrypt data error");
138
139 return err;
140}
141
142static int smp_rand(u8 *buf)
143{
144 get_random_bytes(buf, 16);
145
146 return 0;
147}
Anderson Brigliaeb492e02011-06-09 18:50:40 -0300148
149static struct sk_buff *smp_build_cmd(struct l2cap_conn *conn, u8 code,
150 u16 dlen, void *data)
151{
152 struct sk_buff *skb;
153 struct l2cap_hdr *lh;
154 int len;
155
156 len = L2CAP_HDR_SIZE + sizeof(code) + dlen;
157
158 if (len > conn->mtu)
159 return NULL;
160
161 skb = bt_skb_alloc(len, GFP_ATOMIC);
162 if (!skb)
163 return NULL;
164
165 lh = (struct l2cap_hdr *) skb_put(skb, L2CAP_HDR_SIZE);
166 lh->len = cpu_to_le16(sizeof(code) + dlen);
167 lh->cid = cpu_to_le16(L2CAP_CID_SMP);
168
169 memcpy(skb_put(skb, sizeof(code)), &code, sizeof(code));
170
171 memcpy(skb_put(skb, dlen), data, dlen);
172
173 return skb;
174}
175
176static void smp_send_cmd(struct l2cap_conn *conn, u8 code, u16 len, void *data)
177{
178 struct sk_buff *skb = smp_build_cmd(conn, code, len, data);
179
180 BT_DBG("code 0x%2.2x", code);
181
182 if (!skb)
183 return;
184
Luiz Augusto von Dentz73d80de2011-11-02 15:52:01 +0200185 skb->priority = HCI_PRIO_MAX;
186 hci_send_acl(conn->hchan, skb, 0);
Vinicius Costa Gomese2dcd112011-08-19 21:06:50 -0300187
Gustavo F. Padovan6c9d42a2011-12-20 10:57:27 -0200188 cancel_delayed_work_sync(&conn->security_timer);
Marcel Holtmann17b02e62012-03-01 14:32:37 -0800189 schedule_delayed_work(&conn->security_timer, SMP_TIMEOUT);
Anderson Brigliaeb492e02011-06-09 18:50:40 -0300190}
191
Brian Gix2b64d152011-12-21 16:12:12 -0800192static __u8 authreq_to_seclevel(__u8 authreq)
193{
194 if (authreq & SMP_AUTH_MITM)
195 return BT_SECURITY_HIGH;
196 else
197 return BT_SECURITY_MEDIUM;
198}
199
200static __u8 seclevel_to_authreq(__u8 sec_level)
201{
202 switch (sec_level) {
203 case BT_SECURITY_HIGH:
204 return SMP_AUTH_MITM | SMP_AUTH_BONDING;
205 case BT_SECURITY_MEDIUM:
206 return SMP_AUTH_BONDING;
207 default:
208 return SMP_AUTH_NONE;
209 }
210}
211
Vinicius Costa Gomesb8e66ea2011-06-09 18:50:52 -0300212static void build_pairing_cmd(struct l2cap_conn *conn,
Vinicius Costa Gomes54790f72011-07-07 18:59:38 -0300213 struct smp_cmd_pairing *req,
214 struct smp_cmd_pairing *rsp,
215 __u8 authreq)
Vinicius Costa Gomesb8e66ea2011-06-09 18:50:52 -0300216{
Brian Gix2b64d152011-12-21 16:12:12 -0800217 u8 dist_keys = 0;
Vinicius Costa Gomes54790f72011-07-07 18:59:38 -0300218
Johan Hedberga8b2d5c2012-01-08 23:11:15 +0200219 if (test_bit(HCI_PAIRABLE, &conn->hcon->hdev->dev_flags)) {
Vinicius Costa Gomesca10b5e2011-08-25 20:02:37 -0300220 dist_keys = SMP_DIST_ENC_KEY;
Vinicius Costa Gomes54790f72011-07-07 18:59:38 -0300221 authreq |= SMP_AUTH_BONDING;
Brian Gix2b64d152011-12-21 16:12:12 -0800222 } else {
223 authreq &= ~SMP_AUTH_BONDING;
Vinicius Costa Gomes54790f72011-07-07 18:59:38 -0300224 }
225
226 if (rsp == NULL) {
227 req->io_capability = conn->hcon->io_capability;
228 req->oob_flag = SMP_OOB_NOT_PRESENT;
229 req->max_key_size = SMP_MAX_ENC_KEY_SIZE;
Brian Gix2b64d152011-12-21 16:12:12 -0800230 req->init_key_dist = 0;
Vinicius Costa Gomes54790f72011-07-07 18:59:38 -0300231 req->resp_key_dist = dist_keys;
232 req->auth_req = authreq;
233 return;
234 }
235
236 rsp->io_capability = conn->hcon->io_capability;
237 rsp->oob_flag = SMP_OOB_NOT_PRESENT;
238 rsp->max_key_size = SMP_MAX_ENC_KEY_SIZE;
Brian Gix2b64d152011-12-21 16:12:12 -0800239 rsp->init_key_dist = 0;
Vinicius Costa Gomes54790f72011-07-07 18:59:38 -0300240 rsp->resp_key_dist = req->resp_key_dist & dist_keys;
241 rsp->auth_req = authreq;
Vinicius Costa Gomesb8e66ea2011-06-09 18:50:52 -0300242}
243
Vinicius Costa Gomes3158c502011-06-14 13:37:42 -0300244static u8 check_enc_key_size(struct l2cap_conn *conn, __u8 max_key_size)
245{
Vinicius Costa Gomes1c1def02011-09-05 14:31:30 -0300246 struct smp_chan *smp = conn->smp_chan;
247
Vinicius Costa Gomes3158c502011-06-14 13:37:42 -0300248 if ((max_key_size > SMP_MAX_ENC_KEY_SIZE) ||
249 (max_key_size < SMP_MIN_ENC_KEY_SIZE))
250 return SMP_ENC_KEY_SIZE;
251
Vinicius Costa Gomesf7aa6112012-01-30 19:29:12 -0300252 smp->enc_key_size = max_key_size;
Vinicius Costa Gomes3158c502011-06-14 13:37:42 -0300253
254 return 0;
255}
256
Brian Gix4f957a72011-11-23 08:28:36 -0800257static void smp_failure(struct l2cap_conn *conn, u8 reason, u8 send)
258{
Johan Hedbergbab73cb2012-02-09 16:07:29 +0200259 struct hci_conn *hcon = conn->hcon;
260
Brian Gix4f957a72011-11-23 08:28:36 -0800261 if (send)
262 smp_send_cmd(conn, SMP_CMD_PAIRING_FAIL, sizeof(reason),
263 &reason);
264
Johan Hedberg51a8efd2012-01-16 06:10:31 +0200265 clear_bit(HCI_CONN_ENCRYPT_PEND, &conn->hcon->flags);
Johan Hedbergbab73cb2012-02-09 16:07:29 +0200266 mgmt_auth_failed(conn->hcon->hdev, conn->dst, hcon->type,
Gustavo F. Padovan04124682012-03-08 01:25:00 -0300267 hcon->dst_type, reason);
Vinicius Costa Gomesf1c09c02012-02-01 18:27:56 -0300268
269 if (test_and_clear_bit(HCI_CONN_LE_SMP_PEND, &conn->hcon->flags)) {
270 cancel_delayed_work_sync(&conn->security_timer);
271 smp_chan_destroy(conn);
272 }
Brian Gix4f957a72011-11-23 08:28:36 -0800273}
274
Brian Gix2b64d152011-12-21 16:12:12 -0800275#define JUST_WORKS 0x00
276#define JUST_CFM 0x01
277#define REQ_PASSKEY 0x02
278#define CFM_PASSKEY 0x03
279#define REQ_OOB 0x04
280#define OVERLAP 0xFF
281
282static const u8 gen_method[5][5] = {
283 { JUST_WORKS, JUST_CFM, REQ_PASSKEY, JUST_WORKS, REQ_PASSKEY },
284 { JUST_WORKS, JUST_CFM, REQ_PASSKEY, JUST_WORKS, REQ_PASSKEY },
285 { CFM_PASSKEY, CFM_PASSKEY, REQ_PASSKEY, JUST_WORKS, CFM_PASSKEY },
286 { JUST_WORKS, JUST_CFM, JUST_WORKS, JUST_WORKS, JUST_CFM },
287 { CFM_PASSKEY, CFM_PASSKEY, REQ_PASSKEY, JUST_WORKS, OVERLAP },
288};
289
290static int tk_request(struct l2cap_conn *conn, u8 remote_oob, u8 auth,
291 u8 local_io, u8 remote_io)
292{
293 struct hci_conn *hcon = conn->hcon;
294 struct smp_chan *smp = conn->smp_chan;
295 u8 method;
296 u32 passkey = 0;
297 int ret = 0;
298
299 /* Initialize key for JUST WORKS */
300 memset(smp->tk, 0, sizeof(smp->tk));
301 clear_bit(SMP_FLAG_TK_VALID, &smp->smp_flags);
302
303 BT_DBG("tk_request: auth:%d lcl:%d rem:%d", auth, local_io, remote_io);
304
305 /* If neither side wants MITM, use JUST WORKS */
306 /* If either side has unknown io_caps, use JUST WORKS */
307 /* Otherwise, look up method from the table */
308 if (!(auth & SMP_AUTH_MITM) ||
309 local_io > SMP_IO_KEYBOARD_DISPLAY ||
310 remote_io > SMP_IO_KEYBOARD_DISPLAY)
311 method = JUST_WORKS;
312 else
313 method = gen_method[local_io][remote_io];
314
315 /* If not bonding, don't ask user to confirm a Zero TK */
316 if (!(auth & SMP_AUTH_BONDING) && method == JUST_CFM)
317 method = JUST_WORKS;
318
319 /* If Just Works, Continue with Zero TK */
320 if (method == JUST_WORKS) {
321 set_bit(SMP_FLAG_TK_VALID, &smp->smp_flags);
322 return 0;
323 }
324
325 /* Not Just Works/Confirm results in MITM Authentication */
326 if (method != JUST_CFM)
327 set_bit(SMP_FLAG_MITM_AUTH, &smp->smp_flags);
328
329 /* If both devices have Keyoard-Display I/O, the master
330 * Confirms and the slave Enters the passkey.
331 */
332 if (method == OVERLAP) {
333 if (hcon->link_mode & HCI_LM_MASTER)
334 method = CFM_PASSKEY;
335 else
336 method = REQ_PASSKEY;
337 }
338
339 /* Generate random passkey. Not valid until confirmed. */
340 if (method == CFM_PASSKEY) {
341 u8 key[16];
342
343 memset(key, 0, sizeof(key));
344 get_random_bytes(&passkey, sizeof(passkey));
345 passkey %= 1000000;
346 put_unaligned_le32(passkey, key);
347 swap128(key, smp->tk);
348 BT_DBG("PassKey: %d", passkey);
349 }
350
351 hci_dev_lock(hcon->hdev);
352
353 if (method == REQ_PASSKEY)
Johan Hedberg272d90d2012-02-09 15:26:12 +0200354 ret = mgmt_user_passkey_request(hcon->hdev, conn->dst,
355 hcon->type, hcon->dst_type);
Brian Gix2b64d152011-12-21 16:12:12 -0800356 else
357 ret = mgmt_user_confirm_request(hcon->hdev, conn->dst,
Johan Hedberg272d90d2012-02-09 15:26:12 +0200358 hcon->type, hcon->dst_type,
Brian Gix2b64d152011-12-21 16:12:12 -0800359 cpu_to_le32(passkey), 0);
360
361 hci_dev_unlock(hcon->hdev);
362
363 return ret;
364}
365
Vinicius Costa Gomes8aab4752011-09-05 14:31:31 -0300366static void confirm_work(struct work_struct *work)
367{
368 struct smp_chan *smp = container_of(work, struct smp_chan, confirm);
369 struct l2cap_conn *conn = smp->conn;
370 struct crypto_blkcipher *tfm;
371 struct smp_cmd_pairing_confirm cp;
372 int ret;
373 u8 res[16], reason;
374
375 BT_DBG("conn %p", conn);
376
377 tfm = crypto_alloc_blkcipher("ecb(aes)", 0, CRYPTO_ALG_ASYNC);
378 if (IS_ERR(tfm)) {
379 reason = SMP_UNSPECIFIED;
380 goto error;
381 }
382
383 smp->tfm = tfm;
384
385 if (conn->hcon->out)
386 ret = smp_c1(tfm, smp->tk, smp->prnd, smp->preq, smp->prsp, 0,
Gustavo F. Padovan04124682012-03-08 01:25:00 -0300387 conn->src, conn->hcon->dst_type, conn->dst, res);
Vinicius Costa Gomes8aab4752011-09-05 14:31:31 -0300388 else
389 ret = smp_c1(tfm, smp->tk, smp->prnd, smp->preq, smp->prsp,
Gustavo F. Padovan04124682012-03-08 01:25:00 -0300390 conn->hcon->dst_type, conn->dst, 0, conn->src,
391 res);
Vinicius Costa Gomes8aab4752011-09-05 14:31:31 -0300392 if (ret) {
393 reason = SMP_UNSPECIFIED;
394 goto error;
395 }
396
Brian Gix2b64d152011-12-21 16:12:12 -0800397 clear_bit(SMP_FLAG_CFM_PENDING, &smp->smp_flags);
398
Vinicius Costa Gomes8aab4752011-09-05 14:31:31 -0300399 swap128(res, cp.confirm_val);
400 smp_send_cmd(smp->conn, SMP_CMD_PAIRING_CONFIRM, sizeof(cp), &cp);
401
402 return;
403
404error:
Brian Gix4f957a72011-11-23 08:28:36 -0800405 smp_failure(conn, reason, 1);
Vinicius Costa Gomes8aab4752011-09-05 14:31:31 -0300406}
407
408static void random_work(struct work_struct *work)
409{
410 struct smp_chan *smp = container_of(work, struct smp_chan, random);
411 struct l2cap_conn *conn = smp->conn;
412 struct hci_conn *hcon = conn->hcon;
413 struct crypto_blkcipher *tfm = smp->tfm;
414 u8 reason, confirm[16], res[16], key[16];
415 int ret;
416
417 if (IS_ERR_OR_NULL(tfm)) {
418 reason = SMP_UNSPECIFIED;
419 goto error;
420 }
421
422 BT_DBG("conn %p %s", conn, conn->hcon->out ? "master" : "slave");
423
424 if (hcon->out)
425 ret = smp_c1(tfm, smp->tk, smp->rrnd, smp->preq, smp->prsp, 0,
Gustavo F. Padovan04124682012-03-08 01:25:00 -0300426 conn->src, hcon->dst_type, conn->dst, res);
Vinicius Costa Gomes8aab4752011-09-05 14:31:31 -0300427 else
428 ret = smp_c1(tfm, smp->tk, smp->rrnd, smp->preq, smp->prsp,
Gustavo F. Padovan04124682012-03-08 01:25:00 -0300429 hcon->dst_type, conn->dst, 0, conn->src, res);
Vinicius Costa Gomes8aab4752011-09-05 14:31:31 -0300430 if (ret) {
431 reason = SMP_UNSPECIFIED;
432 goto error;
433 }
434
435 swap128(res, confirm);
436
437 if (memcmp(smp->pcnf, confirm, sizeof(smp->pcnf)) != 0) {
438 BT_ERR("Pairing failed (confirmation values mismatch)");
439 reason = SMP_CONFIRM_FAILED;
440 goto error;
441 }
442
443 if (hcon->out) {
444 u8 stk[16], rand[8];
445 __le16 ediv;
446
447 memset(rand, 0, sizeof(rand));
448 ediv = 0;
449
450 smp_s1(tfm, smp->tk, smp->rrnd, smp->prnd, key);
451 swap128(key, stk);
452
Vinicius Costa Gomesf7aa6112012-01-30 19:29:12 -0300453 memset(stk + smp->enc_key_size, 0,
Gustavo F. Padovan04124682012-03-08 01:25:00 -0300454 SMP_MAX_ENC_KEY_SIZE - smp->enc_key_size);
Vinicius Costa Gomes8aab4752011-09-05 14:31:31 -0300455
Johan Hedberg51a8efd2012-01-16 06:10:31 +0200456 if (test_and_set_bit(HCI_CONN_ENCRYPT_PEND, &hcon->flags)) {
Vinicius Costa Gomes8aab4752011-09-05 14:31:31 -0300457 reason = SMP_UNSPECIFIED;
458 goto error;
459 }
460
461 hci_le_start_enc(hcon, ediv, rand, stk);
Vinicius Costa Gomesf7aa6112012-01-30 19:29:12 -0300462 hcon->enc_key_size = smp->enc_key_size;
Vinicius Costa Gomes8aab4752011-09-05 14:31:31 -0300463 } else {
464 u8 stk[16], r[16], rand[8];
465 __le16 ediv;
466
467 memset(rand, 0, sizeof(rand));
468 ediv = 0;
469
470 swap128(smp->prnd, r);
471 smp_send_cmd(conn, SMP_CMD_PAIRING_RANDOM, sizeof(r), r);
472
473 smp_s1(tfm, smp->tk, smp->prnd, smp->rrnd, key);
474 swap128(key, stk);
475
Vinicius Costa Gomesf7aa6112012-01-30 19:29:12 -0300476 memset(stk + smp->enc_key_size, 0,
477 SMP_MAX_ENC_KEY_SIZE - smp->enc_key_size);
Vinicius Costa Gomes8aab4752011-09-05 14:31:31 -0300478
Vinicius Costa Gomesc9839a12012-02-02 21:08:01 -0300479 hci_add_ltk(hcon->hdev, conn->dst, hcon->dst_type,
Gustavo F. Padovan04124682012-03-08 01:25:00 -0300480 HCI_SMP_STK_SLAVE, 0, 0, stk, smp->enc_key_size,
481 ediv, rand);
Vinicius Costa Gomes8aab4752011-09-05 14:31:31 -0300482 }
483
484 return;
485
486error:
Brian Gix4f957a72011-11-23 08:28:36 -0800487 smp_failure(conn, reason, 1);
Vinicius Costa Gomes8aab4752011-09-05 14:31:31 -0300488}
489
490static struct smp_chan *smp_chan_create(struct l2cap_conn *conn)
491{
492 struct smp_chan *smp;
493
494 smp = kzalloc(sizeof(struct smp_chan), GFP_ATOMIC);
495 if (!smp)
496 return NULL;
497
498 INIT_WORK(&smp->confirm, confirm_work);
499 INIT_WORK(&smp->random, random_work);
500
501 smp->conn = conn;
502 conn->smp_chan = smp;
Brian Gix2b64d152011-12-21 16:12:12 -0800503 conn->hcon->smp_conn = conn;
Vinicius Costa Gomes8aab4752011-09-05 14:31:31 -0300504
505 hci_conn_hold(conn->hcon);
506
507 return smp;
508}
509
510void smp_chan_destroy(struct l2cap_conn *conn)
511{
Brian Gixc8eb9692011-11-23 08:28:35 -0800512 struct smp_chan *smp = conn->smp_chan;
513
Vinicius Costa Gomesf1c09c02012-02-01 18:27:56 -0300514 BUG_ON(!smp);
Brian Gixc8eb9692011-11-23 08:28:35 -0800515
516 if (smp->tfm)
517 crypto_free_blkcipher(smp->tfm);
518
519 kfree(smp);
520 conn->smp_chan = NULL;
Brian Gix2b64d152011-12-21 16:12:12 -0800521 conn->hcon->smp_conn = NULL;
Vinicius Costa Gomes8aab4752011-09-05 14:31:31 -0300522 hci_conn_put(conn->hcon);
523}
524
Brian Gix2b64d152011-12-21 16:12:12 -0800525int smp_user_confirm_reply(struct hci_conn *hcon, u16 mgmt_op, __le32 passkey)
526{
527 struct l2cap_conn *conn = hcon->smp_conn;
528 struct smp_chan *smp;
529 u32 value;
530 u8 key[16];
531
532 BT_DBG("");
533
534 if (!conn)
535 return -ENOTCONN;
536
537 smp = conn->smp_chan;
538
539 switch (mgmt_op) {
540 case MGMT_OP_USER_PASSKEY_REPLY:
541 value = le32_to_cpu(passkey);
542 memset(key, 0, sizeof(key));
543 BT_DBG("PassKey: %d", value);
544 put_unaligned_le32(value, key);
545 swap128(key, smp->tk);
546 /* Fall Through */
547 case MGMT_OP_USER_CONFIRM_REPLY:
548 set_bit(SMP_FLAG_TK_VALID, &smp->smp_flags);
549 break;
550 case MGMT_OP_USER_PASSKEY_NEG_REPLY:
551 case MGMT_OP_USER_CONFIRM_NEG_REPLY:
552 smp_failure(conn, SMP_PASSKEY_ENTRY_FAILED, 1);
553 return 0;
554 default:
555 smp_failure(conn, SMP_PASSKEY_ENTRY_FAILED, 1);
556 return -EOPNOTSUPP;
557 }
558
559 /* If it is our turn to send Pairing Confirm, do so now */
560 if (test_bit(SMP_FLAG_CFM_PENDING, &smp->smp_flags))
561 queue_work(hcon->hdev->workqueue, &smp->confirm);
562
563 return 0;
564}
565
Vinicius Costa Gomesda85e5e2011-06-09 18:50:53 -0300566static u8 smp_cmd_pairing_req(struct l2cap_conn *conn, struct sk_buff *skb)
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300567{
Vinicius Costa Gomes3158c502011-06-14 13:37:42 -0300568 struct smp_cmd_pairing rsp, *req = (void *) skb->data;
Vinicius Costa Gomes8aab4752011-09-05 14:31:31 -0300569 struct smp_chan *smp;
Vinicius Costa Gomes3158c502011-06-14 13:37:42 -0300570 u8 key_size;
Brian Gix2b64d152011-12-21 16:12:12 -0800571 u8 auth = SMP_AUTH_NONE;
Vinicius Costa Gomes8aab4752011-09-05 14:31:31 -0300572 int ret;
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300573
574 BT_DBG("conn %p", conn);
575
Brian Gix2b64d152011-12-21 16:12:12 -0800576 if (conn->hcon->link_mode & HCI_LM_MASTER)
577 return SMP_CMD_NOTSUPP;
578
Johan Hedberg51a8efd2012-01-16 06:10:31 +0200579 if (!test_and_set_bit(HCI_CONN_LE_SMP_PEND, &conn->hcon->flags))
Vinicius Costa Gomes8aab4752011-09-05 14:31:31 -0300580 smp = smp_chan_create(conn);
581
582 smp = conn->smp_chan;
Vinicius Costa Gomesd26a2342011-08-19 21:06:51 -0300583
Vinicius Costa Gomes1c1def02011-09-05 14:31:30 -0300584 smp->preq[0] = SMP_CMD_PAIRING_REQ;
585 memcpy(&smp->preq[1], req, sizeof(*req));
Vinicius Costa Gomes3158c502011-06-14 13:37:42 -0300586 skb_pull(skb, sizeof(*req));
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300587
Brian Gix2b64d152011-12-21 16:12:12 -0800588 /* We didn't start the pairing, so match remote */
589 if (req->auth_req & SMP_AUTH_BONDING)
590 auth = req->auth_req;
Vinicius Costa Gomesda85e5e2011-06-09 18:50:53 -0300591
Brian Gix2b64d152011-12-21 16:12:12 -0800592 build_pairing_cmd(conn, req, &rsp, auth);
Vinicius Costa Gomes3158c502011-06-14 13:37:42 -0300593
594 key_size = min(req->max_key_size, rsp.max_key_size);
595 if (check_enc_key_size(conn, key_size))
596 return SMP_ENC_KEY_SIZE;
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300597
Vinicius Costa Gomes8aab4752011-09-05 14:31:31 -0300598 ret = smp_rand(smp->prnd);
599 if (ret)
600 return SMP_UNSPECIFIED;
601
Vinicius Costa Gomes1c1def02011-09-05 14:31:30 -0300602 smp->prsp[0] = SMP_CMD_PAIRING_RSP;
603 memcpy(&smp->prsp[1], &rsp, sizeof(rsp));
Anderson Brigliaf01ead32011-06-09 18:50:45 -0300604
Vinicius Costa Gomes3158c502011-06-14 13:37:42 -0300605 smp_send_cmd(conn, SMP_CMD_PAIRING_RSP, sizeof(rsp), &rsp);
Vinicius Costa Gomesda85e5e2011-06-09 18:50:53 -0300606
Brian Gix2b64d152011-12-21 16:12:12 -0800607 /* Request setup of TK */
608 ret = tk_request(conn, 0, auth, rsp.io_capability, req->io_capability);
609 if (ret)
610 return SMP_UNSPECIFIED;
611
Vinicius Costa Gomesda85e5e2011-06-09 18:50:53 -0300612 return 0;
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300613}
614
Vinicius Costa Gomesda85e5e2011-06-09 18:50:53 -0300615static u8 smp_cmd_pairing_rsp(struct l2cap_conn *conn, struct sk_buff *skb)
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300616{
Vinicius Costa Gomes3158c502011-06-14 13:37:42 -0300617 struct smp_cmd_pairing *req, *rsp = (void *) skb->data;
Vinicius Costa Gomes1c1def02011-09-05 14:31:30 -0300618 struct smp_chan *smp = conn->smp_chan;
Vinicius Costa Gomes8aab4752011-09-05 14:31:31 -0300619 struct hci_dev *hdev = conn->hcon->hdev;
Brian Gix2b64d152011-12-21 16:12:12 -0800620 u8 key_size, auth = SMP_AUTH_NONE;
Anderson Briglia7d24ddc2011-06-09 18:50:46 -0300621 int ret;
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300622
623 BT_DBG("conn %p", conn);
624
Brian Gix2b64d152011-12-21 16:12:12 -0800625 if (!(conn->hcon->link_mode & HCI_LM_MASTER))
626 return SMP_CMD_NOTSUPP;
627
Vinicius Costa Gomes3158c502011-06-14 13:37:42 -0300628 skb_pull(skb, sizeof(*rsp));
Vinicius Costa Gomesda85e5e2011-06-09 18:50:53 -0300629
Vinicius Costa Gomes1c1def02011-09-05 14:31:30 -0300630 req = (void *) &smp->preq[1];
Vinicius Costa Gomes3158c502011-06-14 13:37:42 -0300631
632 key_size = min(req->max_key_size, rsp->max_key_size);
633 if (check_enc_key_size(conn, key_size))
634 return SMP_ENC_KEY_SIZE;
635
Vinicius Costa Gomes1c1def02011-09-05 14:31:30 -0300636 ret = smp_rand(smp->prnd);
Anderson Briglia7d24ddc2011-06-09 18:50:46 -0300637 if (ret)
Vinicius Costa Gomesda85e5e2011-06-09 18:50:53 -0300638 return SMP_UNSPECIFIED;
Anderson Briglia7d24ddc2011-06-09 18:50:46 -0300639
Vinicius Costa Gomes8aab4752011-09-05 14:31:31 -0300640 smp->prsp[0] = SMP_CMD_PAIRING_RSP;
641 memcpy(&smp->prsp[1], rsp, sizeof(*rsp));
Anderson Briglia7d24ddc2011-06-09 18:50:46 -0300642
Brian Gix2b64d152011-12-21 16:12:12 -0800643 if ((req->auth_req & SMP_AUTH_BONDING) &&
644 (rsp->auth_req & SMP_AUTH_BONDING))
645 auth = SMP_AUTH_BONDING;
646
647 auth |= (req->auth_req | rsp->auth_req) & SMP_AUTH_MITM;
648
649 ret = tk_request(conn, 0, auth, rsp->io_capability, req->io_capability);
650 if (ret)
651 return SMP_UNSPECIFIED;
652
653 set_bit(SMP_FLAG_CFM_PENDING, &smp->smp_flags);
654
655 /* Can't compose response until we have been confirmed */
656 if (!test_bit(SMP_FLAG_TK_VALID, &smp->smp_flags))
657 return 0;
658
Vinicius Costa Gomes8aab4752011-09-05 14:31:31 -0300659 queue_work(hdev->workqueue, &smp->confirm);
Vinicius Costa Gomesda85e5e2011-06-09 18:50:53 -0300660
661 return 0;
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300662}
663
Vinicius Costa Gomesda85e5e2011-06-09 18:50:53 -0300664static u8 smp_cmd_pairing_confirm(struct l2cap_conn *conn, struct sk_buff *skb)
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300665{
Vinicius Costa Gomes1c1def02011-09-05 14:31:30 -0300666 struct smp_chan *smp = conn->smp_chan;
Vinicius Costa Gomes8aab4752011-09-05 14:31:31 -0300667 struct hci_dev *hdev = conn->hcon->hdev;
Anderson Briglia7d24ddc2011-06-09 18:50:46 -0300668
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300669 BT_DBG("conn %p %s", conn, conn->hcon->out ? "master" : "slave");
670
Vinicius Costa Gomes1c1def02011-09-05 14:31:30 -0300671 memcpy(smp->pcnf, skb->data, sizeof(smp->pcnf));
672 skb_pull(skb, sizeof(smp->pcnf));
Anderson Briglia7d24ddc2011-06-09 18:50:46 -0300673
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300674 if (conn->hcon->out) {
Anderson Briglia7d24ddc2011-06-09 18:50:46 -0300675 u8 random[16];
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300676
Vinicius Costa Gomes1c1def02011-09-05 14:31:30 -0300677 swap128(smp->prnd, random);
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300678 smp_send_cmd(conn, SMP_CMD_PAIRING_RANDOM, sizeof(random),
Anderson Briglia7d24ddc2011-06-09 18:50:46 -0300679 random);
Brian Gix2b64d152011-12-21 16:12:12 -0800680 } else if (test_bit(SMP_FLAG_TK_VALID, &smp->smp_flags)) {
Vinicius Costa Gomes8aab4752011-09-05 14:31:31 -0300681 queue_work(hdev->workqueue, &smp->confirm);
Brian Gix2b64d152011-12-21 16:12:12 -0800682 } else {
683 set_bit(SMP_FLAG_CFM_PENDING, &smp->smp_flags);
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300684 }
Vinicius Costa Gomesda85e5e2011-06-09 18:50:53 -0300685
686 return 0;
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300687}
688
Vinicius Costa Gomesda85e5e2011-06-09 18:50:53 -0300689static u8 smp_cmd_pairing_random(struct l2cap_conn *conn, struct sk_buff *skb)
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300690{
Vinicius Costa Gomes1c1def02011-09-05 14:31:30 -0300691 struct smp_chan *smp = conn->smp_chan;
Vinicius Costa Gomes8aab4752011-09-05 14:31:31 -0300692 struct hci_dev *hdev = conn->hcon->hdev;
Anderson Briglia7d24ddc2011-06-09 18:50:46 -0300693
Vinicius Costa Gomes8aab4752011-09-05 14:31:31 -0300694 BT_DBG("conn %p", conn);
Anderson Briglia7d24ddc2011-06-09 18:50:46 -0300695
Vinicius Costa Gomes8aab4752011-09-05 14:31:31 -0300696 swap128(skb->data, smp->rrnd);
697 skb_pull(skb, sizeof(smp->rrnd));
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300698
Vinicius Costa Gomes8aab4752011-09-05 14:31:31 -0300699 queue_work(hdev->workqueue, &smp->random);
Vinicius Costa Gomesda85e5e2011-06-09 18:50:53 -0300700
701 return 0;
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300702}
703
Vinicius Costa Gomes988c5992011-08-25 20:02:28 -0300704static u8 smp_ltk_encrypt(struct l2cap_conn *conn)
705{
Vinicius Costa Gomesc9839a12012-02-02 21:08:01 -0300706 struct smp_ltk *key;
Vinicius Costa Gomes988c5992011-08-25 20:02:28 -0300707 struct hci_conn *hcon = conn->hcon;
708
Vinicius Costa Gomesc9839a12012-02-02 21:08:01 -0300709 key = hci_find_ltk_by_addr(hcon->hdev, conn->dst, hcon->dst_type);
Vinicius Costa Gomes988c5992011-08-25 20:02:28 -0300710 if (!key)
711 return 0;
712
Johan Hedberg51a8efd2012-01-16 06:10:31 +0200713 if (test_and_set_bit(HCI_CONN_ENCRYPT_PEND, &hcon->flags))
Vinicius Costa Gomes988c5992011-08-25 20:02:28 -0300714 return 1;
715
Vinicius Costa Gomesc9839a12012-02-02 21:08:01 -0300716 hci_le_start_enc(hcon, key->ediv, key->rand, key->val);
717 hcon->enc_key_size = key->enc_size;
Vinicius Costa Gomes988c5992011-08-25 20:02:28 -0300718
719 return 1;
720
721}
Vinicius Costa Gomesda85e5e2011-06-09 18:50:53 -0300722static u8 smp_cmd_security_req(struct l2cap_conn *conn, struct sk_buff *skb)
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300723{
724 struct smp_cmd_security_req *rp = (void *) skb->data;
725 struct smp_cmd_pairing cp;
Vinicius Costa Gomesf1cb9af2011-01-26 21:42:57 -0300726 struct hci_conn *hcon = conn->hcon;
Vinicius Costa Gomes8aab4752011-09-05 14:31:31 -0300727 struct smp_chan *smp;
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300728
729 BT_DBG("conn %p", conn);
730
Brian Gix2b64d152011-12-21 16:12:12 -0800731 hcon->pending_sec_level = authreq_to_seclevel(rp->auth_req);
Vinicius Costa Gomesfeb45eb2011-08-25 20:02:35 -0300732
Vinicius Costa Gomes988c5992011-08-25 20:02:28 -0300733 if (smp_ltk_encrypt(conn))
734 return 0;
735
Johan Hedberg51a8efd2012-01-16 06:10:31 +0200736 if (test_and_set_bit(HCI_CONN_LE_SMP_PEND, &hcon->flags))
Vinicius Costa Gomesda85e5e2011-06-09 18:50:53 -0300737 return 0;
Vinicius Costa Gomesf1cb9af2011-01-26 21:42:57 -0300738
Vinicius Costa Gomes8aab4752011-09-05 14:31:31 -0300739 smp = smp_chan_create(conn);
Vinicius Costa Gomesd26a2342011-08-19 21:06:51 -0300740
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300741 skb_pull(skb, sizeof(*rp));
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300742
Vinicius Costa Gomesda85e5e2011-06-09 18:50:53 -0300743 memset(&cp, 0, sizeof(cp));
Vinicius Costa Gomes54790f72011-07-07 18:59:38 -0300744 build_pairing_cmd(conn, &cp, NULL, rp->auth_req);
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300745
Vinicius Costa Gomes1c1def02011-09-05 14:31:30 -0300746 smp->preq[0] = SMP_CMD_PAIRING_REQ;
747 memcpy(&smp->preq[1], &cp, sizeof(cp));
Anderson Brigliaf01ead32011-06-09 18:50:45 -0300748
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300749 smp_send_cmd(conn, SMP_CMD_PAIRING_REQ, sizeof(cp), &cp);
Vinicius Costa Gomesf1cb9af2011-01-26 21:42:57 -0300750
Vinicius Costa Gomesda85e5e2011-06-09 18:50:53 -0300751 return 0;
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300752}
753
Anderson Brigliaeb492e02011-06-09 18:50:40 -0300754int smp_conn_security(struct l2cap_conn *conn, __u8 sec_level)
755{
Vinicius Costa Gomes3a0259b2011-06-09 18:50:43 -0300756 struct hci_conn *hcon = conn->hcon;
Vinicius Costa Gomes1c1def02011-09-05 14:31:30 -0300757 struct smp_chan *smp = conn->smp_chan;
Brian Gix2b64d152011-12-21 16:12:12 -0800758 __u8 authreq;
Anderson Brigliaeb492e02011-06-09 18:50:40 -0300759
Vinicius Costa Gomes3a0259b2011-06-09 18:50:43 -0300760 BT_DBG("conn %p hcon %p level 0x%2.2x", conn, hcon, sec_level);
761
Andre Guedes2e65c9d2011-06-30 19:20:56 -0300762 if (!lmp_host_le_capable(hcon->hdev))
763 return 1;
764
Vinicius Costa Gomesf1cb9af2011-01-26 21:42:57 -0300765 if (sec_level == BT_SECURITY_LOW)
Anderson Brigliaeb492e02011-06-09 18:50:40 -0300766 return 1;
Vinicius Costa Gomesf1cb9af2011-01-26 21:42:57 -0300767
768 if (hcon->sec_level >= sec_level)
769 return 1;
770
Vinicius Costa Gomes988c5992011-08-25 20:02:28 -0300771 if (hcon->link_mode & HCI_LM_MASTER)
772 if (smp_ltk_encrypt(conn))
Vinicius Costa Gomes02bc7452011-07-07 18:59:41 -0300773 goto done;
Vinicius Costa Gomesd26a2342011-08-19 21:06:51 -0300774
Johan Hedberg51a8efd2012-01-16 06:10:31 +0200775 if (test_and_set_bit(HCI_CONN_LE_SMP_PEND, &hcon->flags))
Vinicius Costa Gomesd26a2342011-08-19 21:06:51 -0300776 return 0;
777
Vinicius Costa Gomes8aab4752011-09-05 14:31:31 -0300778 smp = smp_chan_create(conn);
Brian Gix2b64d152011-12-21 16:12:12 -0800779 if (!smp)
780 return 1;
781
782 authreq = seclevel_to_authreq(sec_level);
Vinicius Costa Gomesd26a2342011-08-19 21:06:51 -0300783
Vinicius Costa Gomesd26a2342011-08-19 21:06:51 -0300784 if (hcon->link_mode & HCI_LM_MASTER) {
785 struct smp_cmd_pairing cp;
Anderson Brigliaf01ead32011-06-09 18:50:45 -0300786
Brian Gix2b64d152011-12-21 16:12:12 -0800787 build_pairing_cmd(conn, &cp, NULL, authreq);
Vinicius Costa Gomes1c1def02011-09-05 14:31:30 -0300788 smp->preq[0] = SMP_CMD_PAIRING_REQ;
789 memcpy(&smp->preq[1], &cp, sizeof(cp));
Anderson Brigliaf01ead32011-06-09 18:50:45 -0300790
Anderson Brigliaeb492e02011-06-09 18:50:40 -0300791 smp_send_cmd(conn, SMP_CMD_PAIRING_REQ, sizeof(cp), &cp);
792 } else {
793 struct smp_cmd_security_req cp;
Brian Gix2b64d152011-12-21 16:12:12 -0800794 cp.auth_req = authreq;
Anderson Brigliaeb492e02011-06-09 18:50:40 -0300795 smp_send_cmd(conn, SMP_CMD_SECURITY_REQ, sizeof(cp), &cp);
796 }
797
Vinicius Costa Gomes02bc7452011-07-07 18:59:41 -0300798done:
Vinicius Costa Gomesf1cb9af2011-01-26 21:42:57 -0300799 hcon->pending_sec_level = sec_level;
Vinicius Costa Gomesf1cb9af2011-01-26 21:42:57 -0300800
Anderson Brigliaeb492e02011-06-09 18:50:40 -0300801 return 0;
802}
803
Vinicius Costa Gomes7034b912011-07-07 18:59:34 -0300804static int smp_cmd_encrypt_info(struct l2cap_conn *conn, struct sk_buff *skb)
805{
Vinicius Costa Gomes16b90832011-07-07 18:59:39 -0300806 struct smp_cmd_encrypt_info *rp = (void *) skb->data;
Vinicius Costa Gomes1c1def02011-09-05 14:31:30 -0300807 struct smp_chan *smp = conn->smp_chan;
Vinicius Costa Gomes16b90832011-07-07 18:59:39 -0300808
809 skb_pull(skb, sizeof(*rp));
810
Vinicius Costa Gomes1c1def02011-09-05 14:31:30 -0300811 memcpy(smp->tk, rp->ltk, sizeof(smp->tk));
Vinicius Costa Gomes16b90832011-07-07 18:59:39 -0300812
Vinicius Costa Gomes7034b912011-07-07 18:59:34 -0300813 return 0;
814}
815
816static int smp_cmd_master_ident(struct l2cap_conn *conn, struct sk_buff *skb)
817{
Vinicius Costa Gomes16b90832011-07-07 18:59:39 -0300818 struct smp_cmd_master_ident *rp = (void *) skb->data;
Vinicius Costa Gomes1c1def02011-09-05 14:31:30 -0300819 struct smp_chan *smp = conn->smp_chan;
Vinicius Costa Gomesc9839a12012-02-02 21:08:01 -0300820 struct hci_dev *hdev = conn->hcon->hdev;
821 struct hci_conn *hcon = conn->hcon;
822 u8 authenticated;
Vinicius Costa Gomes7034b912011-07-07 18:59:34 -0300823
Vinicius Costa Gomes16b90832011-07-07 18:59:39 -0300824 skb_pull(skb, sizeof(*rp));
825
Vinicius Costa Gomesc9839a12012-02-02 21:08:01 -0300826 hci_dev_lock(hdev);
827 authenticated = (conn->hcon->sec_level == BT_SECURITY_HIGH);
828 hci_add_ltk(conn->hcon->hdev, conn->dst, hcon->dst_type,
Gustavo F. Padovan04124682012-03-08 01:25:00 -0300829 HCI_SMP_LTK, 1, authenticated, smp->tk, smp->enc_key_size,
830 rp->ediv, rp->rand);
Vinicius Costa Gomes7034b912011-07-07 18:59:34 -0300831 smp_distribute_keys(conn, 1);
Vinicius Costa Gomesc9839a12012-02-02 21:08:01 -0300832 hci_dev_unlock(hdev);
Vinicius Costa Gomes7034b912011-07-07 18:59:34 -0300833
834 return 0;
835}
836
Anderson Brigliaeb492e02011-06-09 18:50:40 -0300837int smp_sig_channel(struct l2cap_conn *conn, struct sk_buff *skb)
838{
839 __u8 code = skb->data[0];
840 __u8 reason;
841 int err = 0;
842
Andre Guedes2e65c9d2011-06-30 19:20:56 -0300843 if (!lmp_host_le_capable(conn->hcon->hdev)) {
844 err = -ENOTSUPP;
845 reason = SMP_PAIRING_NOTSUPP;
846 goto done;
847 }
848
Anderson Brigliaeb492e02011-06-09 18:50:40 -0300849 skb_pull(skb, sizeof(code));
850
851 switch (code) {
852 case SMP_CMD_PAIRING_REQ:
Vinicius Costa Gomesda85e5e2011-06-09 18:50:53 -0300853 reason = smp_cmd_pairing_req(conn, skb);
Anderson Brigliaeb492e02011-06-09 18:50:40 -0300854 break;
855
856 case SMP_CMD_PAIRING_FAIL:
Brian Gix4f957a72011-11-23 08:28:36 -0800857 smp_failure(conn, skb->data[0], 0);
Vinicius Costa Gomesda85e5e2011-06-09 18:50:53 -0300858 reason = 0;
859 err = -EPERM;
Anderson Brigliaeb492e02011-06-09 18:50:40 -0300860 break;
861
862 case SMP_CMD_PAIRING_RSP:
Vinicius Costa Gomesda85e5e2011-06-09 18:50:53 -0300863 reason = smp_cmd_pairing_rsp(conn, skb);
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300864 break;
865
866 case SMP_CMD_SECURITY_REQ:
Vinicius Costa Gomesda85e5e2011-06-09 18:50:53 -0300867 reason = smp_cmd_security_req(conn, skb);
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300868 break;
869
Anderson Brigliaeb492e02011-06-09 18:50:40 -0300870 case SMP_CMD_PAIRING_CONFIRM:
Vinicius Costa Gomesda85e5e2011-06-09 18:50:53 -0300871 reason = smp_cmd_pairing_confirm(conn, skb);
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300872 break;
873
Anderson Brigliaeb492e02011-06-09 18:50:40 -0300874 case SMP_CMD_PAIRING_RANDOM:
Vinicius Costa Gomesda85e5e2011-06-09 18:50:53 -0300875 reason = smp_cmd_pairing_random(conn, skb);
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300876 break;
877
Anderson Brigliaeb492e02011-06-09 18:50:40 -0300878 case SMP_CMD_ENCRYPT_INFO:
Vinicius Costa Gomes7034b912011-07-07 18:59:34 -0300879 reason = smp_cmd_encrypt_info(conn, skb);
880 break;
881
Anderson Brigliaeb492e02011-06-09 18:50:40 -0300882 case SMP_CMD_MASTER_IDENT:
Vinicius Costa Gomes7034b912011-07-07 18:59:34 -0300883 reason = smp_cmd_master_ident(conn, skb);
884 break;
885
Anderson Brigliaeb492e02011-06-09 18:50:40 -0300886 case SMP_CMD_IDENT_INFO:
887 case SMP_CMD_IDENT_ADDR_INFO:
888 case SMP_CMD_SIGN_INFO:
Vinicius Costa Gomes7034b912011-07-07 18:59:34 -0300889 /* Just ignored */
890 reason = 0;
891 break;
892
Anderson Brigliaeb492e02011-06-09 18:50:40 -0300893 default:
894 BT_DBG("Unknown command code 0x%2.2x", code);
895
896 reason = SMP_CMD_NOTSUPP;
Vinicius Costa Gomes3a0259b2011-06-09 18:50:43 -0300897 err = -EOPNOTSUPP;
898 goto done;
899 }
900
901done:
902 if (reason)
Brian Gix4f957a72011-11-23 08:28:36 -0800903 smp_failure(conn, reason, 1);
Anderson Brigliaeb492e02011-06-09 18:50:40 -0300904
905 kfree_skb(skb);
906 return err;
907}
Vinicius Costa Gomes7034b912011-07-07 18:59:34 -0300908
909int smp_distribute_keys(struct l2cap_conn *conn, __u8 force)
910{
911 struct smp_cmd_pairing *req, *rsp;
Vinicius Costa Gomes1c1def02011-09-05 14:31:30 -0300912 struct smp_chan *smp = conn->smp_chan;
Vinicius Costa Gomes7034b912011-07-07 18:59:34 -0300913 __u8 *keydist;
914
915 BT_DBG("conn %p force %d", conn, force);
916
Johan Hedberg51a8efd2012-01-16 06:10:31 +0200917 if (!test_bit(HCI_CONN_LE_SMP_PEND, &conn->hcon->flags))
Vinicius Costa Gomesd26a2342011-08-19 21:06:51 -0300918 return 0;
919
Vinicius Costa Gomes1c1def02011-09-05 14:31:30 -0300920 rsp = (void *) &smp->prsp[1];
Vinicius Costa Gomes7034b912011-07-07 18:59:34 -0300921
922 /* The responder sends its keys first */
923 if (!force && conn->hcon->out && (rsp->resp_key_dist & 0x07))
924 return 0;
925
Vinicius Costa Gomes1c1def02011-09-05 14:31:30 -0300926 req = (void *) &smp->preq[1];
Vinicius Costa Gomes7034b912011-07-07 18:59:34 -0300927
928 if (conn->hcon->out) {
929 keydist = &rsp->init_key_dist;
930 *keydist &= req->init_key_dist;
931 } else {
932 keydist = &rsp->resp_key_dist;
933 *keydist &= req->resp_key_dist;
934 }
935
936
937 BT_DBG("keydist 0x%x", *keydist);
938
939 if (*keydist & SMP_DIST_ENC_KEY) {
940 struct smp_cmd_encrypt_info enc;
941 struct smp_cmd_master_ident ident;
Vinicius Costa Gomesc9839a12012-02-02 21:08:01 -0300942 struct hci_conn *hcon = conn->hcon;
943 u8 authenticated;
Vinicius Costa Gomes7034b912011-07-07 18:59:34 -0300944 __le16 ediv;
945
946 get_random_bytes(enc.ltk, sizeof(enc.ltk));
947 get_random_bytes(&ediv, sizeof(ediv));
948 get_random_bytes(ident.rand, sizeof(ident.rand));
949
950 smp_send_cmd(conn, SMP_CMD_ENCRYPT_INFO, sizeof(enc), &enc);
951
Vinicius Costa Gomesc9839a12012-02-02 21:08:01 -0300952 authenticated = hcon->sec_level == BT_SECURITY_HIGH;
953 hci_add_ltk(conn->hcon->hdev, conn->dst, hcon->dst_type,
Gustavo F. Padovan04124682012-03-08 01:25:00 -0300954 HCI_SMP_LTK_SLAVE, 1, authenticated,
955 enc.ltk, smp->enc_key_size, ediv, ident.rand);
Vinicius Costa Gomes16b90832011-07-07 18:59:39 -0300956
Vinicius Costa Gomes7034b912011-07-07 18:59:34 -0300957 ident.ediv = cpu_to_le16(ediv);
958
959 smp_send_cmd(conn, SMP_CMD_MASTER_IDENT, sizeof(ident), &ident);
960
961 *keydist &= ~SMP_DIST_ENC_KEY;
962 }
963
964 if (*keydist & SMP_DIST_ID_KEY) {
965 struct smp_cmd_ident_addr_info addrinfo;
966 struct smp_cmd_ident_info idinfo;
967
968 /* Send a dummy key */
969 get_random_bytes(idinfo.irk, sizeof(idinfo.irk));
970
971 smp_send_cmd(conn, SMP_CMD_IDENT_INFO, sizeof(idinfo), &idinfo);
972
973 /* Just public address */
974 memset(&addrinfo, 0, sizeof(addrinfo));
975 bacpy(&addrinfo.bdaddr, conn->src);
976
977 smp_send_cmd(conn, SMP_CMD_IDENT_ADDR_INFO, sizeof(addrinfo),
978 &addrinfo);
979
980 *keydist &= ~SMP_DIST_ID_KEY;
981 }
982
983 if (*keydist & SMP_DIST_SIGN) {
984 struct smp_cmd_sign_info sign;
985
986 /* Send a dummy key */
987 get_random_bytes(sign.csrk, sizeof(sign.csrk));
988
989 smp_send_cmd(conn, SMP_CMD_SIGN_INFO, sizeof(sign), &sign);
990
991 *keydist &= ~SMP_DIST_SIGN;
992 }
993
Vinicius Costa Gomesd26a2342011-08-19 21:06:51 -0300994 if (conn->hcon->out || force) {
Johan Hedberg51a8efd2012-01-16 06:10:31 +0200995 clear_bit(HCI_CONN_LE_SMP_PEND, &conn->hcon->flags);
Gustavo F. Padovan6c9d42a2011-12-20 10:57:27 -0200996 cancel_delayed_work_sync(&conn->security_timer);
Vinicius Costa Gomes8aab4752011-09-05 14:31:31 -0300997 smp_chan_destroy(conn);
Vinicius Costa Gomesd26a2342011-08-19 21:06:51 -0300998 }
999
Vinicius Costa Gomes7034b912011-07-07 18:59:34 -03001000 return 0;
1001}