blob: f57b20908ed5c05bbc3f9c13af08af6fe4526171 [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 Holtmann2b36a562013-10-13 05:24:00 -0700391 &conn->hcon->src, conn->hcon->dst_type,
Marcel Holtmannce39fb42013-10-13 02:23:39 -0700392 &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,
Marcel Holtmann2b36a562013-10-13 05:24:00 -0700396 &conn->hcon->src, 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 Holtmann2b36a562013-10-13 05:24:00 -0700431 &hcon->src, hcon->dst_type, &hcon->dst, res);
Vinicius Costa Gomes8aab4752011-09-05 14:31:31 -0300432 else
433 ret = smp_c1(tfm, smp->tk, smp->rrnd, smp->preq, smp->prsp,
Marcel Holtmann2b36a562013-10-13 05:24:00 -0700434 hcon->dst_type, &hcon->dst, 0, &hcon->src, res);
Vinicius Costa Gomes8aab4752011-09-05 14:31:31 -0300435 if (ret) {
436 reason = SMP_UNSPECIFIED;
437 goto error;
438 }
439
440 swap128(res, confirm);
441
442 if (memcmp(smp->pcnf, confirm, sizeof(smp->pcnf)) != 0) {
443 BT_ERR("Pairing failed (confirmation values mismatch)");
444 reason = SMP_CONFIRM_FAILED;
445 goto error;
446 }
447
448 if (hcon->out) {
449 u8 stk[16], rand[8];
450 __le16 ediv;
451
452 memset(rand, 0, sizeof(rand));
453 ediv = 0;
454
455 smp_s1(tfm, smp->tk, smp->rrnd, smp->prnd, key);
456 swap128(key, stk);
457
Vinicius Costa Gomesf7aa6112012-01-30 19:29:12 -0300458 memset(stk + smp->enc_key_size, 0,
Gustavo F. Padovan04124682012-03-08 01:25:00 -0300459 SMP_MAX_ENC_KEY_SIZE - smp->enc_key_size);
Vinicius Costa Gomes8aab4752011-09-05 14:31:31 -0300460
Johan Hedberg51a8efd2012-01-16 06:10:31 +0200461 if (test_and_set_bit(HCI_CONN_ENCRYPT_PEND, &hcon->flags)) {
Vinicius Costa Gomes8aab4752011-09-05 14:31:31 -0300462 reason = SMP_UNSPECIFIED;
463 goto error;
464 }
465
466 hci_le_start_enc(hcon, ediv, rand, stk);
Vinicius Costa Gomesf7aa6112012-01-30 19:29:12 -0300467 hcon->enc_key_size = smp->enc_key_size;
Vinicius Costa Gomes8aab4752011-09-05 14:31:31 -0300468 } else {
469 u8 stk[16], r[16], rand[8];
470 __le16 ediv;
471
472 memset(rand, 0, sizeof(rand));
473 ediv = 0;
474
475 swap128(smp->prnd, r);
476 smp_send_cmd(conn, SMP_CMD_PAIRING_RANDOM, sizeof(r), r);
477
478 smp_s1(tfm, smp->tk, smp->prnd, smp->rrnd, key);
479 swap128(key, stk);
480
Vinicius Costa Gomesf7aa6112012-01-30 19:29:12 -0300481 memset(stk + smp->enc_key_size, 0,
482 SMP_MAX_ENC_KEY_SIZE - smp->enc_key_size);
Vinicius Costa Gomes8aab4752011-09-05 14:31:31 -0300483
Marcel Holtmannce39fb42013-10-13 02:23:39 -0700484 hci_add_ltk(hcon->hdev, &hcon->dst, hcon->dst_type,
Gustavo F. Padovan04124682012-03-08 01:25:00 -0300485 HCI_SMP_STK_SLAVE, 0, 0, stk, smp->enc_key_size,
486 ediv, rand);
Vinicius Costa Gomes8aab4752011-09-05 14:31:31 -0300487 }
488
489 return;
490
491error:
Brian Gix4f957a72011-11-23 08:28:36 -0800492 smp_failure(conn, reason, 1);
Vinicius Costa Gomes8aab4752011-09-05 14:31:31 -0300493}
494
495static struct smp_chan *smp_chan_create(struct l2cap_conn *conn)
496{
497 struct smp_chan *smp;
498
499 smp = kzalloc(sizeof(struct smp_chan), GFP_ATOMIC);
500 if (!smp)
501 return NULL;
502
503 INIT_WORK(&smp->confirm, confirm_work);
504 INIT_WORK(&smp->random, random_work);
505
506 smp->conn = conn;
507 conn->smp_chan = smp;
Brian Gix2b64d152011-12-21 16:12:12 -0800508 conn->hcon->smp_conn = conn;
Vinicius Costa Gomes8aab4752011-09-05 14:31:31 -0300509
510 hci_conn_hold(conn->hcon);
511
512 return smp;
513}
514
515void smp_chan_destroy(struct l2cap_conn *conn)
516{
Brian Gixc8eb9692011-11-23 08:28:35 -0800517 struct smp_chan *smp = conn->smp_chan;
518
Vinicius Costa Gomesf1c09c02012-02-01 18:27:56 -0300519 BUG_ON(!smp);
Brian Gixc8eb9692011-11-23 08:28:35 -0800520
521 if (smp->tfm)
522 crypto_free_blkcipher(smp->tfm);
523
524 kfree(smp);
525 conn->smp_chan = NULL;
Brian Gix2b64d152011-12-21 16:12:12 -0800526 conn->hcon->smp_conn = NULL;
David Herrmann76a68ba2013-04-06 20:28:37 +0200527 hci_conn_drop(conn->hcon);
Vinicius Costa Gomes8aab4752011-09-05 14:31:31 -0300528}
529
Brian Gix2b64d152011-12-21 16:12:12 -0800530int smp_user_confirm_reply(struct hci_conn *hcon, u16 mgmt_op, __le32 passkey)
531{
532 struct l2cap_conn *conn = hcon->smp_conn;
533 struct smp_chan *smp;
534 u32 value;
535 u8 key[16];
536
537 BT_DBG("");
538
539 if (!conn)
540 return -ENOTCONN;
541
542 smp = conn->smp_chan;
543
544 switch (mgmt_op) {
545 case MGMT_OP_USER_PASSKEY_REPLY:
546 value = le32_to_cpu(passkey);
547 memset(key, 0, sizeof(key));
548 BT_DBG("PassKey: %d", value);
549 put_unaligned_le32(value, key);
550 swap128(key, smp->tk);
551 /* Fall Through */
552 case MGMT_OP_USER_CONFIRM_REPLY:
553 set_bit(SMP_FLAG_TK_VALID, &smp->smp_flags);
554 break;
555 case MGMT_OP_USER_PASSKEY_NEG_REPLY:
556 case MGMT_OP_USER_CONFIRM_NEG_REPLY:
557 smp_failure(conn, SMP_PASSKEY_ENTRY_FAILED, 1);
558 return 0;
559 default:
560 smp_failure(conn, SMP_PASSKEY_ENTRY_FAILED, 1);
561 return -EOPNOTSUPP;
562 }
563
564 /* If it is our turn to send Pairing Confirm, do so now */
565 if (test_bit(SMP_FLAG_CFM_PENDING, &smp->smp_flags))
566 queue_work(hcon->hdev->workqueue, &smp->confirm);
567
568 return 0;
569}
570
Vinicius Costa Gomesda85e5e2011-06-09 18:50:53 -0300571static u8 smp_cmd_pairing_req(struct l2cap_conn *conn, struct sk_buff *skb)
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300572{
Vinicius Costa Gomes3158c502011-06-14 13:37:42 -0300573 struct smp_cmd_pairing rsp, *req = (void *) skb->data;
Vinicius Costa Gomes8aab4752011-09-05 14:31:31 -0300574 struct smp_chan *smp;
Vinicius Costa Gomes3158c502011-06-14 13:37:42 -0300575 u8 key_size;
Brian Gix2b64d152011-12-21 16:12:12 -0800576 u8 auth = SMP_AUTH_NONE;
Vinicius Costa Gomes8aab4752011-09-05 14:31:31 -0300577 int ret;
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300578
579 BT_DBG("conn %p", conn);
580
Brian Gix2b64d152011-12-21 16:12:12 -0800581 if (conn->hcon->link_mode & HCI_LM_MASTER)
582 return SMP_CMD_NOTSUPP;
583
Johan Hedberg51a8efd2012-01-16 06:10:31 +0200584 if (!test_and_set_bit(HCI_CONN_LE_SMP_PEND, &conn->hcon->flags))
Vinicius Costa Gomes8aab4752011-09-05 14:31:31 -0300585 smp = smp_chan_create(conn);
Andrei Emeltchenkod08fd0e2012-07-19 17:03:43 +0300586 else
587 smp = conn->smp_chan;
Vinicius Costa Gomes8aab4752011-09-05 14:31:31 -0300588
Andrei Emeltchenkod08fd0e2012-07-19 17:03:43 +0300589 if (!smp)
590 return SMP_UNSPECIFIED;
Vinicius Costa Gomesd26a2342011-08-19 21:06:51 -0300591
Vinicius Costa Gomes1c1def02011-09-05 14:31:30 -0300592 smp->preq[0] = SMP_CMD_PAIRING_REQ;
593 memcpy(&smp->preq[1], req, sizeof(*req));
Vinicius Costa Gomes3158c502011-06-14 13:37:42 -0300594 skb_pull(skb, sizeof(*req));
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300595
Brian Gix2b64d152011-12-21 16:12:12 -0800596 /* We didn't start the pairing, so match remote */
597 if (req->auth_req & SMP_AUTH_BONDING)
598 auth = req->auth_req;
Vinicius Costa Gomesda85e5e2011-06-09 18:50:53 -0300599
Ido Yarivfdde0a22012-03-05 20:09:38 +0200600 conn->hcon->pending_sec_level = authreq_to_seclevel(auth);
601
Brian Gix2b64d152011-12-21 16:12:12 -0800602 build_pairing_cmd(conn, req, &rsp, auth);
Vinicius Costa Gomes3158c502011-06-14 13:37:42 -0300603
604 key_size = min(req->max_key_size, rsp.max_key_size);
605 if (check_enc_key_size(conn, key_size))
606 return SMP_ENC_KEY_SIZE;
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300607
Vinicius Costa Gomes8aab4752011-09-05 14:31:31 -0300608 ret = smp_rand(smp->prnd);
609 if (ret)
610 return SMP_UNSPECIFIED;
611
Vinicius Costa Gomes1c1def02011-09-05 14:31:30 -0300612 smp->prsp[0] = SMP_CMD_PAIRING_RSP;
613 memcpy(&smp->prsp[1], &rsp, sizeof(rsp));
Anderson Brigliaf01ead32011-06-09 18:50:45 -0300614
Vinicius Costa Gomes3158c502011-06-14 13:37:42 -0300615 smp_send_cmd(conn, SMP_CMD_PAIRING_RSP, sizeof(rsp), &rsp);
Vinicius Costa Gomesda85e5e2011-06-09 18:50:53 -0300616
Brian Gix2b64d152011-12-21 16:12:12 -0800617 /* Request setup of TK */
618 ret = tk_request(conn, 0, auth, rsp.io_capability, req->io_capability);
619 if (ret)
620 return SMP_UNSPECIFIED;
621
Vinicius Costa Gomesda85e5e2011-06-09 18:50:53 -0300622 return 0;
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300623}
624
Vinicius Costa Gomesda85e5e2011-06-09 18:50:53 -0300625static u8 smp_cmd_pairing_rsp(struct l2cap_conn *conn, struct sk_buff *skb)
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300626{
Vinicius Costa Gomes3158c502011-06-14 13:37:42 -0300627 struct smp_cmd_pairing *req, *rsp = (void *) skb->data;
Vinicius Costa Gomes1c1def02011-09-05 14:31:30 -0300628 struct smp_chan *smp = conn->smp_chan;
Vinicius Costa Gomes8aab4752011-09-05 14:31:31 -0300629 struct hci_dev *hdev = conn->hcon->hdev;
Brian Gix2b64d152011-12-21 16:12:12 -0800630 u8 key_size, auth = SMP_AUTH_NONE;
Anderson Briglia7d24ddc2011-06-09 18:50:46 -0300631 int ret;
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300632
633 BT_DBG("conn %p", conn);
634
Brian Gix2b64d152011-12-21 16:12:12 -0800635 if (!(conn->hcon->link_mode & HCI_LM_MASTER))
636 return SMP_CMD_NOTSUPP;
637
Vinicius Costa Gomes3158c502011-06-14 13:37:42 -0300638 skb_pull(skb, sizeof(*rsp));
Vinicius Costa Gomesda85e5e2011-06-09 18:50:53 -0300639
Vinicius Costa Gomes1c1def02011-09-05 14:31:30 -0300640 req = (void *) &smp->preq[1];
Vinicius Costa Gomes3158c502011-06-14 13:37:42 -0300641
642 key_size = min(req->max_key_size, rsp->max_key_size);
643 if (check_enc_key_size(conn, key_size))
644 return SMP_ENC_KEY_SIZE;
645
Vinicius Costa Gomes1c1def02011-09-05 14:31:30 -0300646 ret = smp_rand(smp->prnd);
Anderson Briglia7d24ddc2011-06-09 18:50:46 -0300647 if (ret)
Vinicius Costa Gomesda85e5e2011-06-09 18:50:53 -0300648 return SMP_UNSPECIFIED;
Anderson Briglia7d24ddc2011-06-09 18:50:46 -0300649
Vinicius Costa Gomes8aab4752011-09-05 14:31:31 -0300650 smp->prsp[0] = SMP_CMD_PAIRING_RSP;
651 memcpy(&smp->prsp[1], rsp, sizeof(*rsp));
Anderson Briglia7d24ddc2011-06-09 18:50:46 -0300652
Brian Gix2b64d152011-12-21 16:12:12 -0800653 if ((req->auth_req & SMP_AUTH_BONDING) &&
654 (rsp->auth_req & SMP_AUTH_BONDING))
655 auth = SMP_AUTH_BONDING;
656
657 auth |= (req->auth_req | rsp->auth_req) & SMP_AUTH_MITM;
658
Johan Hedberg476585e2012-06-06 18:54:15 +0800659 ret = tk_request(conn, 0, auth, req->io_capability, rsp->io_capability);
Brian Gix2b64d152011-12-21 16:12:12 -0800660 if (ret)
661 return SMP_UNSPECIFIED;
662
663 set_bit(SMP_FLAG_CFM_PENDING, &smp->smp_flags);
664
665 /* Can't compose response until we have been confirmed */
666 if (!test_bit(SMP_FLAG_TK_VALID, &smp->smp_flags))
667 return 0;
668
Vinicius Costa Gomes8aab4752011-09-05 14:31:31 -0300669 queue_work(hdev->workqueue, &smp->confirm);
Vinicius Costa Gomesda85e5e2011-06-09 18:50:53 -0300670
671 return 0;
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300672}
673
Vinicius Costa Gomesda85e5e2011-06-09 18:50:53 -0300674static u8 smp_cmd_pairing_confirm(struct l2cap_conn *conn, struct sk_buff *skb)
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300675{
Vinicius Costa Gomes1c1def02011-09-05 14:31:30 -0300676 struct smp_chan *smp = conn->smp_chan;
Vinicius Costa Gomes8aab4752011-09-05 14:31:31 -0300677 struct hci_dev *hdev = conn->hcon->hdev;
Anderson Briglia7d24ddc2011-06-09 18:50:46 -0300678
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300679 BT_DBG("conn %p %s", conn, conn->hcon->out ? "master" : "slave");
680
Vinicius Costa Gomes1c1def02011-09-05 14:31:30 -0300681 memcpy(smp->pcnf, skb->data, sizeof(smp->pcnf));
682 skb_pull(skb, sizeof(smp->pcnf));
Anderson Briglia7d24ddc2011-06-09 18:50:46 -0300683
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300684 if (conn->hcon->out) {
Anderson Briglia7d24ddc2011-06-09 18:50:46 -0300685 u8 random[16];
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300686
Vinicius Costa Gomes1c1def02011-09-05 14:31:30 -0300687 swap128(smp->prnd, random);
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300688 smp_send_cmd(conn, SMP_CMD_PAIRING_RANDOM, sizeof(random),
Anderson Briglia7d24ddc2011-06-09 18:50:46 -0300689 random);
Brian Gix2b64d152011-12-21 16:12:12 -0800690 } else if (test_bit(SMP_FLAG_TK_VALID, &smp->smp_flags)) {
Vinicius Costa Gomes8aab4752011-09-05 14:31:31 -0300691 queue_work(hdev->workqueue, &smp->confirm);
Brian Gix2b64d152011-12-21 16:12:12 -0800692 } else {
693 set_bit(SMP_FLAG_CFM_PENDING, &smp->smp_flags);
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300694 }
Vinicius Costa Gomesda85e5e2011-06-09 18:50:53 -0300695
696 return 0;
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300697}
698
Vinicius Costa Gomesda85e5e2011-06-09 18:50:53 -0300699static u8 smp_cmd_pairing_random(struct l2cap_conn *conn, struct sk_buff *skb)
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300700{
Vinicius Costa Gomes1c1def02011-09-05 14:31:30 -0300701 struct smp_chan *smp = conn->smp_chan;
Vinicius Costa Gomes8aab4752011-09-05 14:31:31 -0300702 struct hci_dev *hdev = conn->hcon->hdev;
Anderson Briglia7d24ddc2011-06-09 18:50:46 -0300703
Vinicius Costa Gomes8aab4752011-09-05 14:31:31 -0300704 BT_DBG("conn %p", conn);
Anderson Briglia7d24ddc2011-06-09 18:50:46 -0300705
Vinicius Costa Gomes8aab4752011-09-05 14:31:31 -0300706 swap128(skb->data, smp->rrnd);
707 skb_pull(skb, sizeof(smp->rrnd));
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300708
Vinicius Costa Gomes8aab4752011-09-05 14:31:31 -0300709 queue_work(hdev->workqueue, &smp->random);
Vinicius Costa Gomesda85e5e2011-06-09 18:50:53 -0300710
711 return 0;
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300712}
713
Johan Hedberg4dab7862012-06-07 14:58:37 +0800714static u8 smp_ltk_encrypt(struct l2cap_conn *conn, u8 sec_level)
Vinicius Costa Gomes988c5992011-08-25 20:02:28 -0300715{
Vinicius Costa Gomesc9839a12012-02-02 21:08:01 -0300716 struct smp_ltk *key;
Vinicius Costa Gomes988c5992011-08-25 20:02:28 -0300717 struct hci_conn *hcon = conn->hcon;
718
Marcel Holtmannce39fb42013-10-13 02:23:39 -0700719 key = hci_find_ltk_by_addr(hcon->hdev, &hcon->dst, hcon->dst_type);
Vinicius Costa Gomes988c5992011-08-25 20:02:28 -0300720 if (!key)
721 return 0;
722
Johan Hedberg4dab7862012-06-07 14:58:37 +0800723 if (sec_level > BT_SECURITY_MEDIUM && !key->authenticated)
724 return 0;
725
Johan Hedberg51a8efd2012-01-16 06:10:31 +0200726 if (test_and_set_bit(HCI_CONN_ENCRYPT_PEND, &hcon->flags))
Vinicius Costa Gomes988c5992011-08-25 20:02:28 -0300727 return 1;
728
Vinicius Costa Gomesc9839a12012-02-02 21:08:01 -0300729 hci_le_start_enc(hcon, key->ediv, key->rand, key->val);
730 hcon->enc_key_size = key->enc_size;
Vinicius Costa Gomes988c5992011-08-25 20:02:28 -0300731
732 return 1;
733
734}
Vinicius Costa Gomesda85e5e2011-06-09 18:50:53 -0300735static u8 smp_cmd_security_req(struct l2cap_conn *conn, struct sk_buff *skb)
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300736{
737 struct smp_cmd_security_req *rp = (void *) skb->data;
738 struct smp_cmd_pairing cp;
Vinicius Costa Gomesf1cb9af2011-01-26 21:42:57 -0300739 struct hci_conn *hcon = conn->hcon;
Vinicius Costa Gomes8aab4752011-09-05 14:31:31 -0300740 struct smp_chan *smp;
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300741
742 BT_DBG("conn %p", conn);
743
Brian Gix2b64d152011-12-21 16:12:12 -0800744 hcon->pending_sec_level = authreq_to_seclevel(rp->auth_req);
Vinicius Costa Gomesfeb45eb2011-08-25 20:02:35 -0300745
Johan Hedberg4dab7862012-06-07 14:58:37 +0800746 if (smp_ltk_encrypt(conn, hcon->pending_sec_level))
Vinicius Costa Gomes988c5992011-08-25 20:02:28 -0300747 return 0;
748
Johan Hedberg51a8efd2012-01-16 06:10:31 +0200749 if (test_and_set_bit(HCI_CONN_LE_SMP_PEND, &hcon->flags))
Vinicius Costa Gomesda85e5e2011-06-09 18:50:53 -0300750 return 0;
Vinicius Costa Gomesf1cb9af2011-01-26 21:42:57 -0300751
Vinicius Costa Gomes8aab4752011-09-05 14:31:31 -0300752 smp = smp_chan_create(conn);
Vinicius Costa Gomesd26a2342011-08-19 21:06:51 -0300753
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300754 skb_pull(skb, sizeof(*rp));
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300755
Vinicius Costa Gomesda85e5e2011-06-09 18:50:53 -0300756 memset(&cp, 0, sizeof(cp));
Vinicius Costa Gomes54790f72011-07-07 18:59:38 -0300757 build_pairing_cmd(conn, &cp, NULL, rp->auth_req);
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300758
Vinicius Costa Gomes1c1def02011-09-05 14:31:30 -0300759 smp->preq[0] = SMP_CMD_PAIRING_REQ;
760 memcpy(&smp->preq[1], &cp, sizeof(cp));
Anderson Brigliaf01ead32011-06-09 18:50:45 -0300761
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300762 smp_send_cmd(conn, SMP_CMD_PAIRING_REQ, sizeof(cp), &cp);
Vinicius Costa Gomesf1cb9af2011-01-26 21:42:57 -0300763
Vinicius Costa Gomesda85e5e2011-06-09 18:50:53 -0300764 return 0;
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300765}
766
Vinicius Costa Gomescc110922012-08-23 21:32:43 -0300767int smp_conn_security(struct hci_conn *hcon, __u8 sec_level)
Anderson Brigliaeb492e02011-06-09 18:50:40 -0300768{
Vinicius Costa Gomescc110922012-08-23 21:32:43 -0300769 struct l2cap_conn *conn = hcon->l2cap_data;
Vinicius Costa Gomes1c1def02011-09-05 14:31:30 -0300770 struct smp_chan *smp = conn->smp_chan;
Brian Gix2b64d152011-12-21 16:12:12 -0800771 __u8 authreq;
Anderson Brigliaeb492e02011-06-09 18:50:40 -0300772
Vinicius Costa Gomes3a0259b2011-06-09 18:50:43 -0300773 BT_DBG("conn %p hcon %p level 0x%2.2x", conn, hcon, sec_level);
774
Johan Hedberg757aee02013-04-24 13:05:32 +0300775 if (!test_bit(HCI_LE_ENABLED, &hcon->hdev->dev_flags))
Andre Guedes2e65c9d2011-06-30 19:20:56 -0300776 return 1;
777
Vinicius Costa Gomesf1cb9af2011-01-26 21:42:57 -0300778 if (sec_level == BT_SECURITY_LOW)
Anderson Brigliaeb492e02011-06-09 18:50:40 -0300779 return 1;
Vinicius Costa Gomesf1cb9af2011-01-26 21:42:57 -0300780
781 if (hcon->sec_level >= sec_level)
782 return 1;
783
Vinicius Costa Gomes988c5992011-08-25 20:02:28 -0300784 if (hcon->link_mode & HCI_LM_MASTER)
Johan Hedberg4dab7862012-06-07 14:58:37 +0800785 if (smp_ltk_encrypt(conn, sec_level))
Vinicius Costa Gomes02bc7452011-07-07 18:59:41 -0300786 goto done;
Vinicius Costa Gomesd26a2342011-08-19 21:06:51 -0300787
Johan Hedberg51a8efd2012-01-16 06:10:31 +0200788 if (test_and_set_bit(HCI_CONN_LE_SMP_PEND, &hcon->flags))
Vinicius Costa Gomesd26a2342011-08-19 21:06:51 -0300789 return 0;
790
Vinicius Costa Gomes8aab4752011-09-05 14:31:31 -0300791 smp = smp_chan_create(conn);
Brian Gix2b64d152011-12-21 16:12:12 -0800792 if (!smp)
793 return 1;
794
795 authreq = seclevel_to_authreq(sec_level);
Vinicius Costa Gomesd26a2342011-08-19 21:06:51 -0300796
Vinicius Costa Gomesd26a2342011-08-19 21:06:51 -0300797 if (hcon->link_mode & HCI_LM_MASTER) {
798 struct smp_cmd_pairing cp;
Anderson Brigliaf01ead32011-06-09 18:50:45 -0300799
Brian Gix2b64d152011-12-21 16:12:12 -0800800 build_pairing_cmd(conn, &cp, NULL, authreq);
Vinicius Costa Gomes1c1def02011-09-05 14:31:30 -0300801 smp->preq[0] = SMP_CMD_PAIRING_REQ;
802 memcpy(&smp->preq[1], &cp, sizeof(cp));
Anderson Brigliaf01ead32011-06-09 18:50:45 -0300803
Anderson Brigliaeb492e02011-06-09 18:50:40 -0300804 smp_send_cmd(conn, SMP_CMD_PAIRING_REQ, sizeof(cp), &cp);
805 } else {
806 struct smp_cmd_security_req cp;
Brian Gix2b64d152011-12-21 16:12:12 -0800807 cp.auth_req = authreq;
Anderson Brigliaeb492e02011-06-09 18:50:40 -0300808 smp_send_cmd(conn, SMP_CMD_SECURITY_REQ, sizeof(cp), &cp);
809 }
810
Vinicius Costa Gomes02bc7452011-07-07 18:59:41 -0300811done:
Vinicius Costa Gomesf1cb9af2011-01-26 21:42:57 -0300812 hcon->pending_sec_level = sec_level;
Vinicius Costa Gomesf1cb9af2011-01-26 21:42:57 -0300813
Anderson Brigliaeb492e02011-06-09 18:50:40 -0300814 return 0;
815}
816
Vinicius Costa Gomes7034b912011-07-07 18:59:34 -0300817static int smp_cmd_encrypt_info(struct l2cap_conn *conn, struct sk_buff *skb)
818{
Vinicius Costa Gomes16b90832011-07-07 18:59:39 -0300819 struct smp_cmd_encrypt_info *rp = (void *) skb->data;
Vinicius Costa Gomes1c1def02011-09-05 14:31:30 -0300820 struct smp_chan *smp = conn->smp_chan;
Vinicius Costa Gomes16b90832011-07-07 18:59:39 -0300821
822 skb_pull(skb, sizeof(*rp));
823
Vinicius Costa Gomes1c1def02011-09-05 14:31:30 -0300824 memcpy(smp->tk, rp->ltk, sizeof(smp->tk));
Vinicius Costa Gomes16b90832011-07-07 18:59:39 -0300825
Vinicius Costa Gomes7034b912011-07-07 18:59:34 -0300826 return 0;
827}
828
829static int smp_cmd_master_ident(struct l2cap_conn *conn, struct sk_buff *skb)
830{
Vinicius Costa Gomes16b90832011-07-07 18:59:39 -0300831 struct smp_cmd_master_ident *rp = (void *) skb->data;
Vinicius Costa Gomes1c1def02011-09-05 14:31:30 -0300832 struct smp_chan *smp = conn->smp_chan;
Vinicius Costa Gomesc9839a12012-02-02 21:08:01 -0300833 struct hci_dev *hdev = conn->hcon->hdev;
834 struct hci_conn *hcon = conn->hcon;
835 u8 authenticated;
Vinicius Costa Gomes7034b912011-07-07 18:59:34 -0300836
Vinicius Costa Gomes16b90832011-07-07 18:59:39 -0300837 skb_pull(skb, sizeof(*rp));
838
Vinicius Costa Gomesc9839a12012-02-02 21:08:01 -0300839 hci_dev_lock(hdev);
Marcel Holtmannce39fb42013-10-13 02:23:39 -0700840 authenticated = (hcon->sec_level == BT_SECURITY_HIGH);
841 hci_add_ltk(hdev, &hcon->dst, hcon->dst_type, HCI_SMP_LTK, 1,
842 authenticated, smp->tk, smp->enc_key_size,
Gustavo F. Padovan04124682012-03-08 01:25:00 -0300843 rp->ediv, rp->rand);
Vinicius Costa Gomes7034b912011-07-07 18:59:34 -0300844 smp_distribute_keys(conn, 1);
Vinicius Costa Gomesc9839a12012-02-02 21:08:01 -0300845 hci_dev_unlock(hdev);
Vinicius Costa Gomes7034b912011-07-07 18:59:34 -0300846
847 return 0;
848}
849
Anderson Brigliaeb492e02011-06-09 18:50:40 -0300850int smp_sig_channel(struct l2cap_conn *conn, struct sk_buff *skb)
851{
Marcel Holtmann7b9899d2013-10-03 00:00:57 -0700852 struct hci_conn *hcon = conn->hcon;
Marcel Holtmann92381f52013-10-03 01:23:08 -0700853 __u8 code, reason;
Anderson Brigliaeb492e02011-06-09 18:50:40 -0300854 int err = 0;
855
Marcel Holtmann7b9899d2013-10-03 00:00:57 -0700856 if (hcon->type != LE_LINK) {
857 kfree_skb(skb);
858 return -ENOTSUPP;
859 }
860
Marcel Holtmann92381f52013-10-03 01:23:08 -0700861 if (skb->len < 1) {
862 kfree_skb(skb);
863 return -EILSEQ;
864 }
865
Johan Hedberg757aee02013-04-24 13:05:32 +0300866 if (!test_bit(HCI_LE_ENABLED, &conn->hcon->hdev->dev_flags)) {
Andre Guedes2e65c9d2011-06-30 19:20:56 -0300867 err = -ENOTSUPP;
868 reason = SMP_PAIRING_NOTSUPP;
869 goto done;
870 }
871
Marcel Holtmann92381f52013-10-03 01:23:08 -0700872 code = skb->data[0];
Anderson Brigliaeb492e02011-06-09 18:50:40 -0300873 skb_pull(skb, sizeof(code));
874
Johan Hedberg8cf9fa12013-01-29 10:44:23 -0600875 /*
876 * The SMP context must be initialized for all other PDUs except
877 * pairing and security requests. If we get any other PDU when
878 * not initialized simply disconnect (done if this function
879 * returns an error).
880 */
881 if (code != SMP_CMD_PAIRING_REQ && code != SMP_CMD_SECURITY_REQ &&
882 !conn->smp_chan) {
883 BT_ERR("Unexpected SMP command 0x%02x. Disconnecting.", code);
884 kfree_skb(skb);
885 return -ENOTSUPP;
886 }
887
Anderson Brigliaeb492e02011-06-09 18:50:40 -0300888 switch (code) {
889 case SMP_CMD_PAIRING_REQ:
Vinicius Costa Gomesda85e5e2011-06-09 18:50:53 -0300890 reason = smp_cmd_pairing_req(conn, skb);
Anderson Brigliaeb492e02011-06-09 18:50:40 -0300891 break;
892
893 case SMP_CMD_PAIRING_FAIL:
Brian Gix4f957a72011-11-23 08:28:36 -0800894 smp_failure(conn, skb->data[0], 0);
Vinicius Costa Gomesda85e5e2011-06-09 18:50:53 -0300895 reason = 0;
896 err = -EPERM;
Anderson Brigliaeb492e02011-06-09 18:50:40 -0300897 break;
898
899 case SMP_CMD_PAIRING_RSP:
Vinicius Costa Gomesda85e5e2011-06-09 18:50:53 -0300900 reason = smp_cmd_pairing_rsp(conn, skb);
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300901 break;
902
903 case SMP_CMD_SECURITY_REQ:
Vinicius Costa Gomesda85e5e2011-06-09 18:50:53 -0300904 reason = smp_cmd_security_req(conn, skb);
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300905 break;
906
Anderson Brigliaeb492e02011-06-09 18:50:40 -0300907 case SMP_CMD_PAIRING_CONFIRM:
Vinicius Costa Gomesda85e5e2011-06-09 18:50:53 -0300908 reason = smp_cmd_pairing_confirm(conn, skb);
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300909 break;
910
Anderson Brigliaeb492e02011-06-09 18:50:40 -0300911 case SMP_CMD_PAIRING_RANDOM:
Vinicius Costa Gomesda85e5e2011-06-09 18:50:53 -0300912 reason = smp_cmd_pairing_random(conn, skb);
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300913 break;
914
Anderson Brigliaeb492e02011-06-09 18:50:40 -0300915 case SMP_CMD_ENCRYPT_INFO:
Vinicius Costa Gomes7034b912011-07-07 18:59:34 -0300916 reason = smp_cmd_encrypt_info(conn, skb);
917 break;
918
Anderson Brigliaeb492e02011-06-09 18:50:40 -0300919 case SMP_CMD_MASTER_IDENT:
Vinicius Costa Gomes7034b912011-07-07 18:59:34 -0300920 reason = smp_cmd_master_ident(conn, skb);
921 break;
922
Anderson Brigliaeb492e02011-06-09 18:50:40 -0300923 case SMP_CMD_IDENT_INFO:
924 case SMP_CMD_IDENT_ADDR_INFO:
925 case SMP_CMD_SIGN_INFO:
Vinicius Costa Gomes7034b912011-07-07 18:59:34 -0300926 /* Just ignored */
927 reason = 0;
928 break;
929
Anderson Brigliaeb492e02011-06-09 18:50:40 -0300930 default:
931 BT_DBG("Unknown command code 0x%2.2x", code);
932
933 reason = SMP_CMD_NOTSUPP;
Vinicius Costa Gomes3a0259b2011-06-09 18:50:43 -0300934 err = -EOPNOTSUPP;
935 goto done;
936 }
937
938done:
939 if (reason)
Brian Gix4f957a72011-11-23 08:28:36 -0800940 smp_failure(conn, reason, 1);
Anderson Brigliaeb492e02011-06-09 18:50:40 -0300941
942 kfree_skb(skb);
943 return err;
944}
Vinicius Costa Gomes7034b912011-07-07 18:59:34 -0300945
946int smp_distribute_keys(struct l2cap_conn *conn, __u8 force)
947{
948 struct smp_cmd_pairing *req, *rsp;
Vinicius Costa Gomes1c1def02011-09-05 14:31:30 -0300949 struct smp_chan *smp = conn->smp_chan;
Vinicius Costa Gomes7034b912011-07-07 18:59:34 -0300950 __u8 *keydist;
951
952 BT_DBG("conn %p force %d", conn, force);
953
Johan Hedberg51a8efd2012-01-16 06:10:31 +0200954 if (!test_bit(HCI_CONN_LE_SMP_PEND, &conn->hcon->flags))
Vinicius Costa Gomesd26a2342011-08-19 21:06:51 -0300955 return 0;
956
Vinicius Costa Gomes1c1def02011-09-05 14:31:30 -0300957 rsp = (void *) &smp->prsp[1];
Vinicius Costa Gomes7034b912011-07-07 18:59:34 -0300958
959 /* The responder sends its keys first */
960 if (!force && conn->hcon->out && (rsp->resp_key_dist & 0x07))
961 return 0;
962
Vinicius Costa Gomes1c1def02011-09-05 14:31:30 -0300963 req = (void *) &smp->preq[1];
Vinicius Costa Gomes7034b912011-07-07 18:59:34 -0300964
965 if (conn->hcon->out) {
966 keydist = &rsp->init_key_dist;
967 *keydist &= req->init_key_dist;
968 } else {
969 keydist = &rsp->resp_key_dist;
970 *keydist &= req->resp_key_dist;
971 }
972
973
974 BT_DBG("keydist 0x%x", *keydist);
975
976 if (*keydist & SMP_DIST_ENC_KEY) {
977 struct smp_cmd_encrypt_info enc;
978 struct smp_cmd_master_ident ident;
Vinicius Costa Gomesc9839a12012-02-02 21:08:01 -0300979 struct hci_conn *hcon = conn->hcon;
980 u8 authenticated;
Vinicius Costa Gomes7034b912011-07-07 18:59:34 -0300981 __le16 ediv;
982
983 get_random_bytes(enc.ltk, sizeof(enc.ltk));
984 get_random_bytes(&ediv, sizeof(ediv));
985 get_random_bytes(ident.rand, sizeof(ident.rand));
986
987 smp_send_cmd(conn, SMP_CMD_ENCRYPT_INFO, sizeof(enc), &enc);
988
Vinicius Costa Gomesc9839a12012-02-02 21:08:01 -0300989 authenticated = hcon->sec_level == BT_SECURITY_HIGH;
Marcel Holtmannce39fb42013-10-13 02:23:39 -0700990 hci_add_ltk(hcon->hdev, &hcon->dst, hcon->dst_type,
Gustavo F. Padovan04124682012-03-08 01:25:00 -0300991 HCI_SMP_LTK_SLAVE, 1, authenticated,
992 enc.ltk, smp->enc_key_size, ediv, ident.rand);
Vinicius Costa Gomes16b90832011-07-07 18:59:39 -0300993
Andrei Emeltchenko58115372012-03-12 12:13:06 +0200994 ident.ediv = ediv;
Vinicius Costa Gomes7034b912011-07-07 18:59:34 -0300995
996 smp_send_cmd(conn, SMP_CMD_MASTER_IDENT, sizeof(ident), &ident);
997
998 *keydist &= ~SMP_DIST_ENC_KEY;
999 }
1000
1001 if (*keydist & SMP_DIST_ID_KEY) {
1002 struct smp_cmd_ident_addr_info addrinfo;
1003 struct smp_cmd_ident_info idinfo;
1004
1005 /* Send a dummy key */
1006 get_random_bytes(idinfo.irk, sizeof(idinfo.irk));
1007
1008 smp_send_cmd(conn, SMP_CMD_IDENT_INFO, sizeof(idinfo), &idinfo);
1009
1010 /* Just public address */
1011 memset(&addrinfo, 0, sizeof(addrinfo));
Marcel Holtmann2b36a562013-10-13 05:24:00 -07001012 bacpy(&addrinfo.bdaddr, &conn->hcon->src);
Vinicius Costa Gomes7034b912011-07-07 18:59:34 -03001013
1014 smp_send_cmd(conn, SMP_CMD_IDENT_ADDR_INFO, sizeof(addrinfo),
1015 &addrinfo);
1016
1017 *keydist &= ~SMP_DIST_ID_KEY;
1018 }
1019
1020 if (*keydist & SMP_DIST_SIGN) {
1021 struct smp_cmd_sign_info sign;
1022
1023 /* Send a dummy key */
1024 get_random_bytes(sign.csrk, sizeof(sign.csrk));
1025
1026 smp_send_cmd(conn, SMP_CMD_SIGN_INFO, sizeof(sign), &sign);
1027
1028 *keydist &= ~SMP_DIST_SIGN;
1029 }
1030
Vinicius Costa Gomesd26a2342011-08-19 21:06:51 -03001031 if (conn->hcon->out || force) {
Johan Hedberg51a8efd2012-01-16 06:10:31 +02001032 clear_bit(HCI_CONN_LE_SMP_PEND, &conn->hcon->flags);
Gustavo F. Padovan6c9d42a2011-12-20 10:57:27 -02001033 cancel_delayed_work_sync(&conn->security_timer);
Vinicius Costa Gomes8aab4752011-09-05 14:31:31 -03001034 smp_chan_destroy(conn);
Vinicius Costa Gomesd26a2342011-08-19 21:06:51 -03001035 }
1036
Vinicius Costa Gomes7034b912011-07-07 18:59:34 -03001037 return 0;
1038}