blob: 06a082ea903e3992779a1f7f60881ee67cc37234 [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
Gustavo Padovan8c520a52012-05-23 04:04:22 -030023#include <linux/crypto.h>
24#include <linux/scatterlist.h>
25#include <crypto/b128ops.h>
26
Anderson Brigliaeb492e02011-06-09 18:50:40 -030027#include <net/bluetooth/bluetooth.h>
28#include <net/bluetooth/hci_core.h>
29#include <net/bluetooth/l2cap.h>
Brian Gix2b64d152011-12-21 16:12:12 -080030#include <net/bluetooth/mgmt.h>
Marcel Holtmannac4b7232013-10-10 14:54:16 -070031
32#include "smp.h"
Anderson Brigliad22ef0b2011-06-09 18:50:44 -030033
Marcel Holtmann17b02e62012-03-01 14:32:37 -080034#define SMP_TIMEOUT msecs_to_jiffies(30000)
Vinicius Costa Gomes5d3de7d2011-06-14 13:37:41 -030035
Johan Hedberg065a13e2012-10-11 16:26:06 +020036#define AUTH_REQ_MASK 0x07
37
Anderson Brigliad22ef0b2011-06-09 18:50:44 -030038static inline void swap128(u8 src[16], u8 dst[16])
39{
40 int i;
41 for (i = 0; i < 16; i++)
42 dst[15 - i] = src[i];
43}
44
45static inline void swap56(u8 src[7], u8 dst[7])
46{
47 int i;
48 for (i = 0; i < 7; i++)
49 dst[6 - i] = src[i];
50}
51
52static int smp_e(struct crypto_blkcipher *tfm, const u8 *k, u8 *r)
53{
54 struct blkcipher_desc desc;
55 struct scatterlist sg;
56 int err, iv_len;
57 unsigned char iv[128];
58
59 if (tfm == NULL) {
60 BT_ERR("tfm %p", tfm);
61 return -EINVAL;
62 }
63
64 desc.tfm = tfm;
65 desc.flags = 0;
66
67 err = crypto_blkcipher_setkey(tfm, k, 16);
68 if (err) {
69 BT_ERR("cipher setkey failed: %d", err);
70 return err;
71 }
72
73 sg_init_one(&sg, r, 16);
74
75 iv_len = crypto_blkcipher_ivsize(tfm);
76 if (iv_len) {
77 memset(&iv, 0xff, iv_len);
78 crypto_blkcipher_set_iv(tfm, iv, iv_len);
79 }
80
81 err = crypto_blkcipher_encrypt(&desc, &sg, &sg, 16);
82 if (err)
83 BT_ERR("Encrypt data error %d", err);
84
85 return err;
86}
87
88static int smp_c1(struct crypto_blkcipher *tfm, u8 k[16], u8 r[16],
89 u8 preq[7], u8 pres[7], u8 _iat, bdaddr_t *ia,
90 u8 _rat, bdaddr_t *ra, u8 res[16])
91{
92 u8 p1[16], p2[16];
93 int err;
94
95 memset(p1, 0, 16);
96
97 /* p1 = pres || preq || _rat || _iat */
98 swap56(pres, p1);
99 swap56(preq, p1 + 7);
100 p1[14] = _rat;
101 p1[15] = _iat;
102
103 memset(p2, 0, 16);
104
105 /* p2 = padding || ia || ra */
106 baswap((bdaddr_t *) (p2 + 4), ia);
107 baswap((bdaddr_t *) (p2 + 10), ra);
108
109 /* res = r XOR p1 */
110 u128_xor((u128 *) res, (u128 *) r, (u128 *) p1);
111
112 /* res = e(k, res) */
113 err = smp_e(tfm, k, res);
114 if (err) {
115 BT_ERR("Encrypt data error");
116 return err;
117 }
118
119 /* res = res XOR p2 */
120 u128_xor((u128 *) res, (u128 *) res, (u128 *) p2);
121
122 /* res = e(k, res) */
123 err = smp_e(tfm, k, res);
124 if (err)
125 BT_ERR("Encrypt data error");
126
127 return err;
128}
129
130static int smp_s1(struct crypto_blkcipher *tfm, u8 k[16],
131 u8 r1[16], u8 r2[16], u8 _r[16])
132{
133 int err;
134
135 /* Just least significant octets from r1 and r2 are considered */
136 memcpy(_r, r1 + 8, 8);
137 memcpy(_r + 8, r2 + 8, 8);
138
139 err = smp_e(tfm, k, _r);
140 if (err)
141 BT_ERR("Encrypt data error");
142
143 return err;
144}
145
146static int smp_rand(u8 *buf)
147{
148 get_random_bytes(buf, 16);
149
150 return 0;
151}
Anderson Brigliaeb492e02011-06-09 18:50:40 -0300152
153static struct sk_buff *smp_build_cmd(struct l2cap_conn *conn, u8 code,
154 u16 dlen, void *data)
155{
156 struct sk_buff *skb;
157 struct l2cap_hdr *lh;
158 int len;
159
160 len = L2CAP_HDR_SIZE + sizeof(code) + dlen;
161
162 if (len > conn->mtu)
163 return NULL;
164
165 skb = bt_skb_alloc(len, GFP_ATOMIC);
166 if (!skb)
167 return NULL;
168
169 lh = (struct l2cap_hdr *) skb_put(skb, L2CAP_HDR_SIZE);
170 lh->len = cpu_to_le16(sizeof(code) + dlen);
Syam Sidhardhand8aece22012-10-10 22:09:28 +0530171 lh->cid = __constant_cpu_to_le16(L2CAP_CID_SMP);
Anderson Brigliaeb492e02011-06-09 18:50:40 -0300172
173 memcpy(skb_put(skb, sizeof(code)), &code, sizeof(code));
174
175 memcpy(skb_put(skb, dlen), data, dlen);
176
177 return skb;
178}
179
180static void smp_send_cmd(struct l2cap_conn *conn, u8 code, u16 len, void *data)
181{
182 struct sk_buff *skb = smp_build_cmd(conn, code, len, data);
183
184 BT_DBG("code 0x%2.2x", code);
185
186 if (!skb)
187 return;
188
Luiz Augusto von Dentz73d80de2011-11-02 15:52:01 +0200189 skb->priority = HCI_PRIO_MAX;
190 hci_send_acl(conn->hchan, skb, 0);
Vinicius Costa Gomese2dcd112011-08-19 21:06:50 -0300191
Gustavo F. Padovan6c9d42a2011-12-20 10:57:27 -0200192 cancel_delayed_work_sync(&conn->security_timer);
Marcel Holtmann17b02e62012-03-01 14:32:37 -0800193 schedule_delayed_work(&conn->security_timer, SMP_TIMEOUT);
Anderson Brigliaeb492e02011-06-09 18:50:40 -0300194}
195
Brian Gix2b64d152011-12-21 16:12:12 -0800196static __u8 authreq_to_seclevel(__u8 authreq)
197{
198 if (authreq & SMP_AUTH_MITM)
199 return BT_SECURITY_HIGH;
200 else
201 return BT_SECURITY_MEDIUM;
202}
203
204static __u8 seclevel_to_authreq(__u8 sec_level)
205{
206 switch (sec_level) {
207 case BT_SECURITY_HIGH:
208 return SMP_AUTH_MITM | SMP_AUTH_BONDING;
209 case BT_SECURITY_MEDIUM:
210 return SMP_AUTH_BONDING;
211 default:
212 return SMP_AUTH_NONE;
213 }
214}
215
Vinicius Costa Gomesb8e66ea2011-06-09 18:50:52 -0300216static void build_pairing_cmd(struct l2cap_conn *conn,
Vinicius Costa Gomes54790f72011-07-07 18:59:38 -0300217 struct smp_cmd_pairing *req,
218 struct smp_cmd_pairing *rsp,
219 __u8 authreq)
Vinicius Costa Gomesb8e66ea2011-06-09 18:50:52 -0300220{
Brian Gix2b64d152011-12-21 16:12:12 -0800221 u8 dist_keys = 0;
Vinicius Costa Gomes54790f72011-07-07 18:59:38 -0300222
Johan Hedberga8b2d5c2012-01-08 23:11:15 +0200223 if (test_bit(HCI_PAIRABLE, &conn->hcon->hdev->dev_flags)) {
Vinicius Costa Gomesca10b5e2011-08-25 20:02:37 -0300224 dist_keys = SMP_DIST_ENC_KEY;
Vinicius Costa Gomes54790f72011-07-07 18:59:38 -0300225 authreq |= SMP_AUTH_BONDING;
Brian Gix2b64d152011-12-21 16:12:12 -0800226 } else {
227 authreq &= ~SMP_AUTH_BONDING;
Vinicius Costa Gomes54790f72011-07-07 18:59:38 -0300228 }
229
230 if (rsp == NULL) {
231 req->io_capability = conn->hcon->io_capability;
232 req->oob_flag = SMP_OOB_NOT_PRESENT;
233 req->max_key_size = SMP_MAX_ENC_KEY_SIZE;
Brian Gix2b64d152011-12-21 16:12:12 -0800234 req->init_key_dist = 0;
Vinicius Costa Gomes54790f72011-07-07 18:59:38 -0300235 req->resp_key_dist = dist_keys;
Johan Hedberg065a13e2012-10-11 16:26:06 +0200236 req->auth_req = (authreq & AUTH_REQ_MASK);
Vinicius Costa Gomes54790f72011-07-07 18:59:38 -0300237 return;
238 }
239
240 rsp->io_capability = conn->hcon->io_capability;
241 rsp->oob_flag = SMP_OOB_NOT_PRESENT;
242 rsp->max_key_size = SMP_MAX_ENC_KEY_SIZE;
Brian Gix2b64d152011-12-21 16:12:12 -0800243 rsp->init_key_dist = 0;
Vinicius Costa Gomes54790f72011-07-07 18:59:38 -0300244 rsp->resp_key_dist = req->resp_key_dist & dist_keys;
Johan Hedberg065a13e2012-10-11 16:26:06 +0200245 rsp->auth_req = (authreq & AUTH_REQ_MASK);
Vinicius Costa Gomesb8e66ea2011-06-09 18:50:52 -0300246}
247
Vinicius Costa Gomes3158c502011-06-14 13:37:42 -0300248static u8 check_enc_key_size(struct l2cap_conn *conn, __u8 max_key_size)
249{
Vinicius Costa Gomes1c1def02011-09-05 14:31:30 -0300250 struct smp_chan *smp = conn->smp_chan;
251
Vinicius Costa Gomes3158c502011-06-14 13:37:42 -0300252 if ((max_key_size > SMP_MAX_ENC_KEY_SIZE) ||
253 (max_key_size < SMP_MIN_ENC_KEY_SIZE))
254 return SMP_ENC_KEY_SIZE;
255
Vinicius Costa Gomesf7aa6112012-01-30 19:29:12 -0300256 smp->enc_key_size = max_key_size;
Vinicius Costa Gomes3158c502011-06-14 13:37:42 -0300257
258 return 0;
259}
260
Brian Gix4f957a72011-11-23 08:28:36 -0800261static void smp_failure(struct l2cap_conn *conn, u8 reason, u8 send)
262{
Johan Hedbergbab73cb2012-02-09 16:07:29 +0200263 struct hci_conn *hcon = conn->hcon;
264
Brian Gix4f957a72011-11-23 08:28:36 -0800265 if (send)
266 smp_send_cmd(conn, SMP_CMD_PAIRING_FAIL, sizeof(reason),
267 &reason);
268
Marcel Holtmannce39fb42013-10-13 02:23:39 -0700269 clear_bit(HCI_CONN_ENCRYPT_PEND, &hcon->flags);
270 mgmt_auth_failed(hcon->hdev, &hcon->dst, hcon->type, hcon->dst_type,
271 HCI_ERROR_AUTH_FAILURE);
Vinicius Costa Gomesf1c09c02012-02-01 18:27:56 -0300272
Andre Guedes61a0cfb2012-08-01 20:34:15 -0300273 cancel_delayed_work_sync(&conn->security_timer);
274
Marcel Holtmannce39fb42013-10-13 02:23:39 -0700275 if (test_and_clear_bit(HCI_CONN_LE_SMP_PEND, &hcon->flags))
Vinicius Costa Gomesf1c09c02012-02-01 18:27:56 -0300276 smp_chan_destroy(conn);
Brian Gix4f957a72011-11-23 08:28:36 -0800277}
278
Brian Gix2b64d152011-12-21 16:12:12 -0800279#define JUST_WORKS 0x00
280#define JUST_CFM 0x01
281#define REQ_PASSKEY 0x02
282#define CFM_PASSKEY 0x03
283#define REQ_OOB 0x04
284#define OVERLAP 0xFF
285
286static const u8 gen_method[5][5] = {
287 { JUST_WORKS, JUST_CFM, REQ_PASSKEY, JUST_WORKS, REQ_PASSKEY },
288 { JUST_WORKS, JUST_CFM, REQ_PASSKEY, JUST_WORKS, REQ_PASSKEY },
289 { CFM_PASSKEY, CFM_PASSKEY, REQ_PASSKEY, JUST_WORKS, CFM_PASSKEY },
290 { JUST_WORKS, JUST_CFM, JUST_WORKS, JUST_WORKS, JUST_CFM },
291 { CFM_PASSKEY, CFM_PASSKEY, REQ_PASSKEY, JUST_WORKS, OVERLAP },
292};
293
294static int tk_request(struct l2cap_conn *conn, u8 remote_oob, u8 auth,
295 u8 local_io, u8 remote_io)
296{
297 struct hci_conn *hcon = conn->hcon;
298 struct smp_chan *smp = conn->smp_chan;
299 u8 method;
300 u32 passkey = 0;
301 int ret = 0;
302
303 /* Initialize key for JUST WORKS */
304 memset(smp->tk, 0, sizeof(smp->tk));
305 clear_bit(SMP_FLAG_TK_VALID, &smp->smp_flags);
306
307 BT_DBG("tk_request: auth:%d lcl:%d rem:%d", auth, local_io, remote_io);
308
309 /* If neither side wants MITM, use JUST WORKS */
310 /* If either side has unknown io_caps, use JUST WORKS */
311 /* Otherwise, look up method from the table */
312 if (!(auth & SMP_AUTH_MITM) ||
313 local_io > SMP_IO_KEYBOARD_DISPLAY ||
314 remote_io > SMP_IO_KEYBOARD_DISPLAY)
315 method = JUST_WORKS;
316 else
Ido Yarivb3ff53f2012-03-05 20:07:08 +0200317 method = gen_method[remote_io][local_io];
Brian Gix2b64d152011-12-21 16:12:12 -0800318
319 /* If not bonding, don't ask user to confirm a Zero TK */
320 if (!(auth & SMP_AUTH_BONDING) && method == JUST_CFM)
321 method = JUST_WORKS;
322
323 /* If Just Works, Continue with Zero TK */
324 if (method == JUST_WORKS) {
325 set_bit(SMP_FLAG_TK_VALID, &smp->smp_flags);
326 return 0;
327 }
328
329 /* Not Just Works/Confirm results in MITM Authentication */
330 if (method != JUST_CFM)
331 set_bit(SMP_FLAG_MITM_AUTH, &smp->smp_flags);
332
333 /* If both devices have Keyoard-Display I/O, the master
334 * Confirms and the slave Enters the passkey.
335 */
336 if (method == OVERLAP) {
337 if (hcon->link_mode & HCI_LM_MASTER)
338 method = CFM_PASSKEY;
339 else
340 method = REQ_PASSKEY;
341 }
342
343 /* Generate random passkey. Not valid until confirmed. */
344 if (method == CFM_PASSKEY) {
345 u8 key[16];
346
347 memset(key, 0, sizeof(key));
348 get_random_bytes(&passkey, sizeof(passkey));
349 passkey %= 1000000;
350 put_unaligned_le32(passkey, key);
351 swap128(key, smp->tk);
352 BT_DBG("PassKey: %d", passkey);
353 }
354
355 hci_dev_lock(hcon->hdev);
356
357 if (method == REQ_PASSKEY)
Marcel Holtmannce39fb42013-10-13 02:23:39 -0700358 ret = mgmt_user_passkey_request(hcon->hdev, &hcon->dst,
Johan Hedberg272d90d2012-02-09 15:26:12 +0200359 hcon->type, hcon->dst_type);
Brian Gix2b64d152011-12-21 16:12:12 -0800360 else
Marcel Holtmannce39fb42013-10-13 02:23:39 -0700361 ret = mgmt_user_confirm_request(hcon->hdev, &hcon->dst,
Johan Hedberg272d90d2012-02-09 15:26:12 +0200362 hcon->type, hcon->dst_type,
Brian Gix2b64d152011-12-21 16:12:12 -0800363 cpu_to_le32(passkey), 0);
364
365 hci_dev_unlock(hcon->hdev);
366
367 return ret;
368}
369
Vinicius Costa Gomes8aab4752011-09-05 14:31:31 -0300370static void confirm_work(struct work_struct *work)
371{
372 struct smp_chan *smp = container_of(work, struct smp_chan, confirm);
373 struct l2cap_conn *conn = smp->conn;
374 struct crypto_blkcipher *tfm;
375 struct smp_cmd_pairing_confirm cp;
376 int ret;
377 u8 res[16], reason;
378
379 BT_DBG("conn %p", conn);
380
381 tfm = crypto_alloc_blkcipher("ecb(aes)", 0, CRYPTO_ALG_ASYNC);
382 if (IS_ERR(tfm)) {
383 reason = SMP_UNSPECIFIED;
384 goto error;
385 }
386
387 smp->tfm = tfm;
388
389 if (conn->hcon->out)
390 ret = smp_c1(tfm, smp->tk, smp->prnd, smp->preq, smp->prsp, 0,
Marcel Holtmannce39fb42013-10-13 02:23:39 -0700391 &conn->hcon->hdev->bdaddr, conn->hcon->dst_type,
392 &conn->hcon->dst, res);
Vinicius Costa Gomes8aab4752011-09-05 14:31:31 -0300393 else
394 ret = smp_c1(tfm, smp->tk, smp->prnd, smp->preq, smp->prsp,
Marcel Holtmannce39fb42013-10-13 02:23:39 -0700395 conn->hcon->dst_type, &conn->hcon->dst, 0,
396 &conn->hcon->hdev->bdaddr, res);
Vinicius Costa Gomes8aab4752011-09-05 14:31:31 -0300397 if (ret) {
398 reason = SMP_UNSPECIFIED;
399 goto error;
400 }
401
Brian Gix2b64d152011-12-21 16:12:12 -0800402 clear_bit(SMP_FLAG_CFM_PENDING, &smp->smp_flags);
403
Vinicius Costa Gomes8aab4752011-09-05 14:31:31 -0300404 swap128(res, cp.confirm_val);
405 smp_send_cmd(smp->conn, SMP_CMD_PAIRING_CONFIRM, sizeof(cp), &cp);
406
407 return;
408
409error:
Brian Gix4f957a72011-11-23 08:28:36 -0800410 smp_failure(conn, reason, 1);
Vinicius Costa Gomes8aab4752011-09-05 14:31:31 -0300411}
412
413static void random_work(struct work_struct *work)
414{
415 struct smp_chan *smp = container_of(work, struct smp_chan, random);
416 struct l2cap_conn *conn = smp->conn;
417 struct hci_conn *hcon = conn->hcon;
418 struct crypto_blkcipher *tfm = smp->tfm;
419 u8 reason, confirm[16], res[16], key[16];
420 int ret;
421
422 if (IS_ERR_OR_NULL(tfm)) {
423 reason = SMP_UNSPECIFIED;
424 goto error;
425 }
426
427 BT_DBG("conn %p %s", conn, conn->hcon->out ? "master" : "slave");
428
429 if (hcon->out)
430 ret = smp_c1(tfm, smp->tk, smp->rrnd, smp->preq, smp->prsp, 0,
Marcel Holtmannce39fb42013-10-13 02:23:39 -0700431 &hcon->hdev->bdaddr, hcon->dst_type, &hcon->dst,
432 res);
Vinicius Costa Gomes8aab4752011-09-05 14:31:31 -0300433 else
434 ret = smp_c1(tfm, smp->tk, smp->rrnd, smp->preq, smp->prsp,
Marcel Holtmannce39fb42013-10-13 02:23:39 -0700435 hcon->dst_type, &hcon->dst, 0, &hcon->hdev->bdaddr,
436 res);
Vinicius Costa Gomes8aab4752011-09-05 14:31:31 -0300437 if (ret) {
438 reason = SMP_UNSPECIFIED;
439 goto error;
440 }
441
442 swap128(res, confirm);
443
444 if (memcmp(smp->pcnf, confirm, sizeof(smp->pcnf)) != 0) {
445 BT_ERR("Pairing failed (confirmation values mismatch)");
446 reason = SMP_CONFIRM_FAILED;
447 goto error;
448 }
449
450 if (hcon->out) {
451 u8 stk[16], rand[8];
452 __le16 ediv;
453
454 memset(rand, 0, sizeof(rand));
455 ediv = 0;
456
457 smp_s1(tfm, smp->tk, smp->rrnd, smp->prnd, key);
458 swap128(key, stk);
459
Vinicius Costa Gomesf7aa6112012-01-30 19:29:12 -0300460 memset(stk + smp->enc_key_size, 0,
Gustavo F. Padovan04124682012-03-08 01:25:00 -0300461 SMP_MAX_ENC_KEY_SIZE - smp->enc_key_size);
Vinicius Costa Gomes8aab4752011-09-05 14:31:31 -0300462
Johan Hedberg51a8efd2012-01-16 06:10:31 +0200463 if (test_and_set_bit(HCI_CONN_ENCRYPT_PEND, &hcon->flags)) {
Vinicius Costa Gomes8aab4752011-09-05 14:31:31 -0300464 reason = SMP_UNSPECIFIED;
465 goto error;
466 }
467
468 hci_le_start_enc(hcon, ediv, rand, stk);
Vinicius Costa Gomesf7aa6112012-01-30 19:29:12 -0300469 hcon->enc_key_size = smp->enc_key_size;
Vinicius Costa Gomes8aab4752011-09-05 14:31:31 -0300470 } else {
471 u8 stk[16], r[16], rand[8];
472 __le16 ediv;
473
474 memset(rand, 0, sizeof(rand));
475 ediv = 0;
476
477 swap128(smp->prnd, r);
478 smp_send_cmd(conn, SMP_CMD_PAIRING_RANDOM, sizeof(r), r);
479
480 smp_s1(tfm, smp->tk, smp->prnd, smp->rrnd, key);
481 swap128(key, stk);
482
Vinicius Costa Gomesf7aa6112012-01-30 19:29:12 -0300483 memset(stk + smp->enc_key_size, 0,
484 SMP_MAX_ENC_KEY_SIZE - smp->enc_key_size);
Vinicius Costa Gomes8aab4752011-09-05 14:31:31 -0300485
Marcel Holtmannce39fb42013-10-13 02:23:39 -0700486 hci_add_ltk(hcon->hdev, &hcon->dst, hcon->dst_type,
Gustavo F. Padovan04124682012-03-08 01:25:00 -0300487 HCI_SMP_STK_SLAVE, 0, 0, stk, smp->enc_key_size,
488 ediv, rand);
Vinicius Costa Gomes8aab4752011-09-05 14:31:31 -0300489 }
490
491 return;
492
493error:
Brian Gix4f957a72011-11-23 08:28:36 -0800494 smp_failure(conn, reason, 1);
Vinicius Costa Gomes8aab4752011-09-05 14:31:31 -0300495}
496
497static struct smp_chan *smp_chan_create(struct l2cap_conn *conn)
498{
499 struct smp_chan *smp;
500
501 smp = kzalloc(sizeof(struct smp_chan), GFP_ATOMIC);
502 if (!smp)
503 return NULL;
504
505 INIT_WORK(&smp->confirm, confirm_work);
506 INIT_WORK(&smp->random, random_work);
507
508 smp->conn = conn;
509 conn->smp_chan = smp;
Brian Gix2b64d152011-12-21 16:12:12 -0800510 conn->hcon->smp_conn = conn;
Vinicius Costa Gomes8aab4752011-09-05 14:31:31 -0300511
512 hci_conn_hold(conn->hcon);
513
514 return smp;
515}
516
517void smp_chan_destroy(struct l2cap_conn *conn)
518{
Brian Gixc8eb9692011-11-23 08:28:35 -0800519 struct smp_chan *smp = conn->smp_chan;
520
Vinicius Costa Gomesf1c09c02012-02-01 18:27:56 -0300521 BUG_ON(!smp);
Brian Gixc8eb9692011-11-23 08:28:35 -0800522
523 if (smp->tfm)
524 crypto_free_blkcipher(smp->tfm);
525
526 kfree(smp);
527 conn->smp_chan = NULL;
Brian Gix2b64d152011-12-21 16:12:12 -0800528 conn->hcon->smp_conn = NULL;
David Herrmann76a68ba2013-04-06 20:28:37 +0200529 hci_conn_drop(conn->hcon);
Vinicius Costa Gomes8aab4752011-09-05 14:31:31 -0300530}
531
Brian Gix2b64d152011-12-21 16:12:12 -0800532int smp_user_confirm_reply(struct hci_conn *hcon, u16 mgmt_op, __le32 passkey)
533{
534 struct l2cap_conn *conn = hcon->smp_conn;
535 struct smp_chan *smp;
536 u32 value;
537 u8 key[16];
538
539 BT_DBG("");
540
541 if (!conn)
542 return -ENOTCONN;
543
544 smp = conn->smp_chan;
545
546 switch (mgmt_op) {
547 case MGMT_OP_USER_PASSKEY_REPLY:
548 value = le32_to_cpu(passkey);
549 memset(key, 0, sizeof(key));
550 BT_DBG("PassKey: %d", value);
551 put_unaligned_le32(value, key);
552 swap128(key, smp->tk);
553 /* Fall Through */
554 case MGMT_OP_USER_CONFIRM_REPLY:
555 set_bit(SMP_FLAG_TK_VALID, &smp->smp_flags);
556 break;
557 case MGMT_OP_USER_PASSKEY_NEG_REPLY:
558 case MGMT_OP_USER_CONFIRM_NEG_REPLY:
559 smp_failure(conn, SMP_PASSKEY_ENTRY_FAILED, 1);
560 return 0;
561 default:
562 smp_failure(conn, SMP_PASSKEY_ENTRY_FAILED, 1);
563 return -EOPNOTSUPP;
564 }
565
566 /* If it is our turn to send Pairing Confirm, do so now */
567 if (test_bit(SMP_FLAG_CFM_PENDING, &smp->smp_flags))
568 queue_work(hcon->hdev->workqueue, &smp->confirm);
569
570 return 0;
571}
572
Vinicius Costa Gomesda85e5e2011-06-09 18:50:53 -0300573static u8 smp_cmd_pairing_req(struct l2cap_conn *conn, struct sk_buff *skb)
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300574{
Vinicius Costa Gomes3158c502011-06-14 13:37:42 -0300575 struct smp_cmd_pairing rsp, *req = (void *) skb->data;
Vinicius Costa Gomes8aab4752011-09-05 14:31:31 -0300576 struct smp_chan *smp;
Vinicius Costa Gomes3158c502011-06-14 13:37:42 -0300577 u8 key_size;
Brian Gix2b64d152011-12-21 16:12:12 -0800578 u8 auth = SMP_AUTH_NONE;
Vinicius Costa Gomes8aab4752011-09-05 14:31:31 -0300579 int ret;
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300580
581 BT_DBG("conn %p", conn);
582
Brian Gix2b64d152011-12-21 16:12:12 -0800583 if (conn->hcon->link_mode & HCI_LM_MASTER)
584 return SMP_CMD_NOTSUPP;
585
Johan Hedberg51a8efd2012-01-16 06:10:31 +0200586 if (!test_and_set_bit(HCI_CONN_LE_SMP_PEND, &conn->hcon->flags))
Vinicius Costa Gomes8aab4752011-09-05 14:31:31 -0300587 smp = smp_chan_create(conn);
Andrei Emeltchenkod08fd0e2012-07-19 17:03:43 +0300588 else
589 smp = conn->smp_chan;
Vinicius Costa Gomes8aab4752011-09-05 14:31:31 -0300590
Andrei Emeltchenkod08fd0e2012-07-19 17:03:43 +0300591 if (!smp)
592 return SMP_UNSPECIFIED;
Vinicius Costa Gomesd26a2342011-08-19 21:06:51 -0300593
Vinicius Costa Gomes1c1def02011-09-05 14:31:30 -0300594 smp->preq[0] = SMP_CMD_PAIRING_REQ;
595 memcpy(&smp->preq[1], req, sizeof(*req));
Vinicius Costa Gomes3158c502011-06-14 13:37:42 -0300596 skb_pull(skb, sizeof(*req));
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300597
Brian Gix2b64d152011-12-21 16:12:12 -0800598 /* We didn't start the pairing, so match remote */
599 if (req->auth_req & SMP_AUTH_BONDING)
600 auth = req->auth_req;
Vinicius Costa Gomesda85e5e2011-06-09 18:50:53 -0300601
Ido Yarivfdde0a22012-03-05 20:09:38 +0200602 conn->hcon->pending_sec_level = authreq_to_seclevel(auth);
603
Brian Gix2b64d152011-12-21 16:12:12 -0800604 build_pairing_cmd(conn, req, &rsp, auth);
Vinicius Costa Gomes3158c502011-06-14 13:37:42 -0300605
606 key_size = min(req->max_key_size, rsp.max_key_size);
607 if (check_enc_key_size(conn, key_size))
608 return SMP_ENC_KEY_SIZE;
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300609
Vinicius Costa Gomes8aab4752011-09-05 14:31:31 -0300610 ret = smp_rand(smp->prnd);
611 if (ret)
612 return SMP_UNSPECIFIED;
613
Vinicius Costa Gomes1c1def02011-09-05 14:31:30 -0300614 smp->prsp[0] = SMP_CMD_PAIRING_RSP;
615 memcpy(&smp->prsp[1], &rsp, sizeof(rsp));
Anderson Brigliaf01ead32011-06-09 18:50:45 -0300616
Vinicius Costa Gomes3158c502011-06-14 13:37:42 -0300617 smp_send_cmd(conn, SMP_CMD_PAIRING_RSP, sizeof(rsp), &rsp);
Vinicius Costa Gomesda85e5e2011-06-09 18:50:53 -0300618
Brian Gix2b64d152011-12-21 16:12:12 -0800619 /* Request setup of TK */
620 ret = tk_request(conn, 0, auth, rsp.io_capability, req->io_capability);
621 if (ret)
622 return SMP_UNSPECIFIED;
623
Vinicius Costa Gomesda85e5e2011-06-09 18:50:53 -0300624 return 0;
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300625}
626
Vinicius Costa Gomesda85e5e2011-06-09 18:50:53 -0300627static u8 smp_cmd_pairing_rsp(struct l2cap_conn *conn, struct sk_buff *skb)
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300628{
Vinicius Costa Gomes3158c502011-06-14 13:37:42 -0300629 struct smp_cmd_pairing *req, *rsp = (void *) skb->data;
Vinicius Costa Gomes1c1def02011-09-05 14:31:30 -0300630 struct smp_chan *smp = conn->smp_chan;
Vinicius Costa Gomes8aab4752011-09-05 14:31:31 -0300631 struct hci_dev *hdev = conn->hcon->hdev;
Brian Gix2b64d152011-12-21 16:12:12 -0800632 u8 key_size, auth = SMP_AUTH_NONE;
Anderson Briglia7d24ddc2011-06-09 18:50:46 -0300633 int ret;
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300634
635 BT_DBG("conn %p", conn);
636
Brian Gix2b64d152011-12-21 16:12:12 -0800637 if (!(conn->hcon->link_mode & HCI_LM_MASTER))
638 return SMP_CMD_NOTSUPP;
639
Vinicius Costa Gomes3158c502011-06-14 13:37:42 -0300640 skb_pull(skb, sizeof(*rsp));
Vinicius Costa Gomesda85e5e2011-06-09 18:50:53 -0300641
Vinicius Costa Gomes1c1def02011-09-05 14:31:30 -0300642 req = (void *) &smp->preq[1];
Vinicius Costa Gomes3158c502011-06-14 13:37:42 -0300643
644 key_size = min(req->max_key_size, rsp->max_key_size);
645 if (check_enc_key_size(conn, key_size))
646 return SMP_ENC_KEY_SIZE;
647
Vinicius Costa Gomes1c1def02011-09-05 14:31:30 -0300648 ret = smp_rand(smp->prnd);
Anderson Briglia7d24ddc2011-06-09 18:50:46 -0300649 if (ret)
Vinicius Costa Gomesda85e5e2011-06-09 18:50:53 -0300650 return SMP_UNSPECIFIED;
Anderson Briglia7d24ddc2011-06-09 18:50:46 -0300651
Vinicius Costa Gomes8aab4752011-09-05 14:31:31 -0300652 smp->prsp[0] = SMP_CMD_PAIRING_RSP;
653 memcpy(&smp->prsp[1], rsp, sizeof(*rsp));
Anderson Briglia7d24ddc2011-06-09 18:50:46 -0300654
Brian Gix2b64d152011-12-21 16:12:12 -0800655 if ((req->auth_req & SMP_AUTH_BONDING) &&
656 (rsp->auth_req & SMP_AUTH_BONDING))
657 auth = SMP_AUTH_BONDING;
658
659 auth |= (req->auth_req | rsp->auth_req) & SMP_AUTH_MITM;
660
Johan Hedberg476585e2012-06-06 18:54:15 +0800661 ret = tk_request(conn, 0, auth, req->io_capability, rsp->io_capability);
Brian Gix2b64d152011-12-21 16:12:12 -0800662 if (ret)
663 return SMP_UNSPECIFIED;
664
665 set_bit(SMP_FLAG_CFM_PENDING, &smp->smp_flags);
666
667 /* Can't compose response until we have been confirmed */
668 if (!test_bit(SMP_FLAG_TK_VALID, &smp->smp_flags))
669 return 0;
670
Vinicius Costa Gomes8aab4752011-09-05 14:31:31 -0300671 queue_work(hdev->workqueue, &smp->confirm);
Vinicius Costa Gomesda85e5e2011-06-09 18:50:53 -0300672
673 return 0;
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300674}
675
Vinicius Costa Gomesda85e5e2011-06-09 18:50:53 -0300676static u8 smp_cmd_pairing_confirm(struct l2cap_conn *conn, struct sk_buff *skb)
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300677{
Vinicius Costa Gomes1c1def02011-09-05 14:31:30 -0300678 struct smp_chan *smp = conn->smp_chan;
Vinicius Costa Gomes8aab4752011-09-05 14:31:31 -0300679 struct hci_dev *hdev = conn->hcon->hdev;
Anderson Briglia7d24ddc2011-06-09 18:50:46 -0300680
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300681 BT_DBG("conn %p %s", conn, conn->hcon->out ? "master" : "slave");
682
Vinicius Costa Gomes1c1def02011-09-05 14:31:30 -0300683 memcpy(smp->pcnf, skb->data, sizeof(smp->pcnf));
684 skb_pull(skb, sizeof(smp->pcnf));
Anderson Briglia7d24ddc2011-06-09 18:50:46 -0300685
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300686 if (conn->hcon->out) {
Anderson Briglia7d24ddc2011-06-09 18:50:46 -0300687 u8 random[16];
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300688
Vinicius Costa Gomes1c1def02011-09-05 14:31:30 -0300689 swap128(smp->prnd, random);
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300690 smp_send_cmd(conn, SMP_CMD_PAIRING_RANDOM, sizeof(random),
Anderson Briglia7d24ddc2011-06-09 18:50:46 -0300691 random);
Brian Gix2b64d152011-12-21 16:12:12 -0800692 } else if (test_bit(SMP_FLAG_TK_VALID, &smp->smp_flags)) {
Vinicius Costa Gomes8aab4752011-09-05 14:31:31 -0300693 queue_work(hdev->workqueue, &smp->confirm);
Brian Gix2b64d152011-12-21 16:12:12 -0800694 } else {
695 set_bit(SMP_FLAG_CFM_PENDING, &smp->smp_flags);
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300696 }
Vinicius Costa Gomesda85e5e2011-06-09 18:50:53 -0300697
698 return 0;
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300699}
700
Vinicius Costa Gomesda85e5e2011-06-09 18:50:53 -0300701static u8 smp_cmd_pairing_random(struct l2cap_conn *conn, struct sk_buff *skb)
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300702{
Vinicius Costa Gomes1c1def02011-09-05 14:31:30 -0300703 struct smp_chan *smp = conn->smp_chan;
Vinicius Costa Gomes8aab4752011-09-05 14:31:31 -0300704 struct hci_dev *hdev = conn->hcon->hdev;
Anderson Briglia7d24ddc2011-06-09 18:50:46 -0300705
Vinicius Costa Gomes8aab4752011-09-05 14:31:31 -0300706 BT_DBG("conn %p", conn);
Anderson Briglia7d24ddc2011-06-09 18:50:46 -0300707
Vinicius Costa Gomes8aab4752011-09-05 14:31:31 -0300708 swap128(skb->data, smp->rrnd);
709 skb_pull(skb, sizeof(smp->rrnd));
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300710
Vinicius Costa Gomes8aab4752011-09-05 14:31:31 -0300711 queue_work(hdev->workqueue, &smp->random);
Vinicius Costa Gomesda85e5e2011-06-09 18:50:53 -0300712
713 return 0;
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300714}
715
Johan Hedberg4dab7862012-06-07 14:58:37 +0800716static u8 smp_ltk_encrypt(struct l2cap_conn *conn, u8 sec_level)
Vinicius Costa Gomes988c5992011-08-25 20:02:28 -0300717{
Vinicius Costa Gomesc9839a12012-02-02 21:08:01 -0300718 struct smp_ltk *key;
Vinicius Costa Gomes988c5992011-08-25 20:02:28 -0300719 struct hci_conn *hcon = conn->hcon;
720
Marcel Holtmannce39fb42013-10-13 02:23:39 -0700721 key = hci_find_ltk_by_addr(hcon->hdev, &hcon->dst, hcon->dst_type);
Vinicius Costa Gomes988c5992011-08-25 20:02:28 -0300722 if (!key)
723 return 0;
724
Johan Hedberg4dab7862012-06-07 14:58:37 +0800725 if (sec_level > BT_SECURITY_MEDIUM && !key->authenticated)
726 return 0;
727
Johan Hedberg51a8efd2012-01-16 06:10:31 +0200728 if (test_and_set_bit(HCI_CONN_ENCRYPT_PEND, &hcon->flags))
Vinicius Costa Gomes988c5992011-08-25 20:02:28 -0300729 return 1;
730
Vinicius Costa Gomesc9839a12012-02-02 21:08:01 -0300731 hci_le_start_enc(hcon, key->ediv, key->rand, key->val);
732 hcon->enc_key_size = key->enc_size;
Vinicius Costa Gomes988c5992011-08-25 20:02:28 -0300733
734 return 1;
735
736}
Vinicius Costa Gomesda85e5e2011-06-09 18:50:53 -0300737static u8 smp_cmd_security_req(struct l2cap_conn *conn, struct sk_buff *skb)
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300738{
739 struct smp_cmd_security_req *rp = (void *) skb->data;
740 struct smp_cmd_pairing cp;
Vinicius Costa Gomesf1cb9af2011-01-26 21:42:57 -0300741 struct hci_conn *hcon = conn->hcon;
Vinicius Costa Gomes8aab4752011-09-05 14:31:31 -0300742 struct smp_chan *smp;
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300743
744 BT_DBG("conn %p", conn);
745
Brian Gix2b64d152011-12-21 16:12:12 -0800746 hcon->pending_sec_level = authreq_to_seclevel(rp->auth_req);
Vinicius Costa Gomesfeb45eb2011-08-25 20:02:35 -0300747
Johan Hedberg4dab7862012-06-07 14:58:37 +0800748 if (smp_ltk_encrypt(conn, hcon->pending_sec_level))
Vinicius Costa Gomes988c5992011-08-25 20:02:28 -0300749 return 0;
750
Johan Hedberg51a8efd2012-01-16 06:10:31 +0200751 if (test_and_set_bit(HCI_CONN_LE_SMP_PEND, &hcon->flags))
Vinicius Costa Gomesda85e5e2011-06-09 18:50:53 -0300752 return 0;
Vinicius Costa Gomesf1cb9af2011-01-26 21:42:57 -0300753
Vinicius Costa Gomes8aab4752011-09-05 14:31:31 -0300754 smp = smp_chan_create(conn);
Vinicius Costa Gomesd26a2342011-08-19 21:06:51 -0300755
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300756 skb_pull(skb, sizeof(*rp));
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300757
Vinicius Costa Gomesda85e5e2011-06-09 18:50:53 -0300758 memset(&cp, 0, sizeof(cp));
Vinicius Costa Gomes54790f72011-07-07 18:59:38 -0300759 build_pairing_cmd(conn, &cp, NULL, rp->auth_req);
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300760
Vinicius Costa Gomes1c1def02011-09-05 14:31:30 -0300761 smp->preq[0] = SMP_CMD_PAIRING_REQ;
762 memcpy(&smp->preq[1], &cp, sizeof(cp));
Anderson Brigliaf01ead32011-06-09 18:50:45 -0300763
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300764 smp_send_cmd(conn, SMP_CMD_PAIRING_REQ, sizeof(cp), &cp);
Vinicius Costa Gomesf1cb9af2011-01-26 21:42:57 -0300765
Vinicius Costa Gomesda85e5e2011-06-09 18:50:53 -0300766 return 0;
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300767}
768
Vinicius Costa Gomescc110922012-08-23 21:32:43 -0300769int smp_conn_security(struct hci_conn *hcon, __u8 sec_level)
Anderson Brigliaeb492e02011-06-09 18:50:40 -0300770{
Vinicius Costa Gomescc110922012-08-23 21:32:43 -0300771 struct l2cap_conn *conn = hcon->l2cap_data;
Vinicius Costa Gomes1c1def02011-09-05 14:31:30 -0300772 struct smp_chan *smp = conn->smp_chan;
Brian Gix2b64d152011-12-21 16:12:12 -0800773 __u8 authreq;
Anderson Brigliaeb492e02011-06-09 18:50:40 -0300774
Vinicius Costa Gomes3a0259b2011-06-09 18:50:43 -0300775 BT_DBG("conn %p hcon %p level 0x%2.2x", conn, hcon, sec_level);
776
Johan Hedberg757aee02013-04-24 13:05:32 +0300777 if (!test_bit(HCI_LE_ENABLED, &hcon->hdev->dev_flags))
Andre Guedes2e65c9d2011-06-30 19:20:56 -0300778 return 1;
779
Vinicius Costa Gomesf1cb9af2011-01-26 21:42:57 -0300780 if (sec_level == BT_SECURITY_LOW)
Anderson Brigliaeb492e02011-06-09 18:50:40 -0300781 return 1;
Vinicius Costa Gomesf1cb9af2011-01-26 21:42:57 -0300782
783 if (hcon->sec_level >= sec_level)
784 return 1;
785
Vinicius Costa Gomes988c5992011-08-25 20:02:28 -0300786 if (hcon->link_mode & HCI_LM_MASTER)
Johan Hedberg4dab7862012-06-07 14:58:37 +0800787 if (smp_ltk_encrypt(conn, sec_level))
Vinicius Costa Gomes02bc7452011-07-07 18:59:41 -0300788 goto done;
Vinicius Costa Gomesd26a2342011-08-19 21:06:51 -0300789
Johan Hedberg51a8efd2012-01-16 06:10:31 +0200790 if (test_and_set_bit(HCI_CONN_LE_SMP_PEND, &hcon->flags))
Vinicius Costa Gomesd26a2342011-08-19 21:06:51 -0300791 return 0;
792
Vinicius Costa Gomes8aab4752011-09-05 14:31:31 -0300793 smp = smp_chan_create(conn);
Brian Gix2b64d152011-12-21 16:12:12 -0800794 if (!smp)
795 return 1;
796
797 authreq = seclevel_to_authreq(sec_level);
Vinicius Costa Gomesd26a2342011-08-19 21:06:51 -0300798
Vinicius Costa Gomesd26a2342011-08-19 21:06:51 -0300799 if (hcon->link_mode & HCI_LM_MASTER) {
800 struct smp_cmd_pairing cp;
Anderson Brigliaf01ead32011-06-09 18:50:45 -0300801
Brian Gix2b64d152011-12-21 16:12:12 -0800802 build_pairing_cmd(conn, &cp, NULL, authreq);
Vinicius Costa Gomes1c1def02011-09-05 14:31:30 -0300803 smp->preq[0] = SMP_CMD_PAIRING_REQ;
804 memcpy(&smp->preq[1], &cp, sizeof(cp));
Anderson Brigliaf01ead32011-06-09 18:50:45 -0300805
Anderson Brigliaeb492e02011-06-09 18:50:40 -0300806 smp_send_cmd(conn, SMP_CMD_PAIRING_REQ, sizeof(cp), &cp);
807 } else {
808 struct smp_cmd_security_req cp;
Brian Gix2b64d152011-12-21 16:12:12 -0800809 cp.auth_req = authreq;
Anderson Brigliaeb492e02011-06-09 18:50:40 -0300810 smp_send_cmd(conn, SMP_CMD_SECURITY_REQ, sizeof(cp), &cp);
811 }
812
Vinicius Costa Gomes02bc7452011-07-07 18:59:41 -0300813done:
Vinicius Costa Gomesf1cb9af2011-01-26 21:42:57 -0300814 hcon->pending_sec_level = sec_level;
Vinicius Costa Gomesf1cb9af2011-01-26 21:42:57 -0300815
Anderson Brigliaeb492e02011-06-09 18:50:40 -0300816 return 0;
817}
818
Vinicius Costa Gomes7034b912011-07-07 18:59:34 -0300819static int smp_cmd_encrypt_info(struct l2cap_conn *conn, struct sk_buff *skb)
820{
Vinicius Costa Gomes16b90832011-07-07 18:59:39 -0300821 struct smp_cmd_encrypt_info *rp = (void *) skb->data;
Vinicius Costa Gomes1c1def02011-09-05 14:31:30 -0300822 struct smp_chan *smp = conn->smp_chan;
Vinicius Costa Gomes16b90832011-07-07 18:59:39 -0300823
824 skb_pull(skb, sizeof(*rp));
825
Vinicius Costa Gomes1c1def02011-09-05 14:31:30 -0300826 memcpy(smp->tk, rp->ltk, sizeof(smp->tk));
Vinicius Costa Gomes16b90832011-07-07 18:59:39 -0300827
Vinicius Costa Gomes7034b912011-07-07 18:59:34 -0300828 return 0;
829}
830
831static int smp_cmd_master_ident(struct l2cap_conn *conn, struct sk_buff *skb)
832{
Vinicius Costa Gomes16b90832011-07-07 18:59:39 -0300833 struct smp_cmd_master_ident *rp = (void *) skb->data;
Vinicius Costa Gomes1c1def02011-09-05 14:31:30 -0300834 struct smp_chan *smp = conn->smp_chan;
Vinicius Costa Gomesc9839a12012-02-02 21:08:01 -0300835 struct hci_dev *hdev = conn->hcon->hdev;
836 struct hci_conn *hcon = conn->hcon;
837 u8 authenticated;
Vinicius Costa Gomes7034b912011-07-07 18:59:34 -0300838
Vinicius Costa Gomes16b90832011-07-07 18:59:39 -0300839 skb_pull(skb, sizeof(*rp));
840
Vinicius Costa Gomesc9839a12012-02-02 21:08:01 -0300841 hci_dev_lock(hdev);
Marcel Holtmannce39fb42013-10-13 02:23:39 -0700842 authenticated = (hcon->sec_level == BT_SECURITY_HIGH);
843 hci_add_ltk(hdev, &hcon->dst, hcon->dst_type, HCI_SMP_LTK, 1,
844 authenticated, smp->tk, smp->enc_key_size,
Gustavo F. Padovan04124682012-03-08 01:25:00 -0300845 rp->ediv, rp->rand);
Vinicius Costa Gomes7034b912011-07-07 18:59:34 -0300846 smp_distribute_keys(conn, 1);
Vinicius Costa Gomesc9839a12012-02-02 21:08:01 -0300847 hci_dev_unlock(hdev);
Vinicius Costa Gomes7034b912011-07-07 18:59:34 -0300848
849 return 0;
850}
851
Anderson Brigliaeb492e02011-06-09 18:50:40 -0300852int smp_sig_channel(struct l2cap_conn *conn, struct sk_buff *skb)
853{
Marcel Holtmann7b9899d2013-10-03 00:00:57 -0700854 struct hci_conn *hcon = conn->hcon;
Marcel Holtmann92381f52013-10-03 01:23:08 -0700855 __u8 code, reason;
Anderson Brigliaeb492e02011-06-09 18:50:40 -0300856 int err = 0;
857
Marcel Holtmann7b9899d2013-10-03 00:00:57 -0700858 if (hcon->type != LE_LINK) {
859 kfree_skb(skb);
860 return -ENOTSUPP;
861 }
862
Marcel Holtmann92381f52013-10-03 01:23:08 -0700863 if (skb->len < 1) {
864 kfree_skb(skb);
865 return -EILSEQ;
866 }
867
Johan Hedberg757aee02013-04-24 13:05:32 +0300868 if (!test_bit(HCI_LE_ENABLED, &conn->hcon->hdev->dev_flags)) {
Andre Guedes2e65c9d2011-06-30 19:20:56 -0300869 err = -ENOTSUPP;
870 reason = SMP_PAIRING_NOTSUPP;
871 goto done;
872 }
873
Marcel Holtmann92381f52013-10-03 01:23:08 -0700874 code = skb->data[0];
Anderson Brigliaeb492e02011-06-09 18:50:40 -0300875 skb_pull(skb, sizeof(code));
876
Johan Hedberg8cf9fa12013-01-29 10:44:23 -0600877 /*
878 * The SMP context must be initialized for all other PDUs except
879 * pairing and security requests. If we get any other PDU when
880 * not initialized simply disconnect (done if this function
881 * returns an error).
882 */
883 if (code != SMP_CMD_PAIRING_REQ && code != SMP_CMD_SECURITY_REQ &&
884 !conn->smp_chan) {
885 BT_ERR("Unexpected SMP command 0x%02x. Disconnecting.", code);
886 kfree_skb(skb);
887 return -ENOTSUPP;
888 }
889
Anderson Brigliaeb492e02011-06-09 18:50:40 -0300890 switch (code) {
891 case SMP_CMD_PAIRING_REQ:
Vinicius Costa Gomesda85e5e2011-06-09 18:50:53 -0300892 reason = smp_cmd_pairing_req(conn, skb);
Anderson Brigliaeb492e02011-06-09 18:50:40 -0300893 break;
894
895 case SMP_CMD_PAIRING_FAIL:
Brian Gix4f957a72011-11-23 08:28:36 -0800896 smp_failure(conn, skb->data[0], 0);
Vinicius Costa Gomesda85e5e2011-06-09 18:50:53 -0300897 reason = 0;
898 err = -EPERM;
Anderson Brigliaeb492e02011-06-09 18:50:40 -0300899 break;
900
901 case SMP_CMD_PAIRING_RSP:
Vinicius Costa Gomesda85e5e2011-06-09 18:50:53 -0300902 reason = smp_cmd_pairing_rsp(conn, skb);
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300903 break;
904
905 case SMP_CMD_SECURITY_REQ:
Vinicius Costa Gomesda85e5e2011-06-09 18:50:53 -0300906 reason = smp_cmd_security_req(conn, skb);
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300907 break;
908
Anderson Brigliaeb492e02011-06-09 18:50:40 -0300909 case SMP_CMD_PAIRING_CONFIRM:
Vinicius Costa Gomesda85e5e2011-06-09 18:50:53 -0300910 reason = smp_cmd_pairing_confirm(conn, skb);
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300911 break;
912
Anderson Brigliaeb492e02011-06-09 18:50:40 -0300913 case SMP_CMD_PAIRING_RANDOM:
Vinicius Costa Gomesda85e5e2011-06-09 18:50:53 -0300914 reason = smp_cmd_pairing_random(conn, skb);
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300915 break;
916
Anderson Brigliaeb492e02011-06-09 18:50:40 -0300917 case SMP_CMD_ENCRYPT_INFO:
Vinicius Costa Gomes7034b912011-07-07 18:59:34 -0300918 reason = smp_cmd_encrypt_info(conn, skb);
919 break;
920
Anderson Brigliaeb492e02011-06-09 18:50:40 -0300921 case SMP_CMD_MASTER_IDENT:
Vinicius Costa Gomes7034b912011-07-07 18:59:34 -0300922 reason = smp_cmd_master_ident(conn, skb);
923 break;
924
Anderson Brigliaeb492e02011-06-09 18:50:40 -0300925 case SMP_CMD_IDENT_INFO:
926 case SMP_CMD_IDENT_ADDR_INFO:
927 case SMP_CMD_SIGN_INFO:
Vinicius Costa Gomes7034b912011-07-07 18:59:34 -0300928 /* Just ignored */
929 reason = 0;
930 break;
931
Anderson Brigliaeb492e02011-06-09 18:50:40 -0300932 default:
933 BT_DBG("Unknown command code 0x%2.2x", code);
934
935 reason = SMP_CMD_NOTSUPP;
Vinicius Costa Gomes3a0259b2011-06-09 18:50:43 -0300936 err = -EOPNOTSUPP;
937 goto done;
938 }
939
940done:
941 if (reason)
Brian Gix4f957a72011-11-23 08:28:36 -0800942 smp_failure(conn, reason, 1);
Anderson Brigliaeb492e02011-06-09 18:50:40 -0300943
944 kfree_skb(skb);
945 return err;
946}
Vinicius Costa Gomes7034b912011-07-07 18:59:34 -0300947
948int smp_distribute_keys(struct l2cap_conn *conn, __u8 force)
949{
950 struct smp_cmd_pairing *req, *rsp;
Vinicius Costa Gomes1c1def02011-09-05 14:31:30 -0300951 struct smp_chan *smp = conn->smp_chan;
Vinicius Costa Gomes7034b912011-07-07 18:59:34 -0300952 __u8 *keydist;
953
954 BT_DBG("conn %p force %d", conn, force);
955
Johan Hedberg51a8efd2012-01-16 06:10:31 +0200956 if (!test_bit(HCI_CONN_LE_SMP_PEND, &conn->hcon->flags))
Vinicius Costa Gomesd26a2342011-08-19 21:06:51 -0300957 return 0;
958
Vinicius Costa Gomes1c1def02011-09-05 14:31:30 -0300959 rsp = (void *) &smp->prsp[1];
Vinicius Costa Gomes7034b912011-07-07 18:59:34 -0300960
961 /* The responder sends its keys first */
962 if (!force && conn->hcon->out && (rsp->resp_key_dist & 0x07))
963 return 0;
964
Vinicius Costa Gomes1c1def02011-09-05 14:31:30 -0300965 req = (void *) &smp->preq[1];
Vinicius Costa Gomes7034b912011-07-07 18:59:34 -0300966
967 if (conn->hcon->out) {
968 keydist = &rsp->init_key_dist;
969 *keydist &= req->init_key_dist;
970 } else {
971 keydist = &rsp->resp_key_dist;
972 *keydist &= req->resp_key_dist;
973 }
974
975
976 BT_DBG("keydist 0x%x", *keydist);
977
978 if (*keydist & SMP_DIST_ENC_KEY) {
979 struct smp_cmd_encrypt_info enc;
980 struct smp_cmd_master_ident ident;
Vinicius Costa Gomesc9839a12012-02-02 21:08:01 -0300981 struct hci_conn *hcon = conn->hcon;
982 u8 authenticated;
Vinicius Costa Gomes7034b912011-07-07 18:59:34 -0300983 __le16 ediv;
984
985 get_random_bytes(enc.ltk, sizeof(enc.ltk));
986 get_random_bytes(&ediv, sizeof(ediv));
987 get_random_bytes(ident.rand, sizeof(ident.rand));
988
989 smp_send_cmd(conn, SMP_CMD_ENCRYPT_INFO, sizeof(enc), &enc);
990
Vinicius Costa Gomesc9839a12012-02-02 21:08:01 -0300991 authenticated = hcon->sec_level == BT_SECURITY_HIGH;
Marcel Holtmannce39fb42013-10-13 02:23:39 -0700992 hci_add_ltk(hcon->hdev, &hcon->dst, hcon->dst_type,
Gustavo F. Padovan04124682012-03-08 01:25:00 -0300993 HCI_SMP_LTK_SLAVE, 1, authenticated,
994 enc.ltk, smp->enc_key_size, ediv, ident.rand);
Vinicius Costa Gomes16b90832011-07-07 18:59:39 -0300995
Andrei Emeltchenko58115372012-03-12 12:13:06 +0200996 ident.ediv = ediv;
Vinicius Costa Gomes7034b912011-07-07 18:59:34 -0300997
998 smp_send_cmd(conn, SMP_CMD_MASTER_IDENT, sizeof(ident), &ident);
999
1000 *keydist &= ~SMP_DIST_ENC_KEY;
1001 }
1002
1003 if (*keydist & SMP_DIST_ID_KEY) {
1004 struct smp_cmd_ident_addr_info addrinfo;
1005 struct smp_cmd_ident_info idinfo;
1006
1007 /* Send a dummy key */
1008 get_random_bytes(idinfo.irk, sizeof(idinfo.irk));
1009
1010 smp_send_cmd(conn, SMP_CMD_IDENT_INFO, sizeof(idinfo), &idinfo);
1011
1012 /* Just public address */
1013 memset(&addrinfo, 0, sizeof(addrinfo));
Marcel Holtmannce39fb42013-10-13 02:23:39 -07001014 bacpy(&addrinfo.bdaddr, &conn->hcon->hdev->bdaddr);
Vinicius Costa Gomes7034b912011-07-07 18:59:34 -03001015
1016 smp_send_cmd(conn, SMP_CMD_IDENT_ADDR_INFO, sizeof(addrinfo),
1017 &addrinfo);
1018
1019 *keydist &= ~SMP_DIST_ID_KEY;
1020 }
1021
1022 if (*keydist & SMP_DIST_SIGN) {
1023 struct smp_cmd_sign_info sign;
1024
1025 /* Send a dummy key */
1026 get_random_bytes(sign.csrk, sizeof(sign.csrk));
1027
1028 smp_send_cmd(conn, SMP_CMD_SIGN_INFO, sizeof(sign), &sign);
1029
1030 *keydist &= ~SMP_DIST_SIGN;
1031 }
1032
Vinicius Costa Gomesd26a2342011-08-19 21:06:51 -03001033 if (conn->hcon->out || force) {
Johan Hedberg51a8efd2012-01-16 06:10:31 +02001034 clear_bit(HCI_CONN_LE_SMP_PEND, &conn->hcon->flags);
Gustavo F. Padovan6c9d42a2011-12-20 10:57:27 -02001035 cancel_delayed_work_sync(&conn->security_timer);
Vinicius Costa Gomes8aab4752011-09-05 14:31:31 -03001036 smp_chan_destroy(conn);
Vinicius Costa Gomesd26a2342011-08-19 21:06:51 -03001037 }
1038
Vinicius Costa Gomes7034b912011-07-07 18:59:34 -03001039 return 0;
1040}