blob: f6a6d8be3051f2195d00b68a4531dc7ecd401ae1 [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
Vinicius Costa Gomes5d3de7d2011-06-14 13:37:41 -030032#define SMP_TIMEOUT 30000 /* 30 seconds */
33
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);
189 schedule_delayed_work(&conn->security_timer,
Vinicius Costa Gomese2dcd112011-08-19 21:06:50 -0300190 msecs_to_jiffies(SMP_TIMEOUT));
Anderson Brigliaeb492e02011-06-09 18:50:40 -0300191}
192
Brian Gix2b64d152011-12-21 16:12:12 -0800193static __u8 authreq_to_seclevel(__u8 authreq)
194{
195 if (authreq & SMP_AUTH_MITM)
196 return BT_SECURITY_HIGH;
197 else
198 return BT_SECURITY_MEDIUM;
199}
200
201static __u8 seclevel_to_authreq(__u8 sec_level)
202{
203 switch (sec_level) {
204 case BT_SECURITY_HIGH:
205 return SMP_AUTH_MITM | SMP_AUTH_BONDING;
206 case BT_SECURITY_MEDIUM:
207 return SMP_AUTH_BONDING;
208 default:
209 return SMP_AUTH_NONE;
210 }
211}
212
Vinicius Costa Gomesb8e66ea2011-06-09 18:50:52 -0300213static void build_pairing_cmd(struct l2cap_conn *conn,
Vinicius Costa Gomes54790f72011-07-07 18:59:38 -0300214 struct smp_cmd_pairing *req,
215 struct smp_cmd_pairing *rsp,
216 __u8 authreq)
Vinicius Costa Gomesb8e66ea2011-06-09 18:50:52 -0300217{
Brian Gix2b64d152011-12-21 16:12:12 -0800218 u8 dist_keys = 0;
Vinicius Costa Gomes54790f72011-07-07 18:59:38 -0300219
Johan Hedberga8b2d5c2012-01-08 23:11:15 +0200220 if (test_bit(HCI_PAIRABLE, &conn->hcon->hdev->dev_flags)) {
Vinicius Costa Gomesca10b5e2011-08-25 20:02:37 -0300221 dist_keys = SMP_DIST_ENC_KEY;
Vinicius Costa Gomes54790f72011-07-07 18:59:38 -0300222 authreq |= SMP_AUTH_BONDING;
Brian Gix2b64d152011-12-21 16:12:12 -0800223 } else {
224 authreq &= ~SMP_AUTH_BONDING;
Vinicius Costa Gomes54790f72011-07-07 18:59:38 -0300225 }
226
227 if (rsp == NULL) {
228 req->io_capability = conn->hcon->io_capability;
229 req->oob_flag = SMP_OOB_NOT_PRESENT;
230 req->max_key_size = SMP_MAX_ENC_KEY_SIZE;
Brian Gix2b64d152011-12-21 16:12:12 -0800231 req->init_key_dist = 0;
Vinicius Costa Gomes54790f72011-07-07 18:59:38 -0300232 req->resp_key_dist = dist_keys;
233 req->auth_req = authreq;
234 return;
235 }
236
237 rsp->io_capability = conn->hcon->io_capability;
238 rsp->oob_flag = SMP_OOB_NOT_PRESENT;
239 rsp->max_key_size = SMP_MAX_ENC_KEY_SIZE;
Brian Gix2b64d152011-12-21 16:12:12 -0800240 rsp->init_key_dist = 0;
Vinicius Costa Gomes54790f72011-07-07 18:59:38 -0300241 rsp->resp_key_dist = req->resp_key_dist & dist_keys;
242 rsp->auth_req = authreq;
Vinicius Costa Gomesb8e66ea2011-06-09 18:50:52 -0300243}
244
Vinicius Costa Gomes3158c502011-06-14 13:37:42 -0300245static u8 check_enc_key_size(struct l2cap_conn *conn, __u8 max_key_size)
246{
Vinicius Costa Gomes1c1def02011-09-05 14:31:30 -0300247 struct smp_chan *smp = conn->smp_chan;
248
Vinicius Costa Gomes3158c502011-06-14 13:37:42 -0300249 if ((max_key_size > SMP_MAX_ENC_KEY_SIZE) ||
250 (max_key_size < SMP_MIN_ENC_KEY_SIZE))
251 return SMP_ENC_KEY_SIZE;
252
Vinicius Costa Gomesf7aa6112012-01-30 19:29:12 -0300253 smp->enc_key_size = max_key_size;
Vinicius Costa Gomes3158c502011-06-14 13:37:42 -0300254
255 return 0;
256}
257
Brian Gix4f957a72011-11-23 08:28:36 -0800258static void smp_failure(struct l2cap_conn *conn, u8 reason, u8 send)
259{
Johan Hedbergbab73cb2012-02-09 16:07:29 +0200260 struct hci_conn *hcon = conn->hcon;
261
Brian Gix4f957a72011-11-23 08:28:36 -0800262 if (send)
263 smp_send_cmd(conn, SMP_CMD_PAIRING_FAIL, sizeof(reason),
264 &reason);
265
Johan Hedberg51a8efd2012-01-16 06:10:31 +0200266 clear_bit(HCI_CONN_ENCRYPT_PEND, &conn->hcon->flags);
Johan Hedbergbab73cb2012-02-09 16:07:29 +0200267 mgmt_auth_failed(conn->hcon->hdev, conn->dst, hcon->type,
268 hcon->dst_type, reason);
Vinicius Costa Gomesf1c09c02012-02-01 18:27:56 -0300269
270 if (test_and_clear_bit(HCI_CONN_LE_SMP_PEND, &conn->hcon->flags)) {
271 cancel_delayed_work_sync(&conn->security_timer);
272 smp_chan_destroy(conn);
273 }
Brian Gix4f957a72011-11-23 08:28:36 -0800274}
275
Brian Gix2b64d152011-12-21 16:12:12 -0800276#define JUST_WORKS 0x00
277#define JUST_CFM 0x01
278#define REQ_PASSKEY 0x02
279#define CFM_PASSKEY 0x03
280#define REQ_OOB 0x04
281#define OVERLAP 0xFF
282
283static const u8 gen_method[5][5] = {
284 { JUST_WORKS, JUST_CFM, REQ_PASSKEY, JUST_WORKS, REQ_PASSKEY },
285 { JUST_WORKS, JUST_CFM, REQ_PASSKEY, JUST_WORKS, REQ_PASSKEY },
286 { CFM_PASSKEY, CFM_PASSKEY, REQ_PASSKEY, JUST_WORKS, CFM_PASSKEY },
287 { JUST_WORKS, JUST_CFM, JUST_WORKS, JUST_WORKS, JUST_CFM },
288 { CFM_PASSKEY, CFM_PASSKEY, REQ_PASSKEY, JUST_WORKS, OVERLAP },
289};
290
291static int tk_request(struct l2cap_conn *conn, u8 remote_oob, u8 auth,
292 u8 local_io, u8 remote_io)
293{
294 struct hci_conn *hcon = conn->hcon;
295 struct smp_chan *smp = conn->smp_chan;
296 u8 method;
297 u32 passkey = 0;
298 int ret = 0;
299
300 /* Initialize key for JUST WORKS */
301 memset(smp->tk, 0, sizeof(smp->tk));
302 clear_bit(SMP_FLAG_TK_VALID, &smp->smp_flags);
303
304 BT_DBG("tk_request: auth:%d lcl:%d rem:%d", auth, local_io, remote_io);
305
306 /* If neither side wants MITM, use JUST WORKS */
307 /* If either side has unknown io_caps, use JUST WORKS */
308 /* Otherwise, look up method from the table */
309 if (!(auth & SMP_AUTH_MITM) ||
310 local_io > SMP_IO_KEYBOARD_DISPLAY ||
311 remote_io > SMP_IO_KEYBOARD_DISPLAY)
312 method = JUST_WORKS;
313 else
314 method = gen_method[local_io][remote_io];
315
316 /* If not bonding, don't ask user to confirm a Zero TK */
317 if (!(auth & SMP_AUTH_BONDING) && method == JUST_CFM)
318 method = JUST_WORKS;
319
320 /* If Just Works, Continue with Zero TK */
321 if (method == JUST_WORKS) {
322 set_bit(SMP_FLAG_TK_VALID, &smp->smp_flags);
323 return 0;
324 }
325
326 /* Not Just Works/Confirm results in MITM Authentication */
327 if (method != JUST_CFM)
328 set_bit(SMP_FLAG_MITM_AUTH, &smp->smp_flags);
329
330 /* If both devices have Keyoard-Display I/O, the master
331 * Confirms and the slave Enters the passkey.
332 */
333 if (method == OVERLAP) {
334 if (hcon->link_mode & HCI_LM_MASTER)
335 method = CFM_PASSKEY;
336 else
337 method = REQ_PASSKEY;
338 }
339
340 /* Generate random passkey. Not valid until confirmed. */
341 if (method == CFM_PASSKEY) {
342 u8 key[16];
343
344 memset(key, 0, sizeof(key));
345 get_random_bytes(&passkey, sizeof(passkey));
346 passkey %= 1000000;
347 put_unaligned_le32(passkey, key);
348 swap128(key, smp->tk);
349 BT_DBG("PassKey: %d", passkey);
350 }
351
352 hci_dev_lock(hcon->hdev);
353
354 if (method == REQ_PASSKEY)
Johan Hedberg272d90d2012-02-09 15:26:12 +0200355 ret = mgmt_user_passkey_request(hcon->hdev, conn->dst,
356 hcon->type, hcon->dst_type);
Brian Gix2b64d152011-12-21 16:12:12 -0800357 else
358 ret = mgmt_user_confirm_request(hcon->hdev, conn->dst,
Johan Hedberg272d90d2012-02-09 15:26:12 +0200359 hcon->type, hcon->dst_type,
Brian Gix2b64d152011-12-21 16:12:12 -0800360 cpu_to_le32(passkey), 0);
361
362 hci_dev_unlock(hcon->hdev);
363
364 return ret;
365}
366
Vinicius Costa Gomes8aab4752011-09-05 14:31:31 -0300367static void confirm_work(struct work_struct *work)
368{
369 struct smp_chan *smp = container_of(work, struct smp_chan, confirm);
370 struct l2cap_conn *conn = smp->conn;
371 struct crypto_blkcipher *tfm;
372 struct smp_cmd_pairing_confirm cp;
373 int ret;
374 u8 res[16], reason;
375
376 BT_DBG("conn %p", conn);
377
378 tfm = crypto_alloc_blkcipher("ecb(aes)", 0, CRYPTO_ALG_ASYNC);
379 if (IS_ERR(tfm)) {
380 reason = SMP_UNSPECIFIED;
381 goto error;
382 }
383
384 smp->tfm = tfm;
385
386 if (conn->hcon->out)
387 ret = smp_c1(tfm, smp->tk, smp->prnd, smp->preq, smp->prsp, 0,
388 conn->src, conn->hcon->dst_type, conn->dst,
389 res);
390 else
391 ret = smp_c1(tfm, smp->tk, smp->prnd, smp->preq, smp->prsp,
392 conn->hcon->dst_type, conn->dst, 0, conn->src,
393 res);
394 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,
428 conn->src, hcon->dst_type, conn->dst,
429 res);
430 else
431 ret = smp_c1(tfm, smp->tk, smp->rrnd, smp->preq, smp->prsp,
432 hcon->dst_type, conn->dst, 0, conn->src,
433 res);
434 if (ret) {
435 reason = SMP_UNSPECIFIED;
436 goto error;
437 }
438
439 swap128(res, confirm);
440
441 if (memcmp(smp->pcnf, confirm, sizeof(smp->pcnf)) != 0) {
442 BT_ERR("Pairing failed (confirmation values mismatch)");
443 reason = SMP_CONFIRM_FAILED;
444 goto error;
445 }
446
447 if (hcon->out) {
448 u8 stk[16], rand[8];
449 __le16 ediv;
450
451 memset(rand, 0, sizeof(rand));
452 ediv = 0;
453
454 smp_s1(tfm, smp->tk, smp->rrnd, smp->prnd, key);
455 swap128(key, stk);
456
Vinicius Costa Gomesf7aa6112012-01-30 19:29:12 -0300457 memset(stk + smp->enc_key_size, 0,
458 SMP_MAX_ENC_KEY_SIZE - smp->enc_key_size);
Vinicius Costa Gomes8aab4752011-09-05 14:31:31 -0300459
Johan Hedberg51a8efd2012-01-16 06:10:31 +0200460 if (test_and_set_bit(HCI_CONN_ENCRYPT_PEND, &hcon->flags)) {
Vinicius Costa Gomes8aab4752011-09-05 14:31:31 -0300461 reason = SMP_UNSPECIFIED;
462 goto error;
463 }
464
465 hci_le_start_enc(hcon, ediv, rand, stk);
Vinicius Costa Gomesf7aa6112012-01-30 19:29:12 -0300466 hcon->enc_key_size = smp->enc_key_size;
Vinicius Costa Gomes8aab4752011-09-05 14:31:31 -0300467 } else {
468 u8 stk[16], r[16], rand[8];
469 __le16 ediv;
470
471 memset(rand, 0, sizeof(rand));
472 ediv = 0;
473
474 swap128(smp->prnd, r);
475 smp_send_cmd(conn, SMP_CMD_PAIRING_RANDOM, sizeof(r), r);
476
477 smp_s1(tfm, smp->tk, smp->prnd, smp->rrnd, key);
478 swap128(key, stk);
479
Vinicius Costa Gomesf7aa6112012-01-30 19:29:12 -0300480 memset(stk + smp->enc_key_size, 0,
481 SMP_MAX_ENC_KEY_SIZE - smp->enc_key_size);
Vinicius Costa Gomes8aab4752011-09-05 14:31:31 -0300482
Vinicius Costa Gomesc9839a12012-02-02 21:08:01 -0300483 hci_add_ltk(hcon->hdev, conn->dst, hcon->dst_type,
484 HCI_SMP_STK_SLAVE, 0, 0, stk,
485 smp->enc_key_size, ediv, rand);
Vinicius Costa Gomes8aab4752011-09-05 14:31:31 -0300486 }
487
488 return;
489
490error:
Brian Gix4f957a72011-11-23 08:28:36 -0800491 smp_failure(conn, reason, 1);
Vinicius Costa Gomes8aab4752011-09-05 14:31:31 -0300492}
493
494static struct smp_chan *smp_chan_create(struct l2cap_conn *conn)
495{
496 struct smp_chan *smp;
497
498 smp = kzalloc(sizeof(struct smp_chan), GFP_ATOMIC);
499 if (!smp)
500 return NULL;
501
502 INIT_WORK(&smp->confirm, confirm_work);
503 INIT_WORK(&smp->random, random_work);
504
505 smp->conn = conn;
506 conn->smp_chan = smp;
Brian Gix2b64d152011-12-21 16:12:12 -0800507 conn->hcon->smp_conn = conn;
Vinicius Costa Gomes8aab4752011-09-05 14:31:31 -0300508
509 hci_conn_hold(conn->hcon);
510
511 return smp;
512}
513
514void smp_chan_destroy(struct l2cap_conn *conn)
515{
Brian Gixc8eb9692011-11-23 08:28:35 -0800516 struct smp_chan *smp = conn->smp_chan;
517
Vinicius Costa Gomesf1c09c02012-02-01 18:27:56 -0300518 BUG_ON(!smp);
Brian Gixc8eb9692011-11-23 08:28:35 -0800519
520 if (smp->tfm)
521 crypto_free_blkcipher(smp->tfm);
522
523 kfree(smp);
524 conn->smp_chan = NULL;
Brian Gix2b64d152011-12-21 16:12:12 -0800525 conn->hcon->smp_conn = NULL;
Vinicius Costa Gomes8aab4752011-09-05 14:31:31 -0300526 hci_conn_put(conn->hcon);
527}
528
Brian Gix2b64d152011-12-21 16:12:12 -0800529int smp_user_confirm_reply(struct hci_conn *hcon, u16 mgmt_op, __le32 passkey)
530{
531 struct l2cap_conn *conn = hcon->smp_conn;
532 struct smp_chan *smp;
533 u32 value;
534 u8 key[16];
535
536 BT_DBG("");
537
538 if (!conn)
539 return -ENOTCONN;
540
541 smp = conn->smp_chan;
542
543 switch (mgmt_op) {
544 case MGMT_OP_USER_PASSKEY_REPLY:
545 value = le32_to_cpu(passkey);
546 memset(key, 0, sizeof(key));
547 BT_DBG("PassKey: %d", value);
548 put_unaligned_le32(value, key);
549 swap128(key, smp->tk);
550 /* Fall Through */
551 case MGMT_OP_USER_CONFIRM_REPLY:
552 set_bit(SMP_FLAG_TK_VALID, &smp->smp_flags);
553 break;
554 case MGMT_OP_USER_PASSKEY_NEG_REPLY:
555 case MGMT_OP_USER_CONFIRM_NEG_REPLY:
556 smp_failure(conn, SMP_PASSKEY_ENTRY_FAILED, 1);
557 return 0;
558 default:
559 smp_failure(conn, SMP_PASSKEY_ENTRY_FAILED, 1);
560 return -EOPNOTSUPP;
561 }
562
563 /* If it is our turn to send Pairing Confirm, do so now */
564 if (test_bit(SMP_FLAG_CFM_PENDING, &smp->smp_flags))
565 queue_work(hcon->hdev->workqueue, &smp->confirm);
566
567 return 0;
568}
569
Vinicius Costa Gomesda85e5e2011-06-09 18:50:53 -0300570static u8 smp_cmd_pairing_req(struct l2cap_conn *conn, struct sk_buff *skb)
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300571{
Vinicius Costa Gomes3158c502011-06-14 13:37:42 -0300572 struct smp_cmd_pairing rsp, *req = (void *) skb->data;
Vinicius Costa Gomes8aab4752011-09-05 14:31:31 -0300573 struct smp_chan *smp;
Vinicius Costa Gomes3158c502011-06-14 13:37:42 -0300574 u8 key_size;
Brian Gix2b64d152011-12-21 16:12:12 -0800575 u8 auth = SMP_AUTH_NONE;
Vinicius Costa Gomes8aab4752011-09-05 14:31:31 -0300576 int ret;
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300577
578 BT_DBG("conn %p", conn);
579
Brian Gix2b64d152011-12-21 16:12:12 -0800580 if (conn->hcon->link_mode & HCI_LM_MASTER)
581 return SMP_CMD_NOTSUPP;
582
Johan Hedberg51a8efd2012-01-16 06:10:31 +0200583 if (!test_and_set_bit(HCI_CONN_LE_SMP_PEND, &conn->hcon->flags))
Vinicius Costa Gomes8aab4752011-09-05 14:31:31 -0300584 smp = smp_chan_create(conn);
585
586 smp = conn->smp_chan;
Vinicius Costa Gomesd26a2342011-08-19 21:06:51 -0300587
Vinicius Costa Gomes1c1def02011-09-05 14:31:30 -0300588 smp->preq[0] = SMP_CMD_PAIRING_REQ;
589 memcpy(&smp->preq[1], req, sizeof(*req));
Vinicius Costa Gomes3158c502011-06-14 13:37:42 -0300590 skb_pull(skb, sizeof(*req));
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300591
Brian Gix2b64d152011-12-21 16:12:12 -0800592 /* We didn't start the pairing, so match remote */
593 if (req->auth_req & SMP_AUTH_BONDING)
594 auth = req->auth_req;
Vinicius Costa Gomesda85e5e2011-06-09 18:50:53 -0300595
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
Anderson Brigliaeb492e02011-06-09 18:50:40 -0300758int smp_conn_security(struct l2cap_conn *conn, __u8 sec_level)
759{
Vinicius Costa Gomes3a0259b2011-06-09 18:50:43 -0300760 struct hci_conn *hcon = conn->hcon;
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,
833 HCI_SMP_LTK, 1, authenticated, smp->tk,
834 smp->enc_key_size, 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
855 switch (code) {
856 case SMP_CMD_PAIRING_REQ:
Vinicius Costa Gomesda85e5e2011-06-09 18:50:53 -0300857 reason = smp_cmd_pairing_req(conn, skb);
Anderson Brigliaeb492e02011-06-09 18:50:40 -0300858 break;
859
860 case SMP_CMD_PAIRING_FAIL:
Brian Gix4f957a72011-11-23 08:28:36 -0800861 smp_failure(conn, skb->data[0], 0);
Vinicius Costa Gomesda85e5e2011-06-09 18:50:53 -0300862 reason = 0;
863 err = -EPERM;
Anderson Brigliaeb492e02011-06-09 18:50:40 -0300864 break;
865
866 case SMP_CMD_PAIRING_RSP:
Vinicius Costa Gomesda85e5e2011-06-09 18:50:53 -0300867 reason = smp_cmd_pairing_rsp(conn, skb);
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300868 break;
869
870 case SMP_CMD_SECURITY_REQ:
Vinicius Costa Gomesda85e5e2011-06-09 18:50:53 -0300871 reason = smp_cmd_security_req(conn, skb);
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300872 break;
873
Anderson Brigliaeb492e02011-06-09 18:50:40 -0300874 case SMP_CMD_PAIRING_CONFIRM:
Vinicius Costa Gomesda85e5e2011-06-09 18:50:53 -0300875 reason = smp_cmd_pairing_confirm(conn, skb);
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300876 break;
877
Anderson Brigliaeb492e02011-06-09 18:50:40 -0300878 case SMP_CMD_PAIRING_RANDOM:
Vinicius Costa Gomesda85e5e2011-06-09 18:50:53 -0300879 reason = smp_cmd_pairing_random(conn, skb);
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300880 break;
881
Anderson Brigliaeb492e02011-06-09 18:50:40 -0300882 case SMP_CMD_ENCRYPT_INFO:
Vinicius Costa Gomes7034b912011-07-07 18:59:34 -0300883 reason = smp_cmd_encrypt_info(conn, skb);
884 break;
885
Anderson Brigliaeb492e02011-06-09 18:50:40 -0300886 case SMP_CMD_MASTER_IDENT:
Vinicius Costa Gomes7034b912011-07-07 18:59:34 -0300887 reason = smp_cmd_master_ident(conn, skb);
888 break;
889
Anderson Brigliaeb492e02011-06-09 18:50:40 -0300890 case SMP_CMD_IDENT_INFO:
891 case SMP_CMD_IDENT_ADDR_INFO:
892 case SMP_CMD_SIGN_INFO:
Vinicius Costa Gomes7034b912011-07-07 18:59:34 -0300893 /* Just ignored */
894 reason = 0;
895 break;
896
Anderson Brigliaeb492e02011-06-09 18:50:40 -0300897 default:
898 BT_DBG("Unknown command code 0x%2.2x", code);
899
900 reason = SMP_CMD_NOTSUPP;
Vinicius Costa Gomes3a0259b2011-06-09 18:50:43 -0300901 err = -EOPNOTSUPP;
902 goto done;
903 }
904
905done:
906 if (reason)
Brian Gix4f957a72011-11-23 08:28:36 -0800907 smp_failure(conn, reason, 1);
Anderson Brigliaeb492e02011-06-09 18:50:40 -0300908
909 kfree_skb(skb);
910 return err;
911}
Vinicius Costa Gomes7034b912011-07-07 18:59:34 -0300912
913int smp_distribute_keys(struct l2cap_conn *conn, __u8 force)
914{
915 struct smp_cmd_pairing *req, *rsp;
Vinicius Costa Gomes1c1def02011-09-05 14:31:30 -0300916 struct smp_chan *smp = conn->smp_chan;
Vinicius Costa Gomes7034b912011-07-07 18:59:34 -0300917 __u8 *keydist;
918
919 BT_DBG("conn %p force %d", conn, force);
920
Johan Hedberg51a8efd2012-01-16 06:10:31 +0200921 if (!test_bit(HCI_CONN_LE_SMP_PEND, &conn->hcon->flags))
Vinicius Costa Gomesd26a2342011-08-19 21:06:51 -0300922 return 0;
923
Vinicius Costa Gomes1c1def02011-09-05 14:31:30 -0300924 rsp = (void *) &smp->prsp[1];
Vinicius Costa Gomes7034b912011-07-07 18:59:34 -0300925
926 /* The responder sends its keys first */
927 if (!force && conn->hcon->out && (rsp->resp_key_dist & 0x07))
928 return 0;
929
Vinicius Costa Gomes1c1def02011-09-05 14:31:30 -0300930 req = (void *) &smp->preq[1];
Vinicius Costa Gomes7034b912011-07-07 18:59:34 -0300931
932 if (conn->hcon->out) {
933 keydist = &rsp->init_key_dist;
934 *keydist &= req->init_key_dist;
935 } else {
936 keydist = &rsp->resp_key_dist;
937 *keydist &= req->resp_key_dist;
938 }
939
940
941 BT_DBG("keydist 0x%x", *keydist);
942
943 if (*keydist & SMP_DIST_ENC_KEY) {
944 struct smp_cmd_encrypt_info enc;
945 struct smp_cmd_master_ident ident;
Vinicius Costa Gomesc9839a12012-02-02 21:08:01 -0300946 struct hci_conn *hcon = conn->hcon;
947 u8 authenticated;
Vinicius Costa Gomes7034b912011-07-07 18:59:34 -0300948 __le16 ediv;
949
950 get_random_bytes(enc.ltk, sizeof(enc.ltk));
951 get_random_bytes(&ediv, sizeof(ediv));
952 get_random_bytes(ident.rand, sizeof(ident.rand));
953
954 smp_send_cmd(conn, SMP_CMD_ENCRYPT_INFO, sizeof(enc), &enc);
955
Vinicius Costa Gomesc9839a12012-02-02 21:08:01 -0300956 authenticated = hcon->sec_level == BT_SECURITY_HIGH;
957 hci_add_ltk(conn->hcon->hdev, conn->dst, hcon->dst_type,
958 HCI_SMP_LTK_SLAVE, 1, authenticated,
959 enc.ltk, smp->enc_key_size,
960 ediv, ident.rand);
Vinicius Costa Gomes16b90832011-07-07 18:59:39 -0300961
Vinicius Costa Gomes7034b912011-07-07 18:59:34 -0300962 ident.ediv = cpu_to_le16(ediv);
963
964 smp_send_cmd(conn, SMP_CMD_MASTER_IDENT, sizeof(ident), &ident);
965
966 *keydist &= ~SMP_DIST_ENC_KEY;
967 }
968
969 if (*keydist & SMP_DIST_ID_KEY) {
970 struct smp_cmd_ident_addr_info addrinfo;
971 struct smp_cmd_ident_info idinfo;
972
973 /* Send a dummy key */
974 get_random_bytes(idinfo.irk, sizeof(idinfo.irk));
975
976 smp_send_cmd(conn, SMP_CMD_IDENT_INFO, sizeof(idinfo), &idinfo);
977
978 /* Just public address */
979 memset(&addrinfo, 0, sizeof(addrinfo));
980 bacpy(&addrinfo.bdaddr, conn->src);
981
982 smp_send_cmd(conn, SMP_CMD_IDENT_ADDR_INFO, sizeof(addrinfo),
983 &addrinfo);
984
985 *keydist &= ~SMP_DIST_ID_KEY;
986 }
987
988 if (*keydist & SMP_DIST_SIGN) {
989 struct smp_cmd_sign_info sign;
990
991 /* Send a dummy key */
992 get_random_bytes(sign.csrk, sizeof(sign.csrk));
993
994 smp_send_cmd(conn, SMP_CMD_SIGN_INFO, sizeof(sign), &sign);
995
996 *keydist &= ~SMP_DIST_SIGN;
997 }
998
Vinicius Costa Gomesd26a2342011-08-19 21:06:51 -0300999 if (conn->hcon->out || force) {
Johan Hedberg51a8efd2012-01-16 06:10:31 +02001000 clear_bit(HCI_CONN_LE_SMP_PEND, &conn->hcon->flags);
Gustavo F. Padovan6c9d42a2011-12-20 10:57:27 -02001001 cancel_delayed_work_sync(&conn->security_timer);
Vinicius Costa Gomes8aab4752011-09-05 14:31:31 -03001002 smp_chan_destroy(conn);
Vinicius Costa Gomesd26a2342011-08-19 21:06:51 -03001003 }
1004
Vinicius Costa Gomes7034b912011-07-07 18:59:34 -03001005 return 0;
1006}