blob: 0563f737779a2df6a1e99afe3c08130b8fd832bd [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 Gomesc9839a12012-02-02 21:08:01 -0300478 hci_add_ltk(hcon->hdev, conn->dst, hcon->dst_type,
479 HCI_SMP_STK_SLAVE, 0, 0, stk,
480 smp->enc_key_size, ediv, rand);
Vinicius Costa Gomes8aab4752011-09-05 14:31:31 -0300481 }
482
483 return;
484
485error:
Brian Gix4f957a72011-11-23 08:28:36 -0800486 smp_failure(conn, reason, 1);
Vinicius Costa Gomes8aab4752011-09-05 14:31:31 -0300487}
488
489static struct smp_chan *smp_chan_create(struct l2cap_conn *conn)
490{
491 struct smp_chan *smp;
492
493 smp = kzalloc(sizeof(struct smp_chan), GFP_ATOMIC);
494 if (!smp)
495 return NULL;
496
497 INIT_WORK(&smp->confirm, confirm_work);
498 INIT_WORK(&smp->random, random_work);
499
500 smp->conn = conn;
501 conn->smp_chan = smp;
Brian Gix2b64d152011-12-21 16:12:12 -0800502 conn->hcon->smp_conn = conn;
Vinicius Costa Gomes8aab4752011-09-05 14:31:31 -0300503
504 hci_conn_hold(conn->hcon);
505
506 return smp;
507}
508
509void smp_chan_destroy(struct l2cap_conn *conn)
510{
Brian Gixc8eb9692011-11-23 08:28:35 -0800511 struct smp_chan *smp = conn->smp_chan;
512
Vinicius Costa Gomesf1c09c02012-02-01 18:27:56 -0300513 BUG_ON(!smp);
Brian Gixc8eb9692011-11-23 08:28:35 -0800514
515 if (smp->tfm)
516 crypto_free_blkcipher(smp->tfm);
517
518 kfree(smp);
519 conn->smp_chan = NULL;
Brian Gix2b64d152011-12-21 16:12:12 -0800520 conn->hcon->smp_conn = NULL;
Vinicius Costa Gomes8aab4752011-09-05 14:31:31 -0300521 hci_conn_put(conn->hcon);
522}
523
Brian Gix2b64d152011-12-21 16:12:12 -0800524int smp_user_confirm_reply(struct hci_conn *hcon, u16 mgmt_op, __le32 passkey)
525{
526 struct l2cap_conn *conn = hcon->smp_conn;
527 struct smp_chan *smp;
528 u32 value;
529 u8 key[16];
530
531 BT_DBG("");
532
533 if (!conn)
534 return -ENOTCONN;
535
536 smp = conn->smp_chan;
537
538 switch (mgmt_op) {
539 case MGMT_OP_USER_PASSKEY_REPLY:
540 value = le32_to_cpu(passkey);
541 memset(key, 0, sizeof(key));
542 BT_DBG("PassKey: %d", value);
543 put_unaligned_le32(value, key);
544 swap128(key, smp->tk);
545 /* Fall Through */
546 case MGMT_OP_USER_CONFIRM_REPLY:
547 set_bit(SMP_FLAG_TK_VALID, &smp->smp_flags);
548 break;
549 case MGMT_OP_USER_PASSKEY_NEG_REPLY:
550 case MGMT_OP_USER_CONFIRM_NEG_REPLY:
551 smp_failure(conn, SMP_PASSKEY_ENTRY_FAILED, 1);
552 return 0;
553 default:
554 smp_failure(conn, SMP_PASSKEY_ENTRY_FAILED, 1);
555 return -EOPNOTSUPP;
556 }
557
558 /* If it is our turn to send Pairing Confirm, do so now */
559 if (test_bit(SMP_FLAG_CFM_PENDING, &smp->smp_flags))
560 queue_work(hcon->hdev->workqueue, &smp->confirm);
561
562 return 0;
563}
564
Vinicius Costa Gomesda85e5e2011-06-09 18:50:53 -0300565static u8 smp_cmd_pairing_req(struct l2cap_conn *conn, struct sk_buff *skb)
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300566{
Vinicius Costa Gomes3158c502011-06-14 13:37:42 -0300567 struct smp_cmd_pairing rsp, *req = (void *) skb->data;
Vinicius Costa Gomes8aab4752011-09-05 14:31:31 -0300568 struct smp_chan *smp;
Vinicius Costa Gomes3158c502011-06-14 13:37:42 -0300569 u8 key_size;
Brian Gix2b64d152011-12-21 16:12:12 -0800570 u8 auth = SMP_AUTH_NONE;
Vinicius Costa Gomes8aab4752011-09-05 14:31:31 -0300571 int ret;
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300572
573 BT_DBG("conn %p", conn);
574
Brian Gix2b64d152011-12-21 16:12:12 -0800575 if (conn->hcon->link_mode & HCI_LM_MASTER)
576 return SMP_CMD_NOTSUPP;
577
Johan Hedberg51a8efd2012-01-16 06:10:31 +0200578 if (!test_and_set_bit(HCI_CONN_LE_SMP_PEND, &conn->hcon->flags))
Vinicius Costa Gomes8aab4752011-09-05 14:31:31 -0300579 smp = smp_chan_create(conn);
580
581 smp = conn->smp_chan;
Vinicius Costa Gomesd26a2342011-08-19 21:06:51 -0300582
Vinicius Costa Gomes1c1def02011-09-05 14:31:30 -0300583 smp->preq[0] = SMP_CMD_PAIRING_REQ;
584 memcpy(&smp->preq[1], req, sizeof(*req));
Vinicius Costa Gomes3158c502011-06-14 13:37:42 -0300585 skb_pull(skb, sizeof(*req));
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300586
Brian Gix2b64d152011-12-21 16:12:12 -0800587 /* We didn't start the pairing, so match remote */
588 if (req->auth_req & SMP_AUTH_BONDING)
589 auth = req->auth_req;
Vinicius Costa Gomesda85e5e2011-06-09 18:50:53 -0300590
Brian Gix2b64d152011-12-21 16:12:12 -0800591 build_pairing_cmd(conn, req, &rsp, auth);
Vinicius Costa Gomes3158c502011-06-14 13:37:42 -0300592
593 key_size = min(req->max_key_size, rsp.max_key_size);
594 if (check_enc_key_size(conn, key_size))
595 return SMP_ENC_KEY_SIZE;
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300596
Vinicius Costa Gomes8aab4752011-09-05 14:31:31 -0300597 ret = smp_rand(smp->prnd);
598 if (ret)
599 return SMP_UNSPECIFIED;
600
Vinicius Costa Gomes1c1def02011-09-05 14:31:30 -0300601 smp->prsp[0] = SMP_CMD_PAIRING_RSP;
602 memcpy(&smp->prsp[1], &rsp, sizeof(rsp));
Anderson Brigliaf01ead32011-06-09 18:50:45 -0300603
Vinicius Costa Gomes3158c502011-06-14 13:37:42 -0300604 smp_send_cmd(conn, SMP_CMD_PAIRING_RSP, sizeof(rsp), &rsp);
Vinicius Costa Gomesda85e5e2011-06-09 18:50:53 -0300605
Brian Gix2b64d152011-12-21 16:12:12 -0800606 /* Request setup of TK */
607 ret = tk_request(conn, 0, auth, rsp.io_capability, req->io_capability);
608 if (ret)
609 return SMP_UNSPECIFIED;
610
Vinicius Costa Gomesda85e5e2011-06-09 18:50:53 -0300611 return 0;
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300612}
613
Vinicius Costa Gomesda85e5e2011-06-09 18:50:53 -0300614static u8 smp_cmd_pairing_rsp(struct l2cap_conn *conn, struct sk_buff *skb)
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300615{
Vinicius Costa Gomes3158c502011-06-14 13:37:42 -0300616 struct smp_cmd_pairing *req, *rsp = (void *) skb->data;
Vinicius Costa Gomes1c1def02011-09-05 14:31:30 -0300617 struct smp_chan *smp = conn->smp_chan;
Vinicius Costa Gomes8aab4752011-09-05 14:31:31 -0300618 struct hci_dev *hdev = conn->hcon->hdev;
Brian Gix2b64d152011-12-21 16:12:12 -0800619 u8 key_size, auth = SMP_AUTH_NONE;
Anderson Briglia7d24ddc2011-06-09 18:50:46 -0300620 int ret;
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300621
622 BT_DBG("conn %p", conn);
623
Brian Gix2b64d152011-12-21 16:12:12 -0800624 if (!(conn->hcon->link_mode & HCI_LM_MASTER))
625 return SMP_CMD_NOTSUPP;
626
Vinicius Costa Gomes3158c502011-06-14 13:37:42 -0300627 skb_pull(skb, sizeof(*rsp));
Vinicius Costa Gomesda85e5e2011-06-09 18:50:53 -0300628
Vinicius Costa Gomes1c1def02011-09-05 14:31:30 -0300629 req = (void *) &smp->preq[1];
Vinicius Costa Gomes3158c502011-06-14 13:37:42 -0300630
631 key_size = min(req->max_key_size, rsp->max_key_size);
632 if (check_enc_key_size(conn, key_size))
633 return SMP_ENC_KEY_SIZE;
634
Vinicius Costa Gomes1c1def02011-09-05 14:31:30 -0300635 ret = smp_rand(smp->prnd);
Anderson Briglia7d24ddc2011-06-09 18:50:46 -0300636 if (ret)
Vinicius Costa Gomesda85e5e2011-06-09 18:50:53 -0300637 return SMP_UNSPECIFIED;
Anderson Briglia7d24ddc2011-06-09 18:50:46 -0300638
Vinicius Costa Gomes8aab4752011-09-05 14:31:31 -0300639 smp->prsp[0] = SMP_CMD_PAIRING_RSP;
640 memcpy(&smp->prsp[1], rsp, sizeof(*rsp));
Anderson Briglia7d24ddc2011-06-09 18:50:46 -0300641
Brian Gix2b64d152011-12-21 16:12:12 -0800642 if ((req->auth_req & SMP_AUTH_BONDING) &&
643 (rsp->auth_req & SMP_AUTH_BONDING))
644 auth = SMP_AUTH_BONDING;
645
646 auth |= (req->auth_req | rsp->auth_req) & SMP_AUTH_MITM;
647
648 ret = tk_request(conn, 0, auth, rsp->io_capability, req->io_capability);
649 if (ret)
650 return SMP_UNSPECIFIED;
651
652 set_bit(SMP_FLAG_CFM_PENDING, &smp->smp_flags);
653
654 /* Can't compose response until we have been confirmed */
655 if (!test_bit(SMP_FLAG_TK_VALID, &smp->smp_flags))
656 return 0;
657
Vinicius Costa Gomes8aab4752011-09-05 14:31:31 -0300658 queue_work(hdev->workqueue, &smp->confirm);
Vinicius Costa Gomesda85e5e2011-06-09 18:50:53 -0300659
660 return 0;
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300661}
662
Vinicius Costa Gomesda85e5e2011-06-09 18:50:53 -0300663static u8 smp_cmd_pairing_confirm(struct l2cap_conn *conn, struct sk_buff *skb)
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300664{
Vinicius Costa Gomes1c1def02011-09-05 14:31:30 -0300665 struct smp_chan *smp = conn->smp_chan;
Vinicius Costa Gomes8aab4752011-09-05 14:31:31 -0300666 struct hci_dev *hdev = conn->hcon->hdev;
Anderson Briglia7d24ddc2011-06-09 18:50:46 -0300667
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300668 BT_DBG("conn %p %s", conn, conn->hcon->out ? "master" : "slave");
669
Vinicius Costa Gomes1c1def02011-09-05 14:31:30 -0300670 memcpy(smp->pcnf, skb->data, sizeof(smp->pcnf));
671 skb_pull(skb, sizeof(smp->pcnf));
Anderson Briglia7d24ddc2011-06-09 18:50:46 -0300672
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300673 if (conn->hcon->out) {
Anderson Briglia7d24ddc2011-06-09 18:50:46 -0300674 u8 random[16];
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300675
Vinicius Costa Gomes1c1def02011-09-05 14:31:30 -0300676 swap128(smp->prnd, random);
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300677 smp_send_cmd(conn, SMP_CMD_PAIRING_RANDOM, sizeof(random),
Anderson Briglia7d24ddc2011-06-09 18:50:46 -0300678 random);
Brian Gix2b64d152011-12-21 16:12:12 -0800679 } else if (test_bit(SMP_FLAG_TK_VALID, &smp->smp_flags)) {
Vinicius Costa Gomes8aab4752011-09-05 14:31:31 -0300680 queue_work(hdev->workqueue, &smp->confirm);
Brian Gix2b64d152011-12-21 16:12:12 -0800681 } else {
682 set_bit(SMP_FLAG_CFM_PENDING, &smp->smp_flags);
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300683 }
Vinicius Costa Gomesda85e5e2011-06-09 18:50:53 -0300684
685 return 0;
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300686}
687
Vinicius Costa Gomesda85e5e2011-06-09 18:50:53 -0300688static u8 smp_cmd_pairing_random(struct l2cap_conn *conn, struct sk_buff *skb)
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300689{
Vinicius Costa Gomes1c1def02011-09-05 14:31:30 -0300690 struct smp_chan *smp = conn->smp_chan;
Vinicius Costa Gomes8aab4752011-09-05 14:31:31 -0300691 struct hci_dev *hdev = conn->hcon->hdev;
Anderson Briglia7d24ddc2011-06-09 18:50:46 -0300692
Vinicius Costa Gomes8aab4752011-09-05 14:31:31 -0300693 BT_DBG("conn %p", conn);
Anderson Briglia7d24ddc2011-06-09 18:50:46 -0300694
Vinicius Costa Gomes8aab4752011-09-05 14:31:31 -0300695 swap128(skb->data, smp->rrnd);
696 skb_pull(skb, sizeof(smp->rrnd));
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300697
Vinicius Costa Gomes8aab4752011-09-05 14:31:31 -0300698 queue_work(hdev->workqueue, &smp->random);
Vinicius Costa Gomesda85e5e2011-06-09 18:50:53 -0300699
700 return 0;
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300701}
702
Vinicius Costa Gomes988c5992011-08-25 20:02:28 -0300703static u8 smp_ltk_encrypt(struct l2cap_conn *conn)
704{
Vinicius Costa Gomesc9839a12012-02-02 21:08:01 -0300705 struct smp_ltk *key;
Vinicius Costa Gomes988c5992011-08-25 20:02:28 -0300706 struct hci_conn *hcon = conn->hcon;
707
Vinicius Costa Gomesc9839a12012-02-02 21:08:01 -0300708 key = hci_find_ltk_by_addr(hcon->hdev, conn->dst, hcon->dst_type);
Vinicius Costa Gomes988c5992011-08-25 20:02:28 -0300709 if (!key)
710 return 0;
711
Johan Hedberg51a8efd2012-01-16 06:10:31 +0200712 if (test_and_set_bit(HCI_CONN_ENCRYPT_PEND, &hcon->flags))
Vinicius Costa Gomes988c5992011-08-25 20:02:28 -0300713 return 1;
714
Vinicius Costa Gomesc9839a12012-02-02 21:08:01 -0300715 hci_le_start_enc(hcon, key->ediv, key->rand, key->val);
716 hcon->enc_key_size = key->enc_size;
Vinicius Costa Gomes988c5992011-08-25 20:02:28 -0300717
718 return 1;
719
720}
Vinicius Costa Gomesda85e5e2011-06-09 18:50:53 -0300721static u8 smp_cmd_security_req(struct l2cap_conn *conn, struct sk_buff *skb)
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300722{
723 struct smp_cmd_security_req *rp = (void *) skb->data;
724 struct smp_cmd_pairing cp;
Vinicius Costa Gomesf1cb9af2011-01-26 21:42:57 -0300725 struct hci_conn *hcon = conn->hcon;
Vinicius Costa Gomes8aab4752011-09-05 14:31:31 -0300726 struct smp_chan *smp;
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300727
728 BT_DBG("conn %p", conn);
729
Brian Gix2b64d152011-12-21 16:12:12 -0800730 hcon->pending_sec_level = authreq_to_seclevel(rp->auth_req);
Vinicius Costa Gomesfeb45eb2011-08-25 20:02:35 -0300731
Vinicius Costa Gomes988c5992011-08-25 20:02:28 -0300732 if (smp_ltk_encrypt(conn))
733 return 0;
734
Johan Hedberg51a8efd2012-01-16 06:10:31 +0200735 if (test_and_set_bit(HCI_CONN_LE_SMP_PEND, &hcon->flags))
Vinicius Costa Gomesda85e5e2011-06-09 18:50:53 -0300736 return 0;
Vinicius Costa Gomesf1cb9af2011-01-26 21:42:57 -0300737
Vinicius Costa Gomes8aab4752011-09-05 14:31:31 -0300738 smp = smp_chan_create(conn);
Vinicius Costa Gomesd26a2342011-08-19 21:06:51 -0300739
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300740 skb_pull(skb, sizeof(*rp));
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300741
Vinicius Costa Gomesda85e5e2011-06-09 18:50:53 -0300742 memset(&cp, 0, sizeof(cp));
Vinicius Costa Gomes54790f72011-07-07 18:59:38 -0300743 build_pairing_cmd(conn, &cp, NULL, rp->auth_req);
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300744
Vinicius Costa Gomes1c1def02011-09-05 14:31:30 -0300745 smp->preq[0] = SMP_CMD_PAIRING_REQ;
746 memcpy(&smp->preq[1], &cp, sizeof(cp));
Anderson Brigliaf01ead32011-06-09 18:50:45 -0300747
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300748 smp_send_cmd(conn, SMP_CMD_PAIRING_REQ, sizeof(cp), &cp);
Vinicius Costa Gomesf1cb9af2011-01-26 21:42:57 -0300749
Vinicius Costa Gomesda85e5e2011-06-09 18:50:53 -0300750 return 0;
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300751}
752
Anderson Brigliaeb492e02011-06-09 18:50:40 -0300753int smp_conn_security(struct l2cap_conn *conn, __u8 sec_level)
754{
Vinicius Costa Gomes3a0259b2011-06-09 18:50:43 -0300755 struct hci_conn *hcon = conn->hcon;
Vinicius Costa Gomes1c1def02011-09-05 14:31:30 -0300756 struct smp_chan *smp = conn->smp_chan;
Brian Gix2b64d152011-12-21 16:12:12 -0800757 __u8 authreq;
Anderson Brigliaeb492e02011-06-09 18:50:40 -0300758
Vinicius Costa Gomes3a0259b2011-06-09 18:50:43 -0300759 BT_DBG("conn %p hcon %p level 0x%2.2x", conn, hcon, sec_level);
760
Andre Guedes2e65c9d2011-06-30 19:20:56 -0300761 if (!lmp_host_le_capable(hcon->hdev))
762 return 1;
763
Vinicius Costa Gomesf1cb9af2011-01-26 21:42:57 -0300764 if (sec_level == BT_SECURITY_LOW)
Anderson Brigliaeb492e02011-06-09 18:50:40 -0300765 return 1;
Vinicius Costa Gomesf1cb9af2011-01-26 21:42:57 -0300766
767 if (hcon->sec_level >= sec_level)
768 return 1;
769
Vinicius Costa Gomes988c5992011-08-25 20:02:28 -0300770 if (hcon->link_mode & HCI_LM_MASTER)
771 if (smp_ltk_encrypt(conn))
Vinicius Costa Gomes02bc7452011-07-07 18:59:41 -0300772 goto done;
Vinicius Costa Gomesd26a2342011-08-19 21:06:51 -0300773
Johan Hedberg51a8efd2012-01-16 06:10:31 +0200774 if (test_and_set_bit(HCI_CONN_LE_SMP_PEND, &hcon->flags))
Vinicius Costa Gomesd26a2342011-08-19 21:06:51 -0300775 return 0;
776
Vinicius Costa Gomes8aab4752011-09-05 14:31:31 -0300777 smp = smp_chan_create(conn);
Brian Gix2b64d152011-12-21 16:12:12 -0800778 if (!smp)
779 return 1;
780
781 authreq = seclevel_to_authreq(sec_level);
Vinicius Costa Gomesd26a2342011-08-19 21:06:51 -0300782
Vinicius Costa Gomesd26a2342011-08-19 21:06:51 -0300783 if (hcon->link_mode & HCI_LM_MASTER) {
784 struct smp_cmd_pairing cp;
Anderson Brigliaf01ead32011-06-09 18:50:45 -0300785
Brian Gix2b64d152011-12-21 16:12:12 -0800786 build_pairing_cmd(conn, &cp, NULL, authreq);
Vinicius Costa Gomes1c1def02011-09-05 14:31:30 -0300787 smp->preq[0] = SMP_CMD_PAIRING_REQ;
788 memcpy(&smp->preq[1], &cp, sizeof(cp));
Anderson Brigliaf01ead32011-06-09 18:50:45 -0300789
Anderson Brigliaeb492e02011-06-09 18:50:40 -0300790 smp_send_cmd(conn, SMP_CMD_PAIRING_REQ, sizeof(cp), &cp);
791 } else {
792 struct smp_cmd_security_req cp;
Brian Gix2b64d152011-12-21 16:12:12 -0800793 cp.auth_req = authreq;
Anderson Brigliaeb492e02011-06-09 18:50:40 -0300794 smp_send_cmd(conn, SMP_CMD_SECURITY_REQ, sizeof(cp), &cp);
795 }
796
Vinicius Costa Gomes02bc7452011-07-07 18:59:41 -0300797done:
Vinicius Costa Gomesf1cb9af2011-01-26 21:42:57 -0300798 hcon->pending_sec_level = sec_level;
Vinicius Costa Gomesf1cb9af2011-01-26 21:42:57 -0300799
Anderson Brigliaeb492e02011-06-09 18:50:40 -0300800 return 0;
801}
802
Vinicius Costa Gomes7034b912011-07-07 18:59:34 -0300803static int smp_cmd_encrypt_info(struct l2cap_conn *conn, struct sk_buff *skb)
804{
Vinicius Costa Gomes16b90832011-07-07 18:59:39 -0300805 struct smp_cmd_encrypt_info *rp = (void *) skb->data;
Vinicius Costa Gomes1c1def02011-09-05 14:31:30 -0300806 struct smp_chan *smp = conn->smp_chan;
Vinicius Costa Gomes16b90832011-07-07 18:59:39 -0300807
808 skb_pull(skb, sizeof(*rp));
809
Vinicius Costa Gomes1c1def02011-09-05 14:31:30 -0300810 memcpy(smp->tk, rp->ltk, sizeof(smp->tk));
Vinicius Costa Gomes16b90832011-07-07 18:59:39 -0300811
Vinicius Costa Gomes7034b912011-07-07 18:59:34 -0300812 return 0;
813}
814
815static int smp_cmd_master_ident(struct l2cap_conn *conn, struct sk_buff *skb)
816{
Vinicius Costa Gomes16b90832011-07-07 18:59:39 -0300817 struct smp_cmd_master_ident *rp = (void *) skb->data;
Vinicius Costa Gomes1c1def02011-09-05 14:31:30 -0300818 struct smp_chan *smp = conn->smp_chan;
Vinicius Costa Gomesc9839a12012-02-02 21:08:01 -0300819 struct hci_dev *hdev = conn->hcon->hdev;
820 struct hci_conn *hcon = conn->hcon;
821 u8 authenticated;
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 Gomesc9839a12012-02-02 21:08:01 -0300825 hci_dev_lock(hdev);
826 authenticated = (conn->hcon->sec_level == BT_SECURITY_HIGH);
827 hci_add_ltk(conn->hcon->hdev, conn->dst, hcon->dst_type,
828 HCI_SMP_LTK, 1, authenticated, smp->tk,
829 smp->enc_key_size, rp->ediv, rp->rand);
Vinicius Costa Gomes7034b912011-07-07 18:59:34 -0300830 smp_distribute_keys(conn, 1);
Vinicius Costa Gomesc9839a12012-02-02 21:08:01 -0300831 hci_dev_unlock(hdev);
Vinicius Costa Gomes7034b912011-07-07 18:59:34 -0300832
833 return 0;
834}
835
Anderson Brigliaeb492e02011-06-09 18:50:40 -0300836int smp_sig_channel(struct l2cap_conn *conn, struct sk_buff *skb)
837{
838 __u8 code = skb->data[0];
839 __u8 reason;
840 int err = 0;
841
Andre Guedes2e65c9d2011-06-30 19:20:56 -0300842 if (!lmp_host_le_capable(conn->hcon->hdev)) {
843 err = -ENOTSUPP;
844 reason = SMP_PAIRING_NOTSUPP;
845 goto done;
846 }
847
Anderson Brigliaeb492e02011-06-09 18:50:40 -0300848 skb_pull(skb, sizeof(code));
849
850 switch (code) {
851 case SMP_CMD_PAIRING_REQ:
Vinicius Costa Gomesda85e5e2011-06-09 18:50:53 -0300852 reason = smp_cmd_pairing_req(conn, skb);
Anderson Brigliaeb492e02011-06-09 18:50:40 -0300853 break;
854
855 case SMP_CMD_PAIRING_FAIL:
Brian Gix4f957a72011-11-23 08:28:36 -0800856 smp_failure(conn, skb->data[0], 0);
Vinicius Costa Gomesda85e5e2011-06-09 18:50:53 -0300857 reason = 0;
858 err = -EPERM;
Anderson Brigliaeb492e02011-06-09 18:50:40 -0300859 break;
860
861 case SMP_CMD_PAIRING_RSP:
Vinicius Costa Gomesda85e5e2011-06-09 18:50:53 -0300862 reason = smp_cmd_pairing_rsp(conn, skb);
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300863 break;
864
865 case SMP_CMD_SECURITY_REQ:
Vinicius Costa Gomesda85e5e2011-06-09 18:50:53 -0300866 reason = smp_cmd_security_req(conn, skb);
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300867 break;
868
Anderson Brigliaeb492e02011-06-09 18:50:40 -0300869 case SMP_CMD_PAIRING_CONFIRM:
Vinicius Costa Gomesda85e5e2011-06-09 18:50:53 -0300870 reason = smp_cmd_pairing_confirm(conn, skb);
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300871 break;
872
Anderson Brigliaeb492e02011-06-09 18:50:40 -0300873 case SMP_CMD_PAIRING_RANDOM:
Vinicius Costa Gomesda85e5e2011-06-09 18:50:53 -0300874 reason = smp_cmd_pairing_random(conn, skb);
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300875 break;
876
Anderson Brigliaeb492e02011-06-09 18:50:40 -0300877 case SMP_CMD_ENCRYPT_INFO:
Vinicius Costa Gomes7034b912011-07-07 18:59:34 -0300878 reason = smp_cmd_encrypt_info(conn, skb);
879 break;
880
Anderson Brigliaeb492e02011-06-09 18:50:40 -0300881 case SMP_CMD_MASTER_IDENT:
Vinicius Costa Gomes7034b912011-07-07 18:59:34 -0300882 reason = smp_cmd_master_ident(conn, skb);
883 break;
884
Anderson Brigliaeb492e02011-06-09 18:50:40 -0300885 case SMP_CMD_IDENT_INFO:
886 case SMP_CMD_IDENT_ADDR_INFO:
887 case SMP_CMD_SIGN_INFO:
Vinicius Costa Gomes7034b912011-07-07 18:59:34 -0300888 /* Just ignored */
889 reason = 0;
890 break;
891
Anderson Brigliaeb492e02011-06-09 18:50:40 -0300892 default:
893 BT_DBG("Unknown command code 0x%2.2x", code);
894
895 reason = SMP_CMD_NOTSUPP;
Vinicius Costa Gomes3a0259b2011-06-09 18:50:43 -0300896 err = -EOPNOTSUPP;
897 goto done;
898 }
899
900done:
901 if (reason)
Brian Gix4f957a72011-11-23 08:28:36 -0800902 smp_failure(conn, reason, 1);
Anderson Brigliaeb492e02011-06-09 18:50:40 -0300903
904 kfree_skb(skb);
905 return err;
906}
Vinicius Costa Gomes7034b912011-07-07 18:59:34 -0300907
908int smp_distribute_keys(struct l2cap_conn *conn, __u8 force)
909{
910 struct smp_cmd_pairing *req, *rsp;
Vinicius Costa Gomes1c1def02011-09-05 14:31:30 -0300911 struct smp_chan *smp = conn->smp_chan;
Vinicius Costa Gomes7034b912011-07-07 18:59:34 -0300912 __u8 *keydist;
913
914 BT_DBG("conn %p force %d", conn, force);
915
Johan Hedberg51a8efd2012-01-16 06:10:31 +0200916 if (!test_bit(HCI_CONN_LE_SMP_PEND, &conn->hcon->flags))
Vinicius Costa Gomesd26a2342011-08-19 21:06:51 -0300917 return 0;
918
Vinicius Costa Gomes1c1def02011-09-05 14:31:30 -0300919 rsp = (void *) &smp->prsp[1];
Vinicius Costa Gomes7034b912011-07-07 18:59:34 -0300920
921 /* The responder sends its keys first */
922 if (!force && conn->hcon->out && (rsp->resp_key_dist & 0x07))
923 return 0;
924
Vinicius Costa Gomes1c1def02011-09-05 14:31:30 -0300925 req = (void *) &smp->preq[1];
Vinicius Costa Gomes7034b912011-07-07 18:59:34 -0300926
927 if (conn->hcon->out) {
928 keydist = &rsp->init_key_dist;
929 *keydist &= req->init_key_dist;
930 } else {
931 keydist = &rsp->resp_key_dist;
932 *keydist &= req->resp_key_dist;
933 }
934
935
936 BT_DBG("keydist 0x%x", *keydist);
937
938 if (*keydist & SMP_DIST_ENC_KEY) {
939 struct smp_cmd_encrypt_info enc;
940 struct smp_cmd_master_ident ident;
Vinicius Costa Gomesc9839a12012-02-02 21:08:01 -0300941 struct hci_conn *hcon = conn->hcon;
942 u8 authenticated;
Vinicius Costa Gomes7034b912011-07-07 18:59:34 -0300943 __le16 ediv;
944
945 get_random_bytes(enc.ltk, sizeof(enc.ltk));
946 get_random_bytes(&ediv, sizeof(ediv));
947 get_random_bytes(ident.rand, sizeof(ident.rand));
948
949 smp_send_cmd(conn, SMP_CMD_ENCRYPT_INFO, sizeof(enc), &enc);
950
Vinicius Costa Gomesc9839a12012-02-02 21:08:01 -0300951 authenticated = hcon->sec_level == BT_SECURITY_HIGH;
952 hci_add_ltk(conn->hcon->hdev, conn->dst, hcon->dst_type,
953 HCI_SMP_LTK_SLAVE, 1, authenticated,
954 enc.ltk, smp->enc_key_size,
955 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}