blob: 9ff56e18d99b1c08426103e5ffa5f8fbdb0330b5 [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{
260 if (send)
261 smp_send_cmd(conn, SMP_CMD_PAIRING_FAIL, sizeof(reason),
262 &reason);
263
Johan Hedberg51a8efd2012-01-16 06:10:31 +0200264 clear_bit(HCI_CONN_ENCRYPT_PEND, &conn->hcon->flags);
Brian Gix4f957a72011-11-23 08:28:36 -0800265 mgmt_auth_failed(conn->hcon->hdev, conn->dst, reason);
Vinicius Costa Gomesf1c09c02012-02-01 18:27:56 -0300266
267 if (test_and_clear_bit(HCI_CONN_LE_SMP_PEND, &conn->hcon->flags)) {
268 cancel_delayed_work_sync(&conn->security_timer);
269 smp_chan_destroy(conn);
270 }
Brian Gix4f957a72011-11-23 08:28:36 -0800271}
272
Brian Gix2b64d152011-12-21 16:12:12 -0800273#define JUST_WORKS 0x00
274#define JUST_CFM 0x01
275#define REQ_PASSKEY 0x02
276#define CFM_PASSKEY 0x03
277#define REQ_OOB 0x04
278#define OVERLAP 0xFF
279
280static const u8 gen_method[5][5] = {
281 { JUST_WORKS, JUST_CFM, REQ_PASSKEY, JUST_WORKS, REQ_PASSKEY },
282 { JUST_WORKS, JUST_CFM, REQ_PASSKEY, JUST_WORKS, REQ_PASSKEY },
283 { CFM_PASSKEY, CFM_PASSKEY, REQ_PASSKEY, JUST_WORKS, CFM_PASSKEY },
284 { JUST_WORKS, JUST_CFM, JUST_WORKS, JUST_WORKS, JUST_CFM },
285 { CFM_PASSKEY, CFM_PASSKEY, REQ_PASSKEY, JUST_WORKS, OVERLAP },
286};
287
288static int tk_request(struct l2cap_conn *conn, u8 remote_oob, u8 auth,
289 u8 local_io, u8 remote_io)
290{
291 struct hci_conn *hcon = conn->hcon;
292 struct smp_chan *smp = conn->smp_chan;
293 u8 method;
294 u32 passkey = 0;
295 int ret = 0;
296
297 /* Initialize key for JUST WORKS */
298 memset(smp->tk, 0, sizeof(smp->tk));
299 clear_bit(SMP_FLAG_TK_VALID, &smp->smp_flags);
300
301 BT_DBG("tk_request: auth:%d lcl:%d rem:%d", auth, local_io, remote_io);
302
303 /* If neither side wants MITM, use JUST WORKS */
304 /* If either side has unknown io_caps, use JUST WORKS */
305 /* Otherwise, look up method from the table */
306 if (!(auth & SMP_AUTH_MITM) ||
307 local_io > SMP_IO_KEYBOARD_DISPLAY ||
308 remote_io > SMP_IO_KEYBOARD_DISPLAY)
309 method = JUST_WORKS;
310 else
311 method = gen_method[local_io][remote_io];
312
313 /* If not bonding, don't ask user to confirm a Zero TK */
314 if (!(auth & SMP_AUTH_BONDING) && method == JUST_CFM)
315 method = JUST_WORKS;
316
317 /* If Just Works, Continue with Zero TK */
318 if (method == JUST_WORKS) {
319 set_bit(SMP_FLAG_TK_VALID, &smp->smp_flags);
320 return 0;
321 }
322
323 /* Not Just Works/Confirm results in MITM Authentication */
324 if (method != JUST_CFM)
325 set_bit(SMP_FLAG_MITM_AUTH, &smp->smp_flags);
326
327 /* If both devices have Keyoard-Display I/O, the master
328 * Confirms and the slave Enters the passkey.
329 */
330 if (method == OVERLAP) {
331 if (hcon->link_mode & HCI_LM_MASTER)
332 method = CFM_PASSKEY;
333 else
334 method = REQ_PASSKEY;
335 }
336
337 /* Generate random passkey. Not valid until confirmed. */
338 if (method == CFM_PASSKEY) {
339 u8 key[16];
340
341 memset(key, 0, sizeof(key));
342 get_random_bytes(&passkey, sizeof(passkey));
343 passkey %= 1000000;
344 put_unaligned_le32(passkey, key);
345 swap128(key, smp->tk);
346 BT_DBG("PassKey: %d", passkey);
347 }
348
349 hci_dev_lock(hcon->hdev);
350
351 if (method == REQ_PASSKEY)
352 ret = mgmt_user_passkey_request(hcon->hdev, conn->dst);
353 else
354 ret = mgmt_user_confirm_request(hcon->hdev, conn->dst,
355 cpu_to_le32(passkey), 0);
356
357 hci_dev_unlock(hcon->hdev);
358
359 return ret;
360}
361
Vinicius Costa Gomes8aab4752011-09-05 14:31:31 -0300362static void confirm_work(struct work_struct *work)
363{
364 struct smp_chan *smp = container_of(work, struct smp_chan, confirm);
365 struct l2cap_conn *conn = smp->conn;
366 struct crypto_blkcipher *tfm;
367 struct smp_cmd_pairing_confirm cp;
368 int ret;
369 u8 res[16], reason;
370
371 BT_DBG("conn %p", conn);
372
373 tfm = crypto_alloc_blkcipher("ecb(aes)", 0, CRYPTO_ALG_ASYNC);
374 if (IS_ERR(tfm)) {
375 reason = SMP_UNSPECIFIED;
376 goto error;
377 }
378
379 smp->tfm = tfm;
380
381 if (conn->hcon->out)
382 ret = smp_c1(tfm, smp->tk, smp->prnd, smp->preq, smp->prsp, 0,
383 conn->src, conn->hcon->dst_type, conn->dst,
384 res);
385 else
386 ret = smp_c1(tfm, smp->tk, smp->prnd, smp->preq, smp->prsp,
387 conn->hcon->dst_type, conn->dst, 0, conn->src,
388 res);
389 if (ret) {
390 reason = SMP_UNSPECIFIED;
391 goto error;
392 }
393
Brian Gix2b64d152011-12-21 16:12:12 -0800394 clear_bit(SMP_FLAG_CFM_PENDING, &smp->smp_flags);
395
Vinicius Costa Gomes8aab4752011-09-05 14:31:31 -0300396 swap128(res, cp.confirm_val);
397 smp_send_cmd(smp->conn, SMP_CMD_PAIRING_CONFIRM, sizeof(cp), &cp);
398
399 return;
400
401error:
Brian Gix4f957a72011-11-23 08:28:36 -0800402 smp_failure(conn, reason, 1);
Vinicius Costa Gomes8aab4752011-09-05 14:31:31 -0300403}
404
405static void random_work(struct work_struct *work)
406{
407 struct smp_chan *smp = container_of(work, struct smp_chan, random);
408 struct l2cap_conn *conn = smp->conn;
409 struct hci_conn *hcon = conn->hcon;
410 struct crypto_blkcipher *tfm = smp->tfm;
411 u8 reason, confirm[16], res[16], key[16];
412 int ret;
413
414 if (IS_ERR_OR_NULL(tfm)) {
415 reason = SMP_UNSPECIFIED;
416 goto error;
417 }
418
419 BT_DBG("conn %p %s", conn, conn->hcon->out ? "master" : "slave");
420
421 if (hcon->out)
422 ret = smp_c1(tfm, smp->tk, smp->rrnd, smp->preq, smp->prsp, 0,
423 conn->src, hcon->dst_type, conn->dst,
424 res);
425 else
426 ret = smp_c1(tfm, smp->tk, smp->rrnd, smp->preq, smp->prsp,
427 hcon->dst_type, conn->dst, 0, conn->src,
428 res);
429 if (ret) {
430 reason = SMP_UNSPECIFIED;
431 goto error;
432 }
433
434 swap128(res, confirm);
435
436 if (memcmp(smp->pcnf, confirm, sizeof(smp->pcnf)) != 0) {
437 BT_ERR("Pairing failed (confirmation values mismatch)");
438 reason = SMP_CONFIRM_FAILED;
439 goto error;
440 }
441
442 if (hcon->out) {
443 u8 stk[16], rand[8];
444 __le16 ediv;
445
446 memset(rand, 0, sizeof(rand));
447 ediv = 0;
448
449 smp_s1(tfm, smp->tk, smp->rrnd, smp->prnd, key);
450 swap128(key, stk);
451
Vinicius Costa Gomesf7aa6112012-01-30 19:29:12 -0300452 memset(stk + smp->enc_key_size, 0,
453 SMP_MAX_ENC_KEY_SIZE - smp->enc_key_size);
Vinicius Costa Gomes8aab4752011-09-05 14:31:31 -0300454
Johan Hedberg51a8efd2012-01-16 06:10:31 +0200455 if (test_and_set_bit(HCI_CONN_ENCRYPT_PEND, &hcon->flags)) {
Vinicius Costa Gomes8aab4752011-09-05 14:31:31 -0300456 reason = SMP_UNSPECIFIED;
457 goto error;
458 }
459
460 hci_le_start_enc(hcon, ediv, rand, stk);
Vinicius Costa Gomesf7aa6112012-01-30 19:29:12 -0300461 hcon->enc_key_size = smp->enc_key_size;
Vinicius Costa Gomes8aab4752011-09-05 14:31:31 -0300462 } else {
463 u8 stk[16], r[16], rand[8];
464 __le16 ediv;
465
466 memset(rand, 0, sizeof(rand));
467 ediv = 0;
468
469 swap128(smp->prnd, r);
470 smp_send_cmd(conn, SMP_CMD_PAIRING_RANDOM, sizeof(r), r);
471
472 smp_s1(tfm, smp->tk, smp->prnd, smp->rrnd, key);
473 swap128(key, stk);
474
Vinicius Costa Gomesf7aa6112012-01-30 19:29:12 -0300475 memset(stk + smp->enc_key_size, 0,
476 SMP_MAX_ENC_KEY_SIZE - smp->enc_key_size);
Vinicius Costa Gomes8aab4752011-09-05 14:31:31 -0300477
Vinicius Costa Gomesf7aa6112012-01-30 19:29:12 -0300478 hci_add_ltk(hcon->hdev, 0, conn->dst, smp->enc_key_size,
Vinicius Costa Gomes8aab4752011-09-05 14:31:31 -0300479 ediv, rand, stk);
480 }
481
482 return;
483
484error:
Brian Gix4f957a72011-11-23 08:28:36 -0800485 smp_failure(conn, reason, 1);
Vinicius Costa Gomes8aab4752011-09-05 14:31:31 -0300486}
487
488static struct smp_chan *smp_chan_create(struct l2cap_conn *conn)
489{
490 struct smp_chan *smp;
491
492 smp = kzalloc(sizeof(struct smp_chan), GFP_ATOMIC);
493 if (!smp)
494 return NULL;
495
496 INIT_WORK(&smp->confirm, confirm_work);
497 INIT_WORK(&smp->random, random_work);
498
499 smp->conn = conn;
500 conn->smp_chan = smp;
Brian Gix2b64d152011-12-21 16:12:12 -0800501 conn->hcon->smp_conn = conn;
Vinicius Costa Gomes8aab4752011-09-05 14:31:31 -0300502
503 hci_conn_hold(conn->hcon);
504
505 return smp;
506}
507
508void smp_chan_destroy(struct l2cap_conn *conn)
509{
Brian Gixc8eb9692011-11-23 08:28:35 -0800510 struct smp_chan *smp = conn->smp_chan;
511
Vinicius Costa Gomesf1c09c02012-02-01 18:27:56 -0300512 BUG_ON(!smp);
Brian Gixc8eb9692011-11-23 08:28:35 -0800513
514 if (smp->tfm)
515 crypto_free_blkcipher(smp->tfm);
516
517 kfree(smp);
518 conn->smp_chan = NULL;
Brian Gix2b64d152011-12-21 16:12:12 -0800519 conn->hcon->smp_conn = NULL;
Vinicius Costa Gomes8aab4752011-09-05 14:31:31 -0300520 hci_conn_put(conn->hcon);
521}
522
Brian Gix2b64d152011-12-21 16:12:12 -0800523int smp_user_confirm_reply(struct hci_conn *hcon, u16 mgmt_op, __le32 passkey)
524{
525 struct l2cap_conn *conn = hcon->smp_conn;
526 struct smp_chan *smp;
527 u32 value;
528 u8 key[16];
529
530 BT_DBG("");
531
532 if (!conn)
533 return -ENOTCONN;
534
535 smp = conn->smp_chan;
536
537 switch (mgmt_op) {
538 case MGMT_OP_USER_PASSKEY_REPLY:
539 value = le32_to_cpu(passkey);
540 memset(key, 0, sizeof(key));
541 BT_DBG("PassKey: %d", value);
542 put_unaligned_le32(value, key);
543 swap128(key, smp->tk);
544 /* Fall Through */
545 case MGMT_OP_USER_CONFIRM_REPLY:
546 set_bit(SMP_FLAG_TK_VALID, &smp->smp_flags);
547 break;
548 case MGMT_OP_USER_PASSKEY_NEG_REPLY:
549 case MGMT_OP_USER_CONFIRM_NEG_REPLY:
550 smp_failure(conn, SMP_PASSKEY_ENTRY_FAILED, 1);
551 return 0;
552 default:
553 smp_failure(conn, SMP_PASSKEY_ENTRY_FAILED, 1);
554 return -EOPNOTSUPP;
555 }
556
557 /* If it is our turn to send Pairing Confirm, do so now */
558 if (test_bit(SMP_FLAG_CFM_PENDING, &smp->smp_flags))
559 queue_work(hcon->hdev->workqueue, &smp->confirm);
560
561 return 0;
562}
563
Vinicius Costa Gomesda85e5e2011-06-09 18:50:53 -0300564static u8 smp_cmd_pairing_req(struct l2cap_conn *conn, struct sk_buff *skb)
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300565{
Vinicius Costa Gomes3158c502011-06-14 13:37:42 -0300566 struct smp_cmd_pairing rsp, *req = (void *) skb->data;
Vinicius Costa Gomes8aab4752011-09-05 14:31:31 -0300567 struct smp_chan *smp;
Vinicius Costa Gomes3158c502011-06-14 13:37:42 -0300568 u8 key_size;
Brian Gix2b64d152011-12-21 16:12:12 -0800569 u8 auth = SMP_AUTH_NONE;
Vinicius Costa Gomes8aab4752011-09-05 14:31:31 -0300570 int ret;
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300571
572 BT_DBG("conn %p", conn);
573
Brian Gix2b64d152011-12-21 16:12:12 -0800574 if (conn->hcon->link_mode & HCI_LM_MASTER)
575 return SMP_CMD_NOTSUPP;
576
Johan Hedberg51a8efd2012-01-16 06:10:31 +0200577 if (!test_and_set_bit(HCI_CONN_LE_SMP_PEND, &conn->hcon->flags))
Vinicius Costa Gomes8aab4752011-09-05 14:31:31 -0300578 smp = smp_chan_create(conn);
579
580 smp = conn->smp_chan;
Vinicius Costa Gomesd26a2342011-08-19 21:06:51 -0300581
Vinicius Costa Gomes1c1def02011-09-05 14:31:30 -0300582 smp->preq[0] = SMP_CMD_PAIRING_REQ;
583 memcpy(&smp->preq[1], req, sizeof(*req));
Vinicius Costa Gomes3158c502011-06-14 13:37:42 -0300584 skb_pull(skb, sizeof(*req));
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300585
Brian Gix2b64d152011-12-21 16:12:12 -0800586 /* We didn't start the pairing, so match remote */
587 if (req->auth_req & SMP_AUTH_BONDING)
588 auth = req->auth_req;
Vinicius Costa Gomesda85e5e2011-06-09 18:50:53 -0300589
Brian Gix2b64d152011-12-21 16:12:12 -0800590 build_pairing_cmd(conn, req, &rsp, auth);
Vinicius Costa Gomes3158c502011-06-14 13:37:42 -0300591
592 key_size = min(req->max_key_size, rsp.max_key_size);
593 if (check_enc_key_size(conn, key_size))
594 return SMP_ENC_KEY_SIZE;
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300595
Vinicius Costa Gomes8aab4752011-09-05 14:31:31 -0300596 ret = smp_rand(smp->prnd);
597 if (ret)
598 return SMP_UNSPECIFIED;
599
Vinicius Costa Gomes1c1def02011-09-05 14:31:30 -0300600 smp->prsp[0] = SMP_CMD_PAIRING_RSP;
601 memcpy(&smp->prsp[1], &rsp, sizeof(rsp));
Anderson Brigliaf01ead32011-06-09 18:50:45 -0300602
Vinicius Costa Gomes3158c502011-06-14 13:37:42 -0300603 smp_send_cmd(conn, SMP_CMD_PAIRING_RSP, sizeof(rsp), &rsp);
Vinicius Costa Gomesda85e5e2011-06-09 18:50:53 -0300604
Brian Gix2b64d152011-12-21 16:12:12 -0800605 /* Request setup of TK */
606 ret = tk_request(conn, 0, auth, rsp.io_capability, req->io_capability);
607 if (ret)
608 return SMP_UNSPECIFIED;
609
Vinicius Costa Gomesda85e5e2011-06-09 18:50:53 -0300610 return 0;
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300611}
612
Vinicius Costa Gomesda85e5e2011-06-09 18:50:53 -0300613static u8 smp_cmd_pairing_rsp(struct l2cap_conn *conn, struct sk_buff *skb)
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300614{
Vinicius Costa Gomes3158c502011-06-14 13:37:42 -0300615 struct smp_cmd_pairing *req, *rsp = (void *) skb->data;
Vinicius Costa Gomes1c1def02011-09-05 14:31:30 -0300616 struct smp_chan *smp = conn->smp_chan;
Vinicius Costa Gomes8aab4752011-09-05 14:31:31 -0300617 struct hci_dev *hdev = conn->hcon->hdev;
Brian Gix2b64d152011-12-21 16:12:12 -0800618 u8 key_size, auth = SMP_AUTH_NONE;
Anderson Briglia7d24ddc2011-06-09 18:50:46 -0300619 int ret;
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300620
621 BT_DBG("conn %p", conn);
622
Brian Gix2b64d152011-12-21 16:12:12 -0800623 if (!(conn->hcon->link_mode & HCI_LM_MASTER))
624 return SMP_CMD_NOTSUPP;
625
Vinicius Costa Gomes3158c502011-06-14 13:37:42 -0300626 skb_pull(skb, sizeof(*rsp));
Vinicius Costa Gomesda85e5e2011-06-09 18:50:53 -0300627
Vinicius Costa Gomes1c1def02011-09-05 14:31:30 -0300628 req = (void *) &smp->preq[1];
Vinicius Costa Gomes3158c502011-06-14 13:37:42 -0300629
630 key_size = min(req->max_key_size, rsp->max_key_size);
631 if (check_enc_key_size(conn, key_size))
632 return SMP_ENC_KEY_SIZE;
633
Vinicius Costa Gomes1c1def02011-09-05 14:31:30 -0300634 ret = smp_rand(smp->prnd);
Anderson Briglia7d24ddc2011-06-09 18:50:46 -0300635 if (ret)
Vinicius Costa Gomesda85e5e2011-06-09 18:50:53 -0300636 return SMP_UNSPECIFIED;
Anderson Briglia7d24ddc2011-06-09 18:50:46 -0300637
Vinicius Costa Gomes8aab4752011-09-05 14:31:31 -0300638 smp->prsp[0] = SMP_CMD_PAIRING_RSP;
639 memcpy(&smp->prsp[1], rsp, sizeof(*rsp));
Anderson Briglia7d24ddc2011-06-09 18:50:46 -0300640
Brian Gix2b64d152011-12-21 16:12:12 -0800641 if ((req->auth_req & SMP_AUTH_BONDING) &&
642 (rsp->auth_req & SMP_AUTH_BONDING))
643 auth = SMP_AUTH_BONDING;
644
645 auth |= (req->auth_req | rsp->auth_req) & SMP_AUTH_MITM;
646
647 ret = tk_request(conn, 0, auth, rsp->io_capability, req->io_capability);
648 if (ret)
649 return SMP_UNSPECIFIED;
650
651 set_bit(SMP_FLAG_CFM_PENDING, &smp->smp_flags);
652
653 /* Can't compose response until we have been confirmed */
654 if (!test_bit(SMP_FLAG_TK_VALID, &smp->smp_flags))
655 return 0;
656
Vinicius Costa Gomes8aab4752011-09-05 14:31:31 -0300657 queue_work(hdev->workqueue, &smp->confirm);
Vinicius Costa Gomesda85e5e2011-06-09 18:50:53 -0300658
659 return 0;
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300660}
661
Vinicius Costa Gomesda85e5e2011-06-09 18:50:53 -0300662static u8 smp_cmd_pairing_confirm(struct l2cap_conn *conn, struct sk_buff *skb)
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300663{
Vinicius Costa Gomes1c1def02011-09-05 14:31:30 -0300664 struct smp_chan *smp = conn->smp_chan;
Vinicius Costa Gomes8aab4752011-09-05 14:31:31 -0300665 struct hci_dev *hdev = conn->hcon->hdev;
Anderson Briglia7d24ddc2011-06-09 18:50:46 -0300666
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300667 BT_DBG("conn %p %s", conn, conn->hcon->out ? "master" : "slave");
668
Vinicius Costa Gomes1c1def02011-09-05 14:31:30 -0300669 memcpy(smp->pcnf, skb->data, sizeof(smp->pcnf));
670 skb_pull(skb, sizeof(smp->pcnf));
Anderson Briglia7d24ddc2011-06-09 18:50:46 -0300671
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300672 if (conn->hcon->out) {
Anderson Briglia7d24ddc2011-06-09 18:50:46 -0300673 u8 random[16];
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300674
Vinicius Costa Gomes1c1def02011-09-05 14:31:30 -0300675 swap128(smp->prnd, random);
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300676 smp_send_cmd(conn, SMP_CMD_PAIRING_RANDOM, sizeof(random),
Anderson Briglia7d24ddc2011-06-09 18:50:46 -0300677 random);
Brian Gix2b64d152011-12-21 16:12:12 -0800678 } else if (test_bit(SMP_FLAG_TK_VALID, &smp->smp_flags)) {
Vinicius Costa Gomes8aab4752011-09-05 14:31:31 -0300679 queue_work(hdev->workqueue, &smp->confirm);
Brian Gix2b64d152011-12-21 16:12:12 -0800680 } else {
681 set_bit(SMP_FLAG_CFM_PENDING, &smp->smp_flags);
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300682 }
Vinicius Costa Gomesda85e5e2011-06-09 18:50:53 -0300683
684 return 0;
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300685}
686
Vinicius Costa Gomesda85e5e2011-06-09 18:50:53 -0300687static u8 smp_cmd_pairing_random(struct l2cap_conn *conn, struct sk_buff *skb)
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300688{
Vinicius Costa Gomes1c1def02011-09-05 14:31:30 -0300689 struct smp_chan *smp = conn->smp_chan;
Vinicius Costa Gomes8aab4752011-09-05 14:31:31 -0300690 struct hci_dev *hdev = conn->hcon->hdev;
Anderson Briglia7d24ddc2011-06-09 18:50:46 -0300691
Vinicius Costa Gomes8aab4752011-09-05 14:31:31 -0300692 BT_DBG("conn %p", conn);
Anderson Briglia7d24ddc2011-06-09 18:50:46 -0300693
Vinicius Costa Gomes8aab4752011-09-05 14:31:31 -0300694 swap128(skb->data, smp->rrnd);
695 skb_pull(skb, sizeof(smp->rrnd));
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300696
Vinicius Costa Gomes8aab4752011-09-05 14:31:31 -0300697 queue_work(hdev->workqueue, &smp->random);
Vinicius Costa Gomesda85e5e2011-06-09 18:50:53 -0300698
699 return 0;
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300700}
701
Vinicius Costa Gomes988c5992011-08-25 20:02:28 -0300702static u8 smp_ltk_encrypt(struct l2cap_conn *conn)
703{
704 struct link_key *key;
705 struct key_master_id *master;
706 struct hci_conn *hcon = conn->hcon;
707
708 key = hci_find_link_key_type(hcon->hdev, conn->dst,
709 HCI_LK_SMP_LTK);
710 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
716 master = (void *) key->data;
717 hci_le_start_enc(hcon, master->ediv, master->rand,
718 key->val);
719 hcon->enc_key_size = key->pin_len;
720
721 return 1;
722
723}
Vinicius Costa Gomesda85e5e2011-06-09 18:50:53 -0300724static u8 smp_cmd_security_req(struct l2cap_conn *conn, struct sk_buff *skb)
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300725{
726 struct smp_cmd_security_req *rp = (void *) skb->data;
727 struct smp_cmd_pairing cp;
Vinicius Costa Gomesf1cb9af2011-01-26 21:42:57 -0300728 struct hci_conn *hcon = conn->hcon;
Vinicius Costa Gomes8aab4752011-09-05 14:31:31 -0300729 struct smp_chan *smp;
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300730
731 BT_DBG("conn %p", conn);
732
Brian Gix2b64d152011-12-21 16:12:12 -0800733 hcon->pending_sec_level = authreq_to_seclevel(rp->auth_req);
Vinicius Costa Gomesfeb45eb2011-08-25 20:02:35 -0300734
Vinicius Costa Gomes988c5992011-08-25 20:02:28 -0300735 if (smp_ltk_encrypt(conn))
736 return 0;
737
Johan Hedberg51a8efd2012-01-16 06:10:31 +0200738 if (test_and_set_bit(HCI_CONN_LE_SMP_PEND, &hcon->flags))
Vinicius Costa Gomesda85e5e2011-06-09 18:50:53 -0300739 return 0;
Vinicius Costa Gomesf1cb9af2011-01-26 21:42:57 -0300740
Vinicius Costa Gomes8aab4752011-09-05 14:31:31 -0300741 smp = smp_chan_create(conn);
Vinicius Costa Gomesd26a2342011-08-19 21:06:51 -0300742
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300743 skb_pull(skb, sizeof(*rp));
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300744
Vinicius Costa Gomesda85e5e2011-06-09 18:50:53 -0300745 memset(&cp, 0, sizeof(cp));
Vinicius Costa Gomes54790f72011-07-07 18:59:38 -0300746 build_pairing_cmd(conn, &cp, NULL, rp->auth_req);
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300747
Vinicius Costa Gomes1c1def02011-09-05 14:31:30 -0300748 smp->preq[0] = SMP_CMD_PAIRING_REQ;
749 memcpy(&smp->preq[1], &cp, sizeof(cp));
Anderson Brigliaf01ead32011-06-09 18:50:45 -0300750
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300751 smp_send_cmd(conn, SMP_CMD_PAIRING_REQ, sizeof(cp), &cp);
Vinicius Costa Gomesf1cb9af2011-01-26 21:42:57 -0300752
Vinicius Costa Gomesda85e5e2011-06-09 18:50:53 -0300753 return 0;
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300754}
755
Anderson Brigliaeb492e02011-06-09 18:50:40 -0300756int smp_conn_security(struct l2cap_conn *conn, __u8 sec_level)
757{
Vinicius Costa Gomes3a0259b2011-06-09 18:50:43 -0300758 struct hci_conn *hcon = conn->hcon;
Vinicius Costa Gomes1c1def02011-09-05 14:31:30 -0300759 struct smp_chan *smp = conn->smp_chan;
Brian Gix2b64d152011-12-21 16:12:12 -0800760 __u8 authreq;
Anderson Brigliaeb492e02011-06-09 18:50:40 -0300761
Vinicius Costa Gomes3a0259b2011-06-09 18:50:43 -0300762 BT_DBG("conn %p hcon %p level 0x%2.2x", conn, hcon, sec_level);
763
Andre Guedes2e65c9d2011-06-30 19:20:56 -0300764 if (!lmp_host_le_capable(hcon->hdev))
765 return 1;
766
Vinicius Costa Gomesf1cb9af2011-01-26 21:42:57 -0300767 if (sec_level == BT_SECURITY_LOW)
Anderson Brigliaeb492e02011-06-09 18:50:40 -0300768 return 1;
Vinicius Costa Gomesf1cb9af2011-01-26 21:42:57 -0300769
770 if (hcon->sec_level >= sec_level)
771 return 1;
772
Vinicius Costa Gomes988c5992011-08-25 20:02:28 -0300773 if (hcon->link_mode & HCI_LM_MASTER)
774 if (smp_ltk_encrypt(conn))
Vinicius Costa Gomes02bc7452011-07-07 18:59:41 -0300775 goto done;
Vinicius Costa Gomesd26a2342011-08-19 21:06:51 -0300776
Johan Hedberg51a8efd2012-01-16 06:10:31 +0200777 if (test_and_set_bit(HCI_CONN_LE_SMP_PEND, &hcon->flags))
Vinicius Costa Gomesd26a2342011-08-19 21:06:51 -0300778 return 0;
779
Vinicius Costa Gomes8aab4752011-09-05 14:31:31 -0300780 smp = smp_chan_create(conn);
Brian Gix2b64d152011-12-21 16:12:12 -0800781 if (!smp)
782 return 1;
783
784 authreq = seclevel_to_authreq(sec_level);
Vinicius Costa Gomesd26a2342011-08-19 21:06:51 -0300785
Vinicius Costa Gomesd26a2342011-08-19 21:06:51 -0300786 if (hcon->link_mode & HCI_LM_MASTER) {
787 struct smp_cmd_pairing cp;
Anderson Brigliaf01ead32011-06-09 18:50:45 -0300788
Brian Gix2b64d152011-12-21 16:12:12 -0800789 build_pairing_cmd(conn, &cp, NULL, authreq);
Vinicius Costa Gomes1c1def02011-09-05 14:31:30 -0300790 smp->preq[0] = SMP_CMD_PAIRING_REQ;
791 memcpy(&smp->preq[1], &cp, sizeof(cp));
Anderson Brigliaf01ead32011-06-09 18:50:45 -0300792
Anderson Brigliaeb492e02011-06-09 18:50:40 -0300793 smp_send_cmd(conn, SMP_CMD_PAIRING_REQ, sizeof(cp), &cp);
794 } else {
795 struct smp_cmd_security_req cp;
Brian Gix2b64d152011-12-21 16:12:12 -0800796 cp.auth_req = authreq;
Anderson Brigliaeb492e02011-06-09 18:50:40 -0300797 smp_send_cmd(conn, SMP_CMD_SECURITY_REQ, sizeof(cp), &cp);
798 }
799
Vinicius Costa Gomes02bc7452011-07-07 18:59:41 -0300800done:
Vinicius Costa Gomesf1cb9af2011-01-26 21:42:57 -0300801 hcon->pending_sec_level = sec_level;
Vinicius Costa Gomesf1cb9af2011-01-26 21:42:57 -0300802
Anderson Brigliaeb492e02011-06-09 18:50:40 -0300803 return 0;
804}
805
Vinicius Costa Gomes7034b912011-07-07 18:59:34 -0300806static int smp_cmd_encrypt_info(struct l2cap_conn *conn, struct sk_buff *skb)
807{
Vinicius Costa Gomes16b90832011-07-07 18:59:39 -0300808 struct smp_cmd_encrypt_info *rp = (void *) skb->data;
Vinicius Costa Gomes1c1def02011-09-05 14:31:30 -0300809 struct smp_chan *smp = conn->smp_chan;
Vinicius Costa Gomes16b90832011-07-07 18:59:39 -0300810
811 skb_pull(skb, sizeof(*rp));
812
Vinicius Costa Gomes1c1def02011-09-05 14:31:30 -0300813 memcpy(smp->tk, rp->ltk, sizeof(smp->tk));
Vinicius Costa Gomes16b90832011-07-07 18:59:39 -0300814
Vinicius Costa Gomes7034b912011-07-07 18:59:34 -0300815 return 0;
816}
817
818static int smp_cmd_master_ident(struct l2cap_conn *conn, struct sk_buff *skb)
819{
Vinicius Costa Gomes16b90832011-07-07 18:59:39 -0300820 struct smp_cmd_master_ident *rp = (void *) skb->data;
Vinicius Costa Gomes1c1def02011-09-05 14:31:30 -0300821 struct smp_chan *smp = conn->smp_chan;
Vinicius Costa Gomes7034b912011-07-07 18:59:34 -0300822
Vinicius Costa Gomes16b90832011-07-07 18:59:39 -0300823 skb_pull(skb, sizeof(*rp));
824
Vinicius Costa Gomesf7aa6112012-01-30 19:29:12 -0300825 hci_add_ltk(conn->hcon->hdev, 1, conn->dst, smp->enc_key_size,
Vinicius Costa Gomes1c1def02011-09-05 14:31:30 -0300826 rp->ediv, rp->rand, smp->tk);
Vinicius Costa Gomes7034b912011-07-07 18:59:34 -0300827
828 smp_distribute_keys(conn, 1);
829
830 return 0;
831}
832
Anderson Brigliaeb492e02011-06-09 18:50:40 -0300833int smp_sig_channel(struct l2cap_conn *conn, struct sk_buff *skb)
834{
835 __u8 code = skb->data[0];
836 __u8 reason;
837 int err = 0;
838
Andre Guedes2e65c9d2011-06-30 19:20:56 -0300839 if (!lmp_host_le_capable(conn->hcon->hdev)) {
840 err = -ENOTSUPP;
841 reason = SMP_PAIRING_NOTSUPP;
842 goto done;
843 }
844
Anderson Brigliaeb492e02011-06-09 18:50:40 -0300845 skb_pull(skb, sizeof(code));
846
847 switch (code) {
848 case SMP_CMD_PAIRING_REQ:
Vinicius Costa Gomesda85e5e2011-06-09 18:50:53 -0300849 reason = smp_cmd_pairing_req(conn, skb);
Anderson Brigliaeb492e02011-06-09 18:50:40 -0300850 break;
851
852 case SMP_CMD_PAIRING_FAIL:
Brian Gix4f957a72011-11-23 08:28:36 -0800853 smp_failure(conn, skb->data[0], 0);
Vinicius Costa Gomesda85e5e2011-06-09 18:50:53 -0300854 reason = 0;
855 err = -EPERM;
Anderson Brigliaeb492e02011-06-09 18:50:40 -0300856 break;
857
858 case SMP_CMD_PAIRING_RSP:
Vinicius Costa Gomesda85e5e2011-06-09 18:50:53 -0300859 reason = smp_cmd_pairing_rsp(conn, skb);
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300860 break;
861
862 case SMP_CMD_SECURITY_REQ:
Vinicius Costa Gomesda85e5e2011-06-09 18:50:53 -0300863 reason = smp_cmd_security_req(conn, skb);
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300864 break;
865
Anderson Brigliaeb492e02011-06-09 18:50:40 -0300866 case SMP_CMD_PAIRING_CONFIRM:
Vinicius Costa Gomesda85e5e2011-06-09 18:50:53 -0300867 reason = smp_cmd_pairing_confirm(conn, skb);
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300868 break;
869
Anderson Brigliaeb492e02011-06-09 18:50:40 -0300870 case SMP_CMD_PAIRING_RANDOM:
Vinicius Costa Gomesda85e5e2011-06-09 18:50:53 -0300871 reason = smp_cmd_pairing_random(conn, skb);
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300872 break;
873
Anderson Brigliaeb492e02011-06-09 18:50:40 -0300874 case SMP_CMD_ENCRYPT_INFO:
Vinicius Costa Gomes7034b912011-07-07 18:59:34 -0300875 reason = smp_cmd_encrypt_info(conn, skb);
876 break;
877
Anderson Brigliaeb492e02011-06-09 18:50:40 -0300878 case SMP_CMD_MASTER_IDENT:
Vinicius Costa Gomes7034b912011-07-07 18:59:34 -0300879 reason = smp_cmd_master_ident(conn, skb);
880 break;
881
Anderson Brigliaeb492e02011-06-09 18:50:40 -0300882 case SMP_CMD_IDENT_INFO:
883 case SMP_CMD_IDENT_ADDR_INFO:
884 case SMP_CMD_SIGN_INFO:
Vinicius Costa Gomes7034b912011-07-07 18:59:34 -0300885 /* Just ignored */
886 reason = 0;
887 break;
888
Anderson Brigliaeb492e02011-06-09 18:50:40 -0300889 default:
890 BT_DBG("Unknown command code 0x%2.2x", code);
891
892 reason = SMP_CMD_NOTSUPP;
Vinicius Costa Gomes3a0259b2011-06-09 18:50:43 -0300893 err = -EOPNOTSUPP;
894 goto done;
895 }
896
897done:
898 if (reason)
Brian Gix4f957a72011-11-23 08:28:36 -0800899 smp_failure(conn, reason, 1);
Anderson Brigliaeb492e02011-06-09 18:50:40 -0300900
901 kfree_skb(skb);
902 return err;
903}
Vinicius Costa Gomes7034b912011-07-07 18:59:34 -0300904
905int smp_distribute_keys(struct l2cap_conn *conn, __u8 force)
906{
907 struct smp_cmd_pairing *req, *rsp;
Vinicius Costa Gomes1c1def02011-09-05 14:31:30 -0300908 struct smp_chan *smp = conn->smp_chan;
Vinicius Costa Gomes7034b912011-07-07 18:59:34 -0300909 __u8 *keydist;
910
911 BT_DBG("conn %p force %d", conn, force);
912
Johan Hedberg51a8efd2012-01-16 06:10:31 +0200913 if (!test_bit(HCI_CONN_LE_SMP_PEND, &conn->hcon->flags))
Vinicius Costa Gomesd26a2342011-08-19 21:06:51 -0300914 return 0;
915
Vinicius Costa Gomes1c1def02011-09-05 14:31:30 -0300916 rsp = (void *) &smp->prsp[1];
Vinicius Costa Gomes7034b912011-07-07 18:59:34 -0300917
918 /* The responder sends its keys first */
919 if (!force && conn->hcon->out && (rsp->resp_key_dist & 0x07))
920 return 0;
921
Vinicius Costa Gomes1c1def02011-09-05 14:31:30 -0300922 req = (void *) &smp->preq[1];
Vinicius Costa Gomes7034b912011-07-07 18:59:34 -0300923
924 if (conn->hcon->out) {
925 keydist = &rsp->init_key_dist;
926 *keydist &= req->init_key_dist;
927 } else {
928 keydist = &rsp->resp_key_dist;
929 *keydist &= req->resp_key_dist;
930 }
931
932
933 BT_DBG("keydist 0x%x", *keydist);
934
935 if (*keydist & SMP_DIST_ENC_KEY) {
936 struct smp_cmd_encrypt_info enc;
937 struct smp_cmd_master_ident ident;
938 __le16 ediv;
939
940 get_random_bytes(enc.ltk, sizeof(enc.ltk));
941 get_random_bytes(&ediv, sizeof(ediv));
942 get_random_bytes(ident.rand, sizeof(ident.rand));
943
944 smp_send_cmd(conn, SMP_CMD_ENCRYPT_INFO, sizeof(enc), &enc);
945
Vinicius Costa Gomesf7aa6112012-01-30 19:29:12 -0300946 hci_add_ltk(conn->hcon->hdev, 1, conn->dst, smp->enc_key_size,
Vinicius Costa Gomes726b4ff2011-07-08 18:31:45 -0300947 ediv, ident.rand, enc.ltk);
Vinicius Costa Gomes16b90832011-07-07 18:59:39 -0300948
Vinicius Costa Gomes7034b912011-07-07 18:59:34 -0300949 ident.ediv = cpu_to_le16(ediv);
950
951 smp_send_cmd(conn, SMP_CMD_MASTER_IDENT, sizeof(ident), &ident);
952
953 *keydist &= ~SMP_DIST_ENC_KEY;
954 }
955
956 if (*keydist & SMP_DIST_ID_KEY) {
957 struct smp_cmd_ident_addr_info addrinfo;
958 struct smp_cmd_ident_info idinfo;
959
960 /* Send a dummy key */
961 get_random_bytes(idinfo.irk, sizeof(idinfo.irk));
962
963 smp_send_cmd(conn, SMP_CMD_IDENT_INFO, sizeof(idinfo), &idinfo);
964
965 /* Just public address */
966 memset(&addrinfo, 0, sizeof(addrinfo));
967 bacpy(&addrinfo.bdaddr, conn->src);
968
969 smp_send_cmd(conn, SMP_CMD_IDENT_ADDR_INFO, sizeof(addrinfo),
970 &addrinfo);
971
972 *keydist &= ~SMP_DIST_ID_KEY;
973 }
974
975 if (*keydist & SMP_DIST_SIGN) {
976 struct smp_cmd_sign_info sign;
977
978 /* Send a dummy key */
979 get_random_bytes(sign.csrk, sizeof(sign.csrk));
980
981 smp_send_cmd(conn, SMP_CMD_SIGN_INFO, sizeof(sign), &sign);
982
983 *keydist &= ~SMP_DIST_SIGN;
984 }
985
Vinicius Costa Gomesd26a2342011-08-19 21:06:51 -0300986 if (conn->hcon->out || force) {
Johan Hedberg51a8efd2012-01-16 06:10:31 +0200987 clear_bit(HCI_CONN_LE_SMP_PEND, &conn->hcon->flags);
Gustavo F. Padovan6c9d42a2011-12-20 10:57:27 -0200988 cancel_delayed_work_sync(&conn->security_timer);
Vinicius Costa Gomes8aab4752011-09-05 14:31:31 -0300989 smp_chan_destroy(conn);
Vinicius Costa Gomesd26a2342011-08-19 21:06:51 -0300990 }
991
Vinicius Costa Gomes7034b912011-07-07 18:59:34 -0300992 return 0;
993}