blob: 75937d73d8aebe0df98a598bf38f56d7045ed18c [file] [log] [blame]
Anderson Brigliaeb492e02011-06-09 18:50:40 -03001/*
2 BlueZ - Bluetooth protocol stack for Linux
3 Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
4
5 This program is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License version 2 as
7 published by the Free Software Foundation;
8
9 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
10 OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
11 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF THIRD PARTY RIGHTS.
12 IN NO EVENT SHALL THE COPYRIGHT HOLDER(S) AND AUTHOR(S) BE LIABLE FOR ANY
13 CLAIM, OR ANY SPECIAL INDIRECT OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES
14 WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15 ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16 OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17
18 ALL LIABILITY, INCLUDING LIABILITY FOR INFRINGEMENT OF ANY PATENTS,
19 COPYRIGHTS, TRADEMARKS OR OTHER RIGHTS, RELATING TO USE OF THIS
20 SOFTWARE IS DISCLAIMED.
21*/
22
23#include <net/bluetooth/bluetooth.h>
24#include <net/bluetooth/hci_core.h>
25#include <net/bluetooth/l2cap.h>
Brian Gix2b64d152011-12-21 16:12:12 -080026#include <net/bluetooth/mgmt.h>
Anderson Brigliaeb492e02011-06-09 18:50:40 -030027#include <net/bluetooth/smp.h>
Anderson Brigliad22ef0b2011-06-09 18:50:44 -030028#include <linux/crypto.h>
Stephen Rothwellf70490e2011-06-23 12:58:55 +100029#include <linux/scatterlist.h>
Anderson Brigliad22ef0b2011-06-09 18:50:44 -030030#include <crypto/b128ops.h>
31
Marcel Holtmann17b02e62012-03-01 14:32:37 -080032#define SMP_TIMEOUT msecs_to_jiffies(30000)
Vinicius Costa Gomes5d3de7d2011-06-14 13:37:41 -030033
Anderson Brigliad22ef0b2011-06-09 18:50:44 -030034static inline void swap128(u8 src[16], u8 dst[16])
35{
36 int i;
37 for (i = 0; i < 16; i++)
38 dst[15 - i] = src[i];
39}
40
41static inline void swap56(u8 src[7], u8 dst[7])
42{
43 int i;
44 for (i = 0; i < 7; i++)
45 dst[6 - i] = src[i];
46}
47
48static int smp_e(struct crypto_blkcipher *tfm, const u8 *k, u8 *r)
49{
50 struct blkcipher_desc desc;
51 struct scatterlist sg;
52 int err, iv_len;
53 unsigned char iv[128];
54
55 if (tfm == NULL) {
56 BT_ERR("tfm %p", tfm);
57 return -EINVAL;
58 }
59
60 desc.tfm = tfm;
61 desc.flags = 0;
62
63 err = crypto_blkcipher_setkey(tfm, k, 16);
64 if (err) {
65 BT_ERR("cipher setkey failed: %d", err);
66 return err;
67 }
68
69 sg_init_one(&sg, r, 16);
70
71 iv_len = crypto_blkcipher_ivsize(tfm);
72 if (iv_len) {
73 memset(&iv, 0xff, iv_len);
74 crypto_blkcipher_set_iv(tfm, iv, iv_len);
75 }
76
77 err = crypto_blkcipher_encrypt(&desc, &sg, &sg, 16);
78 if (err)
79 BT_ERR("Encrypt data error %d", err);
80
81 return err;
82}
83
84static int smp_c1(struct crypto_blkcipher *tfm, u8 k[16], u8 r[16],
85 u8 preq[7], u8 pres[7], u8 _iat, bdaddr_t *ia,
86 u8 _rat, bdaddr_t *ra, u8 res[16])
87{
88 u8 p1[16], p2[16];
89 int err;
90
91 memset(p1, 0, 16);
92
93 /* p1 = pres || preq || _rat || _iat */
94 swap56(pres, p1);
95 swap56(preq, p1 + 7);
96 p1[14] = _rat;
97 p1[15] = _iat;
98
99 memset(p2, 0, 16);
100
101 /* p2 = padding || ia || ra */
102 baswap((bdaddr_t *) (p2 + 4), ia);
103 baswap((bdaddr_t *) (p2 + 10), ra);
104
105 /* res = r XOR p1 */
106 u128_xor((u128 *) res, (u128 *) r, (u128 *) p1);
107
108 /* res = e(k, res) */
109 err = smp_e(tfm, k, res);
110 if (err) {
111 BT_ERR("Encrypt data error");
112 return err;
113 }
114
115 /* res = res XOR p2 */
116 u128_xor((u128 *) res, (u128 *) res, (u128 *) p2);
117
118 /* res = e(k, res) */
119 err = smp_e(tfm, k, res);
120 if (err)
121 BT_ERR("Encrypt data error");
122
123 return err;
124}
125
126static int smp_s1(struct crypto_blkcipher *tfm, u8 k[16],
127 u8 r1[16], u8 r2[16], u8 _r[16])
128{
129 int err;
130
131 /* Just least significant octets from r1 and r2 are considered */
132 memcpy(_r, r1 + 8, 8);
133 memcpy(_r + 8, r2 + 8, 8);
134
135 err = smp_e(tfm, k, _r);
136 if (err)
137 BT_ERR("Encrypt data error");
138
139 return err;
140}
141
142static int smp_rand(u8 *buf)
143{
144 get_random_bytes(buf, 16);
145
146 return 0;
147}
Anderson Brigliaeb492e02011-06-09 18:50:40 -0300148
149static struct sk_buff *smp_build_cmd(struct l2cap_conn *conn, u8 code,
150 u16 dlen, void *data)
151{
152 struct sk_buff *skb;
153 struct l2cap_hdr *lh;
154 int len;
155
156 len = L2CAP_HDR_SIZE + sizeof(code) + dlen;
157
158 if (len > conn->mtu)
159 return NULL;
160
161 skb = bt_skb_alloc(len, GFP_ATOMIC);
162 if (!skb)
163 return NULL;
164
165 lh = (struct l2cap_hdr *) skb_put(skb, L2CAP_HDR_SIZE);
166 lh->len = cpu_to_le16(sizeof(code) + dlen);
167 lh->cid = cpu_to_le16(L2CAP_CID_SMP);
168
169 memcpy(skb_put(skb, sizeof(code)), &code, sizeof(code));
170
171 memcpy(skb_put(skb, dlen), data, dlen);
172
173 return skb;
174}
175
176static void smp_send_cmd(struct l2cap_conn *conn, u8 code, u16 len, void *data)
177{
178 struct sk_buff *skb = smp_build_cmd(conn, code, len, data);
179
180 BT_DBG("code 0x%2.2x", code);
181
182 if (!skb)
183 return;
184
Luiz Augusto von Dentz73d80de2011-11-02 15:52:01 +0200185 skb->priority = HCI_PRIO_MAX;
186 hci_send_acl(conn->hchan, skb, 0);
Vinicius Costa Gomese2dcd112011-08-19 21:06:50 -0300187
Gustavo F. Padovan6c9d42a2011-12-20 10:57:27 -0200188 cancel_delayed_work_sync(&conn->security_timer);
Marcel Holtmann17b02e62012-03-01 14:32:37 -0800189 schedule_delayed_work(&conn->security_timer, SMP_TIMEOUT);
Anderson Brigliaeb492e02011-06-09 18:50:40 -0300190}
191
Brian Gix2b64d152011-12-21 16:12:12 -0800192static __u8 authreq_to_seclevel(__u8 authreq)
193{
194 if (authreq & SMP_AUTH_MITM)
195 return BT_SECURITY_HIGH;
196 else
197 return BT_SECURITY_MEDIUM;
198}
199
200static __u8 seclevel_to_authreq(__u8 sec_level)
201{
202 switch (sec_level) {
203 case BT_SECURITY_HIGH:
204 return SMP_AUTH_MITM | SMP_AUTH_BONDING;
205 case BT_SECURITY_MEDIUM:
206 return SMP_AUTH_BONDING;
207 default:
208 return SMP_AUTH_NONE;
209 }
210}
211
Vinicius Costa Gomesb8e66ea2011-06-09 18:50:52 -0300212static void build_pairing_cmd(struct l2cap_conn *conn,
Vinicius Costa Gomes54790f72011-07-07 18:59:38 -0300213 struct smp_cmd_pairing *req,
214 struct smp_cmd_pairing *rsp,
215 __u8 authreq)
Vinicius Costa Gomesb8e66ea2011-06-09 18:50:52 -0300216{
Brian Gix2b64d152011-12-21 16:12:12 -0800217 u8 dist_keys = 0;
Vinicius Costa Gomes54790f72011-07-07 18:59:38 -0300218
Johan Hedberga8b2d5c2012-01-08 23:11:15 +0200219 if (test_bit(HCI_PAIRABLE, &conn->hcon->hdev->dev_flags)) {
Vinicius Costa Gomesca10b5e2011-08-25 20:02:37 -0300220 dist_keys = SMP_DIST_ENC_KEY;
Vinicius Costa Gomes54790f72011-07-07 18:59:38 -0300221 authreq |= SMP_AUTH_BONDING;
Brian Gix2b64d152011-12-21 16:12:12 -0800222 } else {
223 authreq &= ~SMP_AUTH_BONDING;
Vinicius Costa Gomes54790f72011-07-07 18:59:38 -0300224 }
225
226 if (rsp == NULL) {
227 req->io_capability = conn->hcon->io_capability;
228 req->oob_flag = SMP_OOB_NOT_PRESENT;
229 req->max_key_size = SMP_MAX_ENC_KEY_SIZE;
Brian Gix2b64d152011-12-21 16:12:12 -0800230 req->init_key_dist = 0;
Vinicius Costa Gomes54790f72011-07-07 18:59:38 -0300231 req->resp_key_dist = dist_keys;
232 req->auth_req = authreq;
233 return;
234 }
235
236 rsp->io_capability = conn->hcon->io_capability;
237 rsp->oob_flag = SMP_OOB_NOT_PRESENT;
238 rsp->max_key_size = SMP_MAX_ENC_KEY_SIZE;
Brian Gix2b64d152011-12-21 16:12:12 -0800239 rsp->init_key_dist = 0;
Vinicius Costa Gomes54790f72011-07-07 18:59:38 -0300240 rsp->resp_key_dist = req->resp_key_dist & dist_keys;
241 rsp->auth_req = authreq;
Vinicius Costa Gomesb8e66ea2011-06-09 18:50:52 -0300242}
243
Vinicius Costa Gomes3158c502011-06-14 13:37:42 -0300244static u8 check_enc_key_size(struct l2cap_conn *conn, __u8 max_key_size)
245{
Vinicius Costa Gomes1c1def02011-09-05 14:31:30 -0300246 struct smp_chan *smp = conn->smp_chan;
247
Vinicius Costa Gomes3158c502011-06-14 13:37:42 -0300248 if ((max_key_size > SMP_MAX_ENC_KEY_SIZE) ||
249 (max_key_size < SMP_MIN_ENC_KEY_SIZE))
250 return SMP_ENC_KEY_SIZE;
251
Vinicius Costa Gomesf7aa6112012-01-30 19:29:12 -0300252 smp->enc_key_size = max_key_size;
Vinicius Costa Gomes3158c502011-06-14 13:37:42 -0300253
254 return 0;
255}
256
Brian Gix4f957a72011-11-23 08:28:36 -0800257static void smp_failure(struct l2cap_conn *conn, u8 reason, u8 send)
258{
Johan Hedbergbab73cb2012-02-09 16:07:29 +0200259 struct hci_conn *hcon = conn->hcon;
260
Brian Gix4f957a72011-11-23 08:28:36 -0800261 if (send)
262 smp_send_cmd(conn, SMP_CMD_PAIRING_FAIL, sizeof(reason),
263 &reason);
264
Johan Hedberg51a8efd2012-01-16 06:10:31 +0200265 clear_bit(HCI_CONN_ENCRYPT_PEND, &conn->hcon->flags);
Johan Hedbergbab73cb2012-02-09 16:07:29 +0200266 mgmt_auth_failed(conn->hcon->hdev, conn->dst, hcon->type,
267 hcon->dst_type, reason);
Vinicius Costa Gomesf1c09c02012-02-01 18:27:56 -0300268
269 if (test_and_clear_bit(HCI_CONN_LE_SMP_PEND, &conn->hcon->flags)) {
270 cancel_delayed_work_sync(&conn->security_timer);
271 smp_chan_destroy(conn);
272 }
Brian Gix4f957a72011-11-23 08:28:36 -0800273}
274
Brian Gix2b64d152011-12-21 16:12:12 -0800275#define JUST_WORKS 0x00
276#define JUST_CFM 0x01
277#define REQ_PASSKEY 0x02
278#define CFM_PASSKEY 0x03
279#define REQ_OOB 0x04
280#define OVERLAP 0xFF
281
282static const u8 gen_method[5][5] = {
283 { JUST_WORKS, JUST_CFM, REQ_PASSKEY, JUST_WORKS, REQ_PASSKEY },
284 { JUST_WORKS, JUST_CFM, REQ_PASSKEY, JUST_WORKS, REQ_PASSKEY },
285 { CFM_PASSKEY, CFM_PASSKEY, REQ_PASSKEY, JUST_WORKS, CFM_PASSKEY },
286 { JUST_WORKS, JUST_CFM, JUST_WORKS, JUST_WORKS, JUST_CFM },
287 { CFM_PASSKEY, CFM_PASSKEY, REQ_PASSKEY, JUST_WORKS, OVERLAP },
288};
289
290static int tk_request(struct l2cap_conn *conn, u8 remote_oob, u8 auth,
291 u8 local_io, u8 remote_io)
292{
293 struct hci_conn *hcon = conn->hcon;
294 struct smp_chan *smp = conn->smp_chan;
295 u8 method;
296 u32 passkey = 0;
297 int ret = 0;
298
299 /* Initialize key for JUST WORKS */
300 memset(smp->tk, 0, sizeof(smp->tk));
301 clear_bit(SMP_FLAG_TK_VALID, &smp->smp_flags);
302
303 BT_DBG("tk_request: auth:%d lcl:%d rem:%d", auth, local_io, remote_io);
304
305 /* If neither side wants MITM, use JUST WORKS */
306 /* If either side has unknown io_caps, use JUST WORKS */
307 /* Otherwise, look up method from the table */
308 if (!(auth & SMP_AUTH_MITM) ||
309 local_io > SMP_IO_KEYBOARD_DISPLAY ||
310 remote_io > SMP_IO_KEYBOARD_DISPLAY)
311 method = JUST_WORKS;
312 else
313 method = gen_method[local_io][remote_io];
314
315 /* If not bonding, don't ask user to confirm a Zero TK */
316 if (!(auth & SMP_AUTH_BONDING) && method == JUST_CFM)
317 method = JUST_WORKS;
318
319 /* If Just Works, Continue with Zero TK */
320 if (method == JUST_WORKS) {
321 set_bit(SMP_FLAG_TK_VALID, &smp->smp_flags);
322 return 0;
323 }
324
325 /* Not Just Works/Confirm results in MITM Authentication */
326 if (method != JUST_CFM)
327 set_bit(SMP_FLAG_MITM_AUTH, &smp->smp_flags);
328
329 /* If both devices have Keyoard-Display I/O, the master
330 * Confirms and the slave Enters the passkey.
331 */
332 if (method == OVERLAP) {
333 if (hcon->link_mode & HCI_LM_MASTER)
334 method = CFM_PASSKEY;
335 else
336 method = REQ_PASSKEY;
337 }
338
339 /* Generate random passkey. Not valid until confirmed. */
340 if (method == CFM_PASSKEY) {
341 u8 key[16];
342
343 memset(key, 0, sizeof(key));
344 get_random_bytes(&passkey, sizeof(passkey));
345 passkey %= 1000000;
346 put_unaligned_le32(passkey, key);
347 swap128(key, smp->tk);
348 BT_DBG("PassKey: %d", passkey);
349 }
350
351 hci_dev_lock(hcon->hdev);
352
353 if (method == REQ_PASSKEY)
Johan Hedberg272d90d2012-02-09 15:26:12 +0200354 ret = mgmt_user_passkey_request(hcon->hdev, conn->dst,
355 hcon->type, hcon->dst_type);
Brian Gix2b64d152011-12-21 16:12:12 -0800356 else
357 ret = mgmt_user_confirm_request(hcon->hdev, conn->dst,
Johan Hedberg272d90d2012-02-09 15:26:12 +0200358 hcon->type, hcon->dst_type,
Brian Gix2b64d152011-12-21 16:12:12 -0800359 cpu_to_le32(passkey), 0);
360
361 hci_dev_unlock(hcon->hdev);
362
363 return ret;
364}
365
Vinicius Costa Gomes8aab4752011-09-05 14:31:31 -0300366static void confirm_work(struct work_struct *work)
367{
368 struct smp_chan *smp = container_of(work, struct smp_chan, confirm);
369 struct l2cap_conn *conn = smp->conn;
370 struct crypto_blkcipher *tfm;
371 struct smp_cmd_pairing_confirm cp;
372 int ret;
373 u8 res[16], reason;
374
375 BT_DBG("conn %p", conn);
376
377 tfm = crypto_alloc_blkcipher("ecb(aes)", 0, CRYPTO_ALG_ASYNC);
378 if (IS_ERR(tfm)) {
379 reason = SMP_UNSPECIFIED;
380 goto error;
381 }
382
383 smp->tfm = tfm;
384
385 if (conn->hcon->out)
386 ret = smp_c1(tfm, smp->tk, smp->prnd, smp->preq, smp->prsp, 0,
387 conn->src, conn->hcon->dst_type, conn->dst,
388 res);
389 else
390 ret = smp_c1(tfm, smp->tk, smp->prnd, smp->preq, smp->prsp,
391 conn->hcon->dst_type, conn->dst, 0, conn->src,
392 res);
393 if (ret) {
394 reason = SMP_UNSPECIFIED;
395 goto error;
396 }
397
Brian Gix2b64d152011-12-21 16:12:12 -0800398 clear_bit(SMP_FLAG_CFM_PENDING, &smp->smp_flags);
399
Vinicius Costa Gomes8aab4752011-09-05 14:31:31 -0300400 swap128(res, cp.confirm_val);
401 smp_send_cmd(smp->conn, SMP_CMD_PAIRING_CONFIRM, sizeof(cp), &cp);
402
403 return;
404
405error:
Brian Gix4f957a72011-11-23 08:28:36 -0800406 smp_failure(conn, reason, 1);
Vinicius Costa Gomes8aab4752011-09-05 14:31:31 -0300407}
408
409static void random_work(struct work_struct *work)
410{
411 struct smp_chan *smp = container_of(work, struct smp_chan, random);
412 struct l2cap_conn *conn = smp->conn;
413 struct hci_conn *hcon = conn->hcon;
414 struct crypto_blkcipher *tfm = smp->tfm;
415 u8 reason, confirm[16], res[16], key[16];
416 int ret;
417
418 if (IS_ERR_OR_NULL(tfm)) {
419 reason = SMP_UNSPECIFIED;
420 goto error;
421 }
422
423 BT_DBG("conn %p %s", conn, conn->hcon->out ? "master" : "slave");
424
425 if (hcon->out)
426 ret = smp_c1(tfm, smp->tk, smp->rrnd, smp->preq, smp->prsp, 0,
427 conn->src, hcon->dst_type, conn->dst,
428 res);
429 else
430 ret = smp_c1(tfm, smp->tk, smp->rrnd, smp->preq, smp->prsp,
431 hcon->dst_type, conn->dst, 0, conn->src,
432 res);
433 if (ret) {
434 reason = SMP_UNSPECIFIED;
435 goto error;
436 }
437
438 swap128(res, confirm);
439
440 if (memcmp(smp->pcnf, confirm, sizeof(smp->pcnf)) != 0) {
441 BT_ERR("Pairing failed (confirmation values mismatch)");
442 reason = SMP_CONFIRM_FAILED;
443 goto error;
444 }
445
446 if (hcon->out) {
447 u8 stk[16], rand[8];
448 __le16 ediv;
449
450 memset(rand, 0, sizeof(rand));
451 ediv = 0;
452
453 smp_s1(tfm, smp->tk, smp->rrnd, smp->prnd, key);
454 swap128(key, stk);
455
Vinicius Costa Gomesf7aa6112012-01-30 19:29:12 -0300456 memset(stk + smp->enc_key_size, 0,
457 SMP_MAX_ENC_KEY_SIZE - smp->enc_key_size);
Vinicius Costa Gomes8aab4752011-09-05 14:31:31 -0300458
Johan Hedberg51a8efd2012-01-16 06:10:31 +0200459 if (test_and_set_bit(HCI_CONN_ENCRYPT_PEND, &hcon->flags)) {
Vinicius Costa Gomes8aab4752011-09-05 14:31:31 -0300460 reason = SMP_UNSPECIFIED;
461 goto error;
462 }
463
464 hci_le_start_enc(hcon, ediv, rand, stk);
Vinicius Costa Gomesf7aa6112012-01-30 19:29:12 -0300465 hcon->enc_key_size = smp->enc_key_size;
Vinicius Costa Gomes8aab4752011-09-05 14:31:31 -0300466 } else {
467 u8 stk[16], r[16], rand[8];
468 __le16 ediv;
469
470 memset(rand, 0, sizeof(rand));
471 ediv = 0;
472
473 swap128(smp->prnd, r);
474 smp_send_cmd(conn, SMP_CMD_PAIRING_RANDOM, sizeof(r), r);
475
476 smp_s1(tfm, smp->tk, smp->prnd, smp->rrnd, key);
477 swap128(key, stk);
478
Vinicius Costa Gomesf7aa6112012-01-30 19:29:12 -0300479 memset(stk + smp->enc_key_size, 0,
480 SMP_MAX_ENC_KEY_SIZE - smp->enc_key_size);
Vinicius Costa Gomes8aab4752011-09-05 14:31:31 -0300481
Vinicius Costa Gomesc9839a12012-02-02 21:08:01 -0300482 hci_add_ltk(hcon->hdev, conn->dst, hcon->dst_type,
483 HCI_SMP_STK_SLAVE, 0, 0, stk,
484 smp->enc_key_size, ediv, rand);
Vinicius Costa Gomes8aab4752011-09-05 14:31:31 -0300485 }
486
487 return;
488
489error:
Brian Gix4f957a72011-11-23 08:28:36 -0800490 smp_failure(conn, reason, 1);
Vinicius Costa Gomes8aab4752011-09-05 14:31:31 -0300491}
492
493static struct smp_chan *smp_chan_create(struct l2cap_conn *conn)
494{
495 struct smp_chan *smp;
496
497 smp = kzalloc(sizeof(struct smp_chan), GFP_ATOMIC);
498 if (!smp)
499 return NULL;
500
501 INIT_WORK(&smp->confirm, confirm_work);
502 INIT_WORK(&smp->random, random_work);
503
504 smp->conn = conn;
505 conn->smp_chan = smp;
Brian Gix2b64d152011-12-21 16:12:12 -0800506 conn->hcon->smp_conn = conn;
Vinicius Costa Gomes8aab4752011-09-05 14:31:31 -0300507
508 hci_conn_hold(conn->hcon);
509
510 return smp;
511}
512
513void smp_chan_destroy(struct l2cap_conn *conn)
514{
Brian Gixc8eb9692011-11-23 08:28:35 -0800515 struct smp_chan *smp = conn->smp_chan;
516
Vinicius Costa Gomesf1c09c02012-02-01 18:27:56 -0300517 BUG_ON(!smp);
Brian Gixc8eb9692011-11-23 08:28:35 -0800518
519 if (smp->tfm)
520 crypto_free_blkcipher(smp->tfm);
521
522 kfree(smp);
523 conn->smp_chan = NULL;
Brian Gix2b64d152011-12-21 16:12:12 -0800524 conn->hcon->smp_conn = NULL;
Vinicius Costa Gomes8aab4752011-09-05 14:31:31 -0300525 hci_conn_put(conn->hcon);
526}
527
Brian Gix2b64d152011-12-21 16:12:12 -0800528int smp_user_confirm_reply(struct hci_conn *hcon, u16 mgmt_op, __le32 passkey)
529{
530 struct l2cap_conn *conn = hcon->smp_conn;
531 struct smp_chan *smp;
532 u32 value;
533 u8 key[16];
534
535 BT_DBG("");
536
537 if (!conn)
538 return -ENOTCONN;
539
540 smp = conn->smp_chan;
541
542 switch (mgmt_op) {
543 case MGMT_OP_USER_PASSKEY_REPLY:
544 value = le32_to_cpu(passkey);
545 memset(key, 0, sizeof(key));
546 BT_DBG("PassKey: %d", value);
547 put_unaligned_le32(value, key);
548 swap128(key, smp->tk);
549 /* Fall Through */
550 case MGMT_OP_USER_CONFIRM_REPLY:
551 set_bit(SMP_FLAG_TK_VALID, &smp->smp_flags);
552 break;
553 case MGMT_OP_USER_PASSKEY_NEG_REPLY:
554 case MGMT_OP_USER_CONFIRM_NEG_REPLY:
555 smp_failure(conn, SMP_PASSKEY_ENTRY_FAILED, 1);
556 return 0;
557 default:
558 smp_failure(conn, SMP_PASSKEY_ENTRY_FAILED, 1);
559 return -EOPNOTSUPP;
560 }
561
562 /* If it is our turn to send Pairing Confirm, do so now */
563 if (test_bit(SMP_FLAG_CFM_PENDING, &smp->smp_flags))
564 queue_work(hcon->hdev->workqueue, &smp->confirm);
565
566 return 0;
567}
568
Vinicius Costa Gomesda85e5e2011-06-09 18:50:53 -0300569static u8 smp_cmd_pairing_req(struct l2cap_conn *conn, struct sk_buff *skb)
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300570{
Vinicius Costa Gomes3158c502011-06-14 13:37:42 -0300571 struct smp_cmd_pairing rsp, *req = (void *) skb->data;
Vinicius Costa Gomes8aab4752011-09-05 14:31:31 -0300572 struct smp_chan *smp;
Vinicius Costa Gomes3158c502011-06-14 13:37:42 -0300573 u8 key_size;
Brian Gix2b64d152011-12-21 16:12:12 -0800574 u8 auth = SMP_AUTH_NONE;
Vinicius Costa Gomes8aab4752011-09-05 14:31:31 -0300575 int ret;
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300576
577 BT_DBG("conn %p", conn);
578
Brian Gix2b64d152011-12-21 16:12:12 -0800579 if (conn->hcon->link_mode & HCI_LM_MASTER)
580 return SMP_CMD_NOTSUPP;
581
Johan Hedberg51a8efd2012-01-16 06:10:31 +0200582 if (!test_and_set_bit(HCI_CONN_LE_SMP_PEND, &conn->hcon->flags))
Vinicius Costa Gomes8aab4752011-09-05 14:31:31 -0300583 smp = smp_chan_create(conn);
584
585 smp = conn->smp_chan;
Vinicius Costa Gomesd26a2342011-08-19 21:06:51 -0300586
Vinicius Costa Gomes1c1def02011-09-05 14:31:30 -0300587 smp->preq[0] = SMP_CMD_PAIRING_REQ;
588 memcpy(&smp->preq[1], req, sizeof(*req));
Vinicius Costa Gomes3158c502011-06-14 13:37:42 -0300589 skb_pull(skb, sizeof(*req));
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300590
Brian Gix2b64d152011-12-21 16:12:12 -0800591 /* We didn't start the pairing, so match remote */
592 if (req->auth_req & SMP_AUTH_BONDING)
593 auth = req->auth_req;
Vinicius Costa Gomesda85e5e2011-06-09 18:50:53 -0300594
Brian Gix2b64d152011-12-21 16:12:12 -0800595 build_pairing_cmd(conn, req, &rsp, auth);
Vinicius Costa Gomes3158c502011-06-14 13:37:42 -0300596
597 key_size = min(req->max_key_size, rsp.max_key_size);
598 if (check_enc_key_size(conn, key_size))
599 return SMP_ENC_KEY_SIZE;
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300600
Vinicius Costa Gomes8aab4752011-09-05 14:31:31 -0300601 ret = smp_rand(smp->prnd);
602 if (ret)
603 return SMP_UNSPECIFIED;
604
Vinicius Costa Gomes1c1def02011-09-05 14:31:30 -0300605 smp->prsp[0] = SMP_CMD_PAIRING_RSP;
606 memcpy(&smp->prsp[1], &rsp, sizeof(rsp));
Anderson Brigliaf01ead32011-06-09 18:50:45 -0300607
Vinicius Costa Gomes3158c502011-06-14 13:37:42 -0300608 smp_send_cmd(conn, SMP_CMD_PAIRING_RSP, sizeof(rsp), &rsp);
Vinicius Costa Gomesda85e5e2011-06-09 18:50:53 -0300609
Brian Gix2b64d152011-12-21 16:12:12 -0800610 /* Request setup of TK */
611 ret = tk_request(conn, 0, auth, rsp.io_capability, req->io_capability);
612 if (ret)
613 return SMP_UNSPECIFIED;
614
Vinicius Costa Gomesda85e5e2011-06-09 18:50:53 -0300615 return 0;
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300616}
617
Vinicius Costa Gomesda85e5e2011-06-09 18:50:53 -0300618static u8 smp_cmd_pairing_rsp(struct l2cap_conn *conn, struct sk_buff *skb)
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300619{
Vinicius Costa Gomes3158c502011-06-14 13:37:42 -0300620 struct smp_cmd_pairing *req, *rsp = (void *) skb->data;
Vinicius Costa Gomes1c1def02011-09-05 14:31:30 -0300621 struct smp_chan *smp = conn->smp_chan;
Vinicius Costa Gomes8aab4752011-09-05 14:31:31 -0300622 struct hci_dev *hdev = conn->hcon->hdev;
Brian Gix2b64d152011-12-21 16:12:12 -0800623 u8 key_size, auth = SMP_AUTH_NONE;
Anderson Briglia7d24ddc2011-06-09 18:50:46 -0300624 int ret;
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300625
626 BT_DBG("conn %p", conn);
627
Brian Gix2b64d152011-12-21 16:12:12 -0800628 if (!(conn->hcon->link_mode & HCI_LM_MASTER))
629 return SMP_CMD_NOTSUPP;
630
Vinicius Costa Gomes3158c502011-06-14 13:37:42 -0300631 skb_pull(skb, sizeof(*rsp));
Vinicius Costa Gomesda85e5e2011-06-09 18:50:53 -0300632
Vinicius Costa Gomes1c1def02011-09-05 14:31:30 -0300633 req = (void *) &smp->preq[1];
Vinicius Costa Gomes3158c502011-06-14 13:37:42 -0300634
635 key_size = min(req->max_key_size, rsp->max_key_size);
636 if (check_enc_key_size(conn, key_size))
637 return SMP_ENC_KEY_SIZE;
638
Vinicius Costa Gomes1c1def02011-09-05 14:31:30 -0300639 ret = smp_rand(smp->prnd);
Anderson Briglia7d24ddc2011-06-09 18:50:46 -0300640 if (ret)
Vinicius Costa Gomesda85e5e2011-06-09 18:50:53 -0300641 return SMP_UNSPECIFIED;
Anderson Briglia7d24ddc2011-06-09 18:50:46 -0300642
Vinicius Costa Gomes8aab4752011-09-05 14:31:31 -0300643 smp->prsp[0] = SMP_CMD_PAIRING_RSP;
644 memcpy(&smp->prsp[1], rsp, sizeof(*rsp));
Anderson Briglia7d24ddc2011-06-09 18:50:46 -0300645
Brian Gix2b64d152011-12-21 16:12:12 -0800646 if ((req->auth_req & SMP_AUTH_BONDING) &&
647 (rsp->auth_req & SMP_AUTH_BONDING))
648 auth = SMP_AUTH_BONDING;
649
650 auth |= (req->auth_req | rsp->auth_req) & SMP_AUTH_MITM;
651
652 ret = tk_request(conn, 0, auth, rsp->io_capability, req->io_capability);
653 if (ret)
654 return SMP_UNSPECIFIED;
655
656 set_bit(SMP_FLAG_CFM_PENDING, &smp->smp_flags);
657
658 /* Can't compose response until we have been confirmed */
659 if (!test_bit(SMP_FLAG_TK_VALID, &smp->smp_flags))
660 return 0;
661
Vinicius Costa Gomes8aab4752011-09-05 14:31:31 -0300662 queue_work(hdev->workqueue, &smp->confirm);
Vinicius Costa Gomesda85e5e2011-06-09 18:50:53 -0300663
664 return 0;
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300665}
666
Vinicius Costa Gomesda85e5e2011-06-09 18:50:53 -0300667static u8 smp_cmd_pairing_confirm(struct l2cap_conn *conn, struct sk_buff *skb)
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300668{
Vinicius Costa Gomes1c1def02011-09-05 14:31:30 -0300669 struct smp_chan *smp = conn->smp_chan;
Vinicius Costa Gomes8aab4752011-09-05 14:31:31 -0300670 struct hci_dev *hdev = conn->hcon->hdev;
Anderson Briglia7d24ddc2011-06-09 18:50:46 -0300671
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300672 BT_DBG("conn %p %s", conn, conn->hcon->out ? "master" : "slave");
673
Vinicius Costa Gomes1c1def02011-09-05 14:31:30 -0300674 memcpy(smp->pcnf, skb->data, sizeof(smp->pcnf));
675 skb_pull(skb, sizeof(smp->pcnf));
Anderson Briglia7d24ddc2011-06-09 18:50:46 -0300676
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300677 if (conn->hcon->out) {
Anderson Briglia7d24ddc2011-06-09 18:50:46 -0300678 u8 random[16];
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300679
Vinicius Costa Gomes1c1def02011-09-05 14:31:30 -0300680 swap128(smp->prnd, random);
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300681 smp_send_cmd(conn, SMP_CMD_PAIRING_RANDOM, sizeof(random),
Anderson Briglia7d24ddc2011-06-09 18:50:46 -0300682 random);
Brian Gix2b64d152011-12-21 16:12:12 -0800683 } else if (test_bit(SMP_FLAG_TK_VALID, &smp->smp_flags)) {
Vinicius Costa Gomes8aab4752011-09-05 14:31:31 -0300684 queue_work(hdev->workqueue, &smp->confirm);
Brian Gix2b64d152011-12-21 16:12:12 -0800685 } else {
686 set_bit(SMP_FLAG_CFM_PENDING, &smp->smp_flags);
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300687 }
Vinicius Costa Gomesda85e5e2011-06-09 18:50:53 -0300688
689 return 0;
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300690}
691
Vinicius Costa Gomesda85e5e2011-06-09 18:50:53 -0300692static u8 smp_cmd_pairing_random(struct l2cap_conn *conn, struct sk_buff *skb)
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300693{
Vinicius Costa Gomes1c1def02011-09-05 14:31:30 -0300694 struct smp_chan *smp = conn->smp_chan;
Vinicius Costa Gomes8aab4752011-09-05 14:31:31 -0300695 struct hci_dev *hdev = conn->hcon->hdev;
Anderson Briglia7d24ddc2011-06-09 18:50:46 -0300696
Vinicius Costa Gomes8aab4752011-09-05 14:31:31 -0300697 BT_DBG("conn %p", conn);
Anderson Briglia7d24ddc2011-06-09 18:50:46 -0300698
Vinicius Costa Gomes8aab4752011-09-05 14:31:31 -0300699 swap128(skb->data, smp->rrnd);
700 skb_pull(skb, sizeof(smp->rrnd));
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300701
Vinicius Costa Gomes8aab4752011-09-05 14:31:31 -0300702 queue_work(hdev->workqueue, &smp->random);
Vinicius Costa Gomesda85e5e2011-06-09 18:50:53 -0300703
704 return 0;
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300705}
706
Vinicius Costa Gomes988c5992011-08-25 20:02:28 -0300707static u8 smp_ltk_encrypt(struct l2cap_conn *conn)
708{
Vinicius Costa Gomesc9839a12012-02-02 21:08:01 -0300709 struct smp_ltk *key;
Vinicius Costa Gomes988c5992011-08-25 20:02:28 -0300710 struct hci_conn *hcon = conn->hcon;
711
Vinicius Costa Gomesc9839a12012-02-02 21:08:01 -0300712 key = hci_find_ltk_by_addr(hcon->hdev, conn->dst, hcon->dst_type);
Vinicius Costa Gomes988c5992011-08-25 20:02:28 -0300713 if (!key)
714 return 0;
715
Johan Hedberg51a8efd2012-01-16 06:10:31 +0200716 if (test_and_set_bit(HCI_CONN_ENCRYPT_PEND, &hcon->flags))
Vinicius Costa Gomes988c5992011-08-25 20:02:28 -0300717 return 1;
718
Vinicius Costa Gomesc9839a12012-02-02 21:08:01 -0300719 hci_le_start_enc(hcon, key->ediv, key->rand, key->val);
720 hcon->enc_key_size = key->enc_size;
Vinicius Costa Gomes988c5992011-08-25 20:02:28 -0300721
722 return 1;
723
724}
Vinicius Costa Gomesda85e5e2011-06-09 18:50:53 -0300725static u8 smp_cmd_security_req(struct l2cap_conn *conn, struct sk_buff *skb)
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300726{
727 struct smp_cmd_security_req *rp = (void *) skb->data;
728 struct smp_cmd_pairing cp;
Vinicius Costa Gomesf1cb9af2011-01-26 21:42:57 -0300729 struct hci_conn *hcon = conn->hcon;
Vinicius Costa Gomes8aab4752011-09-05 14:31:31 -0300730 struct smp_chan *smp;
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300731
732 BT_DBG("conn %p", conn);
733
Brian Gix2b64d152011-12-21 16:12:12 -0800734 hcon->pending_sec_level = authreq_to_seclevel(rp->auth_req);
Vinicius Costa Gomesfeb45eb2011-08-25 20:02:35 -0300735
Vinicius Costa Gomes988c5992011-08-25 20:02:28 -0300736 if (smp_ltk_encrypt(conn))
737 return 0;
738
Johan Hedberg51a8efd2012-01-16 06:10:31 +0200739 if (test_and_set_bit(HCI_CONN_LE_SMP_PEND, &hcon->flags))
Vinicius Costa Gomesda85e5e2011-06-09 18:50:53 -0300740 return 0;
Vinicius Costa Gomesf1cb9af2011-01-26 21:42:57 -0300741
Vinicius Costa Gomes8aab4752011-09-05 14:31:31 -0300742 smp = smp_chan_create(conn);
Vinicius Costa Gomesd26a2342011-08-19 21:06:51 -0300743
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300744 skb_pull(skb, sizeof(*rp));
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300745
Vinicius Costa Gomesda85e5e2011-06-09 18:50:53 -0300746 memset(&cp, 0, sizeof(cp));
Vinicius Costa Gomes54790f72011-07-07 18:59:38 -0300747 build_pairing_cmd(conn, &cp, NULL, rp->auth_req);
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300748
Vinicius Costa Gomes1c1def02011-09-05 14:31:30 -0300749 smp->preq[0] = SMP_CMD_PAIRING_REQ;
750 memcpy(&smp->preq[1], &cp, sizeof(cp));
Anderson Brigliaf01ead32011-06-09 18:50:45 -0300751
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300752 smp_send_cmd(conn, SMP_CMD_PAIRING_REQ, sizeof(cp), &cp);
Vinicius Costa Gomesf1cb9af2011-01-26 21:42:57 -0300753
Vinicius Costa Gomesda85e5e2011-06-09 18:50:53 -0300754 return 0;
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300755}
756
Anderson Brigliaeb492e02011-06-09 18:50:40 -0300757int smp_conn_security(struct l2cap_conn *conn, __u8 sec_level)
758{
Vinicius Costa Gomes3a0259b2011-06-09 18:50:43 -0300759 struct hci_conn *hcon = conn->hcon;
Vinicius Costa Gomes1c1def02011-09-05 14:31:30 -0300760 struct smp_chan *smp = conn->smp_chan;
Brian Gix2b64d152011-12-21 16:12:12 -0800761 __u8 authreq;
Anderson Brigliaeb492e02011-06-09 18:50:40 -0300762
Vinicius Costa Gomes3a0259b2011-06-09 18:50:43 -0300763 BT_DBG("conn %p hcon %p level 0x%2.2x", conn, hcon, sec_level);
764
Andre Guedes2e65c9d2011-06-30 19:20:56 -0300765 if (!lmp_host_le_capable(hcon->hdev))
766 return 1;
767
Vinicius Costa Gomesf1cb9af2011-01-26 21:42:57 -0300768 if (sec_level == BT_SECURITY_LOW)
Anderson Brigliaeb492e02011-06-09 18:50:40 -0300769 return 1;
Vinicius Costa Gomesf1cb9af2011-01-26 21:42:57 -0300770
771 if (hcon->sec_level >= sec_level)
772 return 1;
773
Vinicius Costa Gomes988c5992011-08-25 20:02:28 -0300774 if (hcon->link_mode & HCI_LM_MASTER)
775 if (smp_ltk_encrypt(conn))
Vinicius Costa Gomes02bc7452011-07-07 18:59:41 -0300776 goto done;
Vinicius Costa Gomesd26a2342011-08-19 21:06:51 -0300777
Johan Hedberg51a8efd2012-01-16 06:10:31 +0200778 if (test_and_set_bit(HCI_CONN_LE_SMP_PEND, &hcon->flags))
Vinicius Costa Gomesd26a2342011-08-19 21:06:51 -0300779 return 0;
780
Vinicius Costa Gomes8aab4752011-09-05 14:31:31 -0300781 smp = smp_chan_create(conn);
Brian Gix2b64d152011-12-21 16:12:12 -0800782 if (!smp)
783 return 1;
784
785 authreq = seclevel_to_authreq(sec_level);
Vinicius Costa Gomesd26a2342011-08-19 21:06:51 -0300786
Vinicius Costa Gomesd26a2342011-08-19 21:06:51 -0300787 if (hcon->link_mode & HCI_LM_MASTER) {
788 struct smp_cmd_pairing cp;
Anderson Brigliaf01ead32011-06-09 18:50:45 -0300789
Brian Gix2b64d152011-12-21 16:12:12 -0800790 build_pairing_cmd(conn, &cp, NULL, authreq);
Vinicius Costa Gomes1c1def02011-09-05 14:31:30 -0300791 smp->preq[0] = SMP_CMD_PAIRING_REQ;
792 memcpy(&smp->preq[1], &cp, sizeof(cp));
Anderson Brigliaf01ead32011-06-09 18:50:45 -0300793
Anderson Brigliaeb492e02011-06-09 18:50:40 -0300794 smp_send_cmd(conn, SMP_CMD_PAIRING_REQ, sizeof(cp), &cp);
795 } else {
796 struct smp_cmd_security_req cp;
Brian Gix2b64d152011-12-21 16:12:12 -0800797 cp.auth_req = authreq;
Anderson Brigliaeb492e02011-06-09 18:50:40 -0300798 smp_send_cmd(conn, SMP_CMD_SECURITY_REQ, sizeof(cp), &cp);
799 }
800
Vinicius Costa Gomes02bc7452011-07-07 18:59:41 -0300801done:
Vinicius Costa Gomesf1cb9af2011-01-26 21:42:57 -0300802 hcon->pending_sec_level = sec_level;
Vinicius Costa Gomesf1cb9af2011-01-26 21:42:57 -0300803
Anderson Brigliaeb492e02011-06-09 18:50:40 -0300804 return 0;
805}
806
Vinicius Costa Gomes7034b912011-07-07 18:59:34 -0300807static int smp_cmd_encrypt_info(struct l2cap_conn *conn, struct sk_buff *skb)
808{
Vinicius Costa Gomes16b90832011-07-07 18:59:39 -0300809 struct smp_cmd_encrypt_info *rp = (void *) skb->data;
Vinicius Costa Gomes1c1def02011-09-05 14:31:30 -0300810 struct smp_chan *smp = conn->smp_chan;
Vinicius Costa Gomes16b90832011-07-07 18:59:39 -0300811
812 skb_pull(skb, sizeof(*rp));
813
Vinicius Costa Gomes1c1def02011-09-05 14:31:30 -0300814 memcpy(smp->tk, rp->ltk, sizeof(smp->tk));
Vinicius Costa Gomes16b90832011-07-07 18:59:39 -0300815
Vinicius Costa Gomes7034b912011-07-07 18:59:34 -0300816 return 0;
817}
818
819static int smp_cmd_master_ident(struct l2cap_conn *conn, struct sk_buff *skb)
820{
Vinicius Costa Gomes16b90832011-07-07 18:59:39 -0300821 struct smp_cmd_master_ident *rp = (void *) skb->data;
Vinicius Costa Gomes1c1def02011-09-05 14:31:30 -0300822 struct smp_chan *smp = conn->smp_chan;
Vinicius Costa Gomesc9839a12012-02-02 21:08:01 -0300823 struct hci_dev *hdev = conn->hcon->hdev;
824 struct hci_conn *hcon = conn->hcon;
825 u8 authenticated;
Vinicius Costa Gomes7034b912011-07-07 18:59:34 -0300826
Vinicius Costa Gomes16b90832011-07-07 18:59:39 -0300827 skb_pull(skb, sizeof(*rp));
828
Vinicius Costa Gomesc9839a12012-02-02 21:08:01 -0300829 hci_dev_lock(hdev);
830 authenticated = (conn->hcon->sec_level == BT_SECURITY_HIGH);
831 hci_add_ltk(conn->hcon->hdev, conn->dst, hcon->dst_type,
832 HCI_SMP_LTK, 1, authenticated, smp->tk,
833 smp->enc_key_size, rp->ediv, rp->rand);
Vinicius Costa Gomes7034b912011-07-07 18:59:34 -0300834 smp_distribute_keys(conn, 1);
Vinicius Costa Gomesc9839a12012-02-02 21:08:01 -0300835 hci_dev_unlock(hdev);
Vinicius Costa Gomes7034b912011-07-07 18:59:34 -0300836
837 return 0;
838}
839
Anderson Brigliaeb492e02011-06-09 18:50:40 -0300840int smp_sig_channel(struct l2cap_conn *conn, struct sk_buff *skb)
841{
842 __u8 code = skb->data[0];
843 __u8 reason;
844 int err = 0;
845
Andre Guedes2e65c9d2011-06-30 19:20:56 -0300846 if (!lmp_host_le_capable(conn->hcon->hdev)) {
847 err = -ENOTSUPP;
848 reason = SMP_PAIRING_NOTSUPP;
849 goto done;
850 }
851
Anderson Brigliaeb492e02011-06-09 18:50:40 -0300852 skb_pull(skb, sizeof(code));
853
854 switch (code) {
855 case SMP_CMD_PAIRING_REQ:
Vinicius Costa Gomesda85e5e2011-06-09 18:50:53 -0300856 reason = smp_cmd_pairing_req(conn, skb);
Anderson Brigliaeb492e02011-06-09 18:50:40 -0300857 break;
858
859 case SMP_CMD_PAIRING_FAIL:
Brian Gix4f957a72011-11-23 08:28:36 -0800860 smp_failure(conn, skb->data[0], 0);
Vinicius Costa Gomesda85e5e2011-06-09 18:50:53 -0300861 reason = 0;
862 err = -EPERM;
Anderson Brigliaeb492e02011-06-09 18:50:40 -0300863 break;
864
865 case SMP_CMD_PAIRING_RSP:
Vinicius Costa Gomesda85e5e2011-06-09 18:50:53 -0300866 reason = smp_cmd_pairing_rsp(conn, skb);
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300867 break;
868
869 case SMP_CMD_SECURITY_REQ:
Vinicius Costa Gomesda85e5e2011-06-09 18:50:53 -0300870 reason = smp_cmd_security_req(conn, skb);
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300871 break;
872
Anderson Brigliaeb492e02011-06-09 18:50:40 -0300873 case SMP_CMD_PAIRING_CONFIRM:
Vinicius Costa Gomesda85e5e2011-06-09 18:50:53 -0300874 reason = smp_cmd_pairing_confirm(conn, skb);
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300875 break;
876
Anderson Brigliaeb492e02011-06-09 18:50:40 -0300877 case SMP_CMD_PAIRING_RANDOM:
Vinicius Costa Gomesda85e5e2011-06-09 18:50:53 -0300878 reason = smp_cmd_pairing_random(conn, skb);
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300879 break;
880
Anderson Brigliaeb492e02011-06-09 18:50:40 -0300881 case SMP_CMD_ENCRYPT_INFO:
Vinicius Costa Gomes7034b912011-07-07 18:59:34 -0300882 reason = smp_cmd_encrypt_info(conn, skb);
883 break;
884
Anderson Brigliaeb492e02011-06-09 18:50:40 -0300885 case SMP_CMD_MASTER_IDENT:
Vinicius Costa Gomes7034b912011-07-07 18:59:34 -0300886 reason = smp_cmd_master_ident(conn, skb);
887 break;
888
Anderson Brigliaeb492e02011-06-09 18:50:40 -0300889 case SMP_CMD_IDENT_INFO:
890 case SMP_CMD_IDENT_ADDR_INFO:
891 case SMP_CMD_SIGN_INFO:
Vinicius Costa Gomes7034b912011-07-07 18:59:34 -0300892 /* Just ignored */
893 reason = 0;
894 break;
895
Anderson Brigliaeb492e02011-06-09 18:50:40 -0300896 default:
897 BT_DBG("Unknown command code 0x%2.2x", code);
898
899 reason = SMP_CMD_NOTSUPP;
Vinicius Costa Gomes3a0259b2011-06-09 18:50:43 -0300900 err = -EOPNOTSUPP;
901 goto done;
902 }
903
904done:
905 if (reason)
Brian Gix4f957a72011-11-23 08:28:36 -0800906 smp_failure(conn, reason, 1);
Anderson Brigliaeb492e02011-06-09 18:50:40 -0300907
908 kfree_skb(skb);
909 return err;
910}
Vinicius Costa Gomes7034b912011-07-07 18:59:34 -0300911
912int smp_distribute_keys(struct l2cap_conn *conn, __u8 force)
913{
914 struct smp_cmd_pairing *req, *rsp;
Vinicius Costa Gomes1c1def02011-09-05 14:31:30 -0300915 struct smp_chan *smp = conn->smp_chan;
Vinicius Costa Gomes7034b912011-07-07 18:59:34 -0300916 __u8 *keydist;
917
918 BT_DBG("conn %p force %d", conn, force);
919
Johan Hedberg51a8efd2012-01-16 06:10:31 +0200920 if (!test_bit(HCI_CONN_LE_SMP_PEND, &conn->hcon->flags))
Vinicius Costa Gomesd26a2342011-08-19 21:06:51 -0300921 return 0;
922
Vinicius Costa Gomes1c1def02011-09-05 14:31:30 -0300923 rsp = (void *) &smp->prsp[1];
Vinicius Costa Gomes7034b912011-07-07 18:59:34 -0300924
925 /* The responder sends its keys first */
926 if (!force && conn->hcon->out && (rsp->resp_key_dist & 0x07))
927 return 0;
928
Vinicius Costa Gomes1c1def02011-09-05 14:31:30 -0300929 req = (void *) &smp->preq[1];
Vinicius Costa Gomes7034b912011-07-07 18:59:34 -0300930
931 if (conn->hcon->out) {
932 keydist = &rsp->init_key_dist;
933 *keydist &= req->init_key_dist;
934 } else {
935 keydist = &rsp->resp_key_dist;
936 *keydist &= req->resp_key_dist;
937 }
938
939
940 BT_DBG("keydist 0x%x", *keydist);
941
942 if (*keydist & SMP_DIST_ENC_KEY) {
943 struct smp_cmd_encrypt_info enc;
944 struct smp_cmd_master_ident ident;
Vinicius Costa Gomesc9839a12012-02-02 21:08:01 -0300945 struct hci_conn *hcon = conn->hcon;
946 u8 authenticated;
Vinicius Costa Gomes7034b912011-07-07 18:59:34 -0300947 __le16 ediv;
948
949 get_random_bytes(enc.ltk, sizeof(enc.ltk));
950 get_random_bytes(&ediv, sizeof(ediv));
951 get_random_bytes(ident.rand, sizeof(ident.rand));
952
953 smp_send_cmd(conn, SMP_CMD_ENCRYPT_INFO, sizeof(enc), &enc);
954
Vinicius Costa Gomesc9839a12012-02-02 21:08:01 -0300955 authenticated = hcon->sec_level == BT_SECURITY_HIGH;
956 hci_add_ltk(conn->hcon->hdev, conn->dst, hcon->dst_type,
957 HCI_SMP_LTK_SLAVE, 1, authenticated,
958 enc.ltk, smp->enc_key_size,
959 ediv, ident.rand);
Vinicius Costa Gomes16b90832011-07-07 18:59:39 -0300960
Vinicius Costa Gomes7034b912011-07-07 18:59:34 -0300961 ident.ediv = cpu_to_le16(ediv);
962
963 smp_send_cmd(conn, SMP_CMD_MASTER_IDENT, sizeof(ident), &ident);
964
965 *keydist &= ~SMP_DIST_ENC_KEY;
966 }
967
968 if (*keydist & SMP_DIST_ID_KEY) {
969 struct smp_cmd_ident_addr_info addrinfo;
970 struct smp_cmd_ident_info idinfo;
971
972 /* Send a dummy key */
973 get_random_bytes(idinfo.irk, sizeof(idinfo.irk));
974
975 smp_send_cmd(conn, SMP_CMD_IDENT_INFO, sizeof(idinfo), &idinfo);
976
977 /* Just public address */
978 memset(&addrinfo, 0, sizeof(addrinfo));
979 bacpy(&addrinfo.bdaddr, conn->src);
980
981 smp_send_cmd(conn, SMP_CMD_IDENT_ADDR_INFO, sizeof(addrinfo),
982 &addrinfo);
983
984 *keydist &= ~SMP_DIST_ID_KEY;
985 }
986
987 if (*keydist & SMP_DIST_SIGN) {
988 struct smp_cmd_sign_info sign;
989
990 /* Send a dummy key */
991 get_random_bytes(sign.csrk, sizeof(sign.csrk));
992
993 smp_send_cmd(conn, SMP_CMD_SIGN_INFO, sizeof(sign), &sign);
994
995 *keydist &= ~SMP_DIST_SIGN;
996 }
997
Vinicius Costa Gomesd26a2342011-08-19 21:06:51 -0300998 if (conn->hcon->out || force) {
Johan Hedberg51a8efd2012-01-16 06:10:31 +0200999 clear_bit(HCI_CONN_LE_SMP_PEND, &conn->hcon->flags);
Gustavo F. Padovan6c9d42a2011-12-20 10:57:27 -02001000 cancel_delayed_work_sync(&conn->security_timer);
Vinicius Costa Gomes8aab4752011-09-05 14:31:31 -03001001 smp_chan_destroy(conn);
Vinicius Costa Gomesd26a2342011-08-19 21:06:51 -03001002 }
1003
Vinicius Costa Gomes7034b912011-07-07 18:59:34 -03001004 return 0;
1005}