blob: 6355a460e9d0415f499d7a68a727989145f4fffc [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;
Johan Hedberg201a5922013-12-02 10:49:04 +020056 int err;
Anderson Brigliad22ef0b2011-06-09 18:50:44 -030057
58 if (tfm == NULL) {
59 BT_ERR("tfm %p", tfm);
60 return -EINVAL;
61 }
62
63 desc.tfm = tfm;
64 desc.flags = 0;
65
66 err = crypto_blkcipher_setkey(tfm, k, 16);
67 if (err) {
68 BT_ERR("cipher setkey failed: %d", err);
69 return err;
70 }
71
72 sg_init_one(&sg, r, 16);
73
Anderson Brigliad22ef0b2011-06-09 18:50:44 -030074 err = crypto_blkcipher_encrypt(&desc, &sg, &sg, 16);
75 if (err)
76 BT_ERR("Encrypt data error %d", err);
77
78 return err;
79}
80
Johan Hedberg60478052014-02-18 10:19:31 +020081static int smp_ah(struct crypto_blkcipher *tfm, u8 irk[16], u8 r[3], u8 res[3])
82{
83 u8 _res[16], k[16];
84 int err;
85
86 /* r' = padding || r */
87 memset(_res, 0, 13);
88 _res[13] = r[2];
89 _res[14] = r[1];
90 _res[15] = r[0];
91
92 swap128(irk, k);
93 err = smp_e(tfm, k, _res);
94 if (err) {
95 BT_ERR("Encrypt error");
96 return err;
97 }
98
99 /* The output of the random address function ah is:
100 * ah(h, r) = e(k, r') mod 2^24
101 * The output of the security function e is then truncated to 24 bits
102 * by taking the least significant 24 bits of the output of e as the
103 * result of ah.
104 */
105 res[0] = _res[15];
106 res[1] = _res[14];
107 res[2] = _res[13];
108
109 return 0;
110}
111
112bool smp_irk_matches(struct crypto_blkcipher *tfm, u8 irk[16],
113 bdaddr_t *bdaddr)
114{
115 u8 hash[3];
116 int err;
117
118 BT_DBG("RPA %pMR IRK %*phN", bdaddr, 16, irk);
119
120 err = smp_ah(tfm, irk, &bdaddr->b[3], hash);
121 if (err)
122 return false;
123
124 return !memcmp(bdaddr->b, hash, 3);
125}
126
Anderson Brigliad22ef0b2011-06-09 18:50:44 -0300127static int smp_c1(struct crypto_blkcipher *tfm, u8 k[16], u8 r[16],
Marcel Holtmannf1560462013-10-13 05:43:25 -0700128 u8 preq[7], u8 pres[7], u8 _iat, bdaddr_t *ia,
129 u8 _rat, bdaddr_t *ra, u8 res[16])
Anderson Brigliad22ef0b2011-06-09 18:50:44 -0300130{
131 u8 p1[16], p2[16];
132 int err;
133
134 memset(p1, 0, 16);
135
136 /* p1 = pres || preq || _rat || _iat */
137 swap56(pres, p1);
138 swap56(preq, p1 + 7);
139 p1[14] = _rat;
140 p1[15] = _iat;
141
142 memset(p2, 0, 16);
143
144 /* p2 = padding || ia || ra */
145 baswap((bdaddr_t *) (p2 + 4), ia);
146 baswap((bdaddr_t *) (p2 + 10), ra);
147
148 /* res = r XOR p1 */
149 u128_xor((u128 *) res, (u128 *) r, (u128 *) p1);
150
151 /* res = e(k, res) */
152 err = smp_e(tfm, k, res);
153 if (err) {
154 BT_ERR("Encrypt data error");
155 return err;
156 }
157
158 /* res = res XOR p2 */
159 u128_xor((u128 *) res, (u128 *) res, (u128 *) p2);
160
161 /* res = e(k, res) */
162 err = smp_e(tfm, k, res);
163 if (err)
164 BT_ERR("Encrypt data error");
165
166 return err;
167}
168
Marcel Holtmannf1560462013-10-13 05:43:25 -0700169static int smp_s1(struct crypto_blkcipher *tfm, u8 k[16], u8 r1[16],
170 u8 r2[16], u8 _r[16])
Anderson Brigliad22ef0b2011-06-09 18:50:44 -0300171{
172 int err;
173
174 /* Just least significant octets from r1 and r2 are considered */
175 memcpy(_r, r1 + 8, 8);
176 memcpy(_r + 8, r2 + 8, 8);
177
178 err = smp_e(tfm, k, _r);
179 if (err)
180 BT_ERR("Encrypt data error");
181
182 return err;
183}
184
Anderson Brigliaeb492e02011-06-09 18:50:40 -0300185static struct sk_buff *smp_build_cmd(struct l2cap_conn *conn, u8 code,
Marcel Holtmannf1560462013-10-13 05:43:25 -0700186 u16 dlen, void *data)
Anderson Brigliaeb492e02011-06-09 18:50:40 -0300187{
188 struct sk_buff *skb;
189 struct l2cap_hdr *lh;
190 int len;
191
192 len = L2CAP_HDR_SIZE + sizeof(code) + dlen;
193
194 if (len > conn->mtu)
195 return NULL;
196
197 skb = bt_skb_alloc(len, GFP_ATOMIC);
198 if (!skb)
199 return NULL;
200
201 lh = (struct l2cap_hdr *) skb_put(skb, L2CAP_HDR_SIZE);
202 lh->len = cpu_to_le16(sizeof(code) + dlen);
Syam Sidhardhand8aece22012-10-10 22:09:28 +0530203 lh->cid = __constant_cpu_to_le16(L2CAP_CID_SMP);
Anderson Brigliaeb492e02011-06-09 18:50:40 -0300204
205 memcpy(skb_put(skb, sizeof(code)), &code, sizeof(code));
206
207 memcpy(skb_put(skb, dlen), data, dlen);
208
209 return skb;
210}
211
212static void smp_send_cmd(struct l2cap_conn *conn, u8 code, u16 len, void *data)
213{
214 struct sk_buff *skb = smp_build_cmd(conn, code, len, data);
215
216 BT_DBG("code 0x%2.2x", code);
217
218 if (!skb)
219 return;
220
Luiz Augusto von Dentz73d80de2011-11-02 15:52:01 +0200221 skb->priority = HCI_PRIO_MAX;
222 hci_send_acl(conn->hchan, skb, 0);
Vinicius Costa Gomese2dcd112011-08-19 21:06:50 -0300223
Gustavo F. Padovan6c9d42a2011-12-20 10:57:27 -0200224 cancel_delayed_work_sync(&conn->security_timer);
Marcel Holtmann17b02e62012-03-01 14:32:37 -0800225 schedule_delayed_work(&conn->security_timer, SMP_TIMEOUT);
Anderson Brigliaeb492e02011-06-09 18:50:40 -0300226}
227
Brian Gix2b64d152011-12-21 16:12:12 -0800228static __u8 authreq_to_seclevel(__u8 authreq)
229{
230 if (authreq & SMP_AUTH_MITM)
231 return BT_SECURITY_HIGH;
232 else
233 return BT_SECURITY_MEDIUM;
234}
235
236static __u8 seclevel_to_authreq(__u8 sec_level)
237{
238 switch (sec_level) {
239 case BT_SECURITY_HIGH:
240 return SMP_AUTH_MITM | SMP_AUTH_BONDING;
241 case BT_SECURITY_MEDIUM:
242 return SMP_AUTH_BONDING;
243 default:
244 return SMP_AUTH_NONE;
245 }
246}
247
Vinicius Costa Gomesb8e66ea2011-06-09 18:50:52 -0300248static void build_pairing_cmd(struct l2cap_conn *conn,
Marcel Holtmannf1560462013-10-13 05:43:25 -0700249 struct smp_cmd_pairing *req,
250 struct smp_cmd_pairing *rsp, __u8 authreq)
Vinicius Costa Gomesb8e66ea2011-06-09 18:50:52 -0300251{
Johan Hedbergfd349c02014-02-18 10:19:36 +0200252 struct smp_chan *smp = conn->smp_chan;
253 struct hci_conn *hcon = conn->hcon;
254 struct hci_dev *hdev = hcon->hdev;
255 u8 local_dist = 0, remote_dist = 0;
Vinicius Costa Gomes54790f72011-07-07 18:59:38 -0300256
Johan Hedberga8b2d5c2012-01-08 23:11:15 +0200257 if (test_bit(HCI_PAIRABLE, &conn->hcon->hdev->dev_flags)) {
Johan Hedbergfd349c02014-02-18 10:19:36 +0200258 local_dist = SMP_DIST_ENC_KEY;
259 remote_dist = SMP_DIST_ENC_KEY;
Vinicius Costa Gomes54790f72011-07-07 18:59:38 -0300260 authreq |= SMP_AUTH_BONDING;
Brian Gix2b64d152011-12-21 16:12:12 -0800261 } else {
262 authreq &= ~SMP_AUTH_BONDING;
Vinicius Costa Gomes54790f72011-07-07 18:59:38 -0300263 }
264
Johan Hedbergfd349c02014-02-18 10:19:36 +0200265 if (test_bit(HCI_RPA_RESOLVING, &hdev->dev_flags))
266 remote_dist |= SMP_DIST_ID_KEY;
267
Vinicius Costa Gomes54790f72011-07-07 18:59:38 -0300268 if (rsp == NULL) {
269 req->io_capability = conn->hcon->io_capability;
270 req->oob_flag = SMP_OOB_NOT_PRESENT;
271 req->max_key_size = SMP_MAX_ENC_KEY_SIZE;
Johan Hedbergfd349c02014-02-18 10:19:36 +0200272 req->init_key_dist = local_dist;
273 req->resp_key_dist = remote_dist;
Johan Hedberg065a13e2012-10-11 16:26:06 +0200274 req->auth_req = (authreq & AUTH_REQ_MASK);
Johan Hedbergfd349c02014-02-18 10:19:36 +0200275
276 smp->remote_key_dist = remote_dist;
Vinicius Costa Gomes54790f72011-07-07 18:59:38 -0300277 return;
278 }
279
280 rsp->io_capability = conn->hcon->io_capability;
281 rsp->oob_flag = SMP_OOB_NOT_PRESENT;
282 rsp->max_key_size = SMP_MAX_ENC_KEY_SIZE;
Johan Hedbergfd349c02014-02-18 10:19:36 +0200283 rsp->init_key_dist = req->init_key_dist & remote_dist;
284 rsp->resp_key_dist = req->resp_key_dist & local_dist;
Johan Hedberg065a13e2012-10-11 16:26:06 +0200285 rsp->auth_req = (authreq & AUTH_REQ_MASK);
Johan Hedbergfd349c02014-02-18 10:19:36 +0200286
287 smp->remote_key_dist = rsp->init_key_dist;
Vinicius Costa Gomesb8e66ea2011-06-09 18:50:52 -0300288}
289
Vinicius Costa Gomes3158c502011-06-14 13:37:42 -0300290static u8 check_enc_key_size(struct l2cap_conn *conn, __u8 max_key_size)
291{
Vinicius Costa Gomes1c1def02011-09-05 14:31:30 -0300292 struct smp_chan *smp = conn->smp_chan;
293
Vinicius Costa Gomes3158c502011-06-14 13:37:42 -0300294 if ((max_key_size > SMP_MAX_ENC_KEY_SIZE) ||
Marcel Holtmannf1560462013-10-13 05:43:25 -0700295 (max_key_size < SMP_MIN_ENC_KEY_SIZE))
Vinicius Costa Gomes3158c502011-06-14 13:37:42 -0300296 return SMP_ENC_KEY_SIZE;
297
Vinicius Costa Gomesf7aa6112012-01-30 19:29:12 -0300298 smp->enc_key_size = max_key_size;
Vinicius Costa Gomes3158c502011-06-14 13:37:42 -0300299
300 return 0;
301}
302
Johan Hedberg84794e12013-11-06 11:24:57 +0200303static void smp_failure(struct l2cap_conn *conn, u8 reason)
Brian Gix4f957a72011-11-23 08:28:36 -0800304{
Johan Hedbergbab73cb2012-02-09 16:07:29 +0200305 struct hci_conn *hcon = conn->hcon;
306
Johan Hedberg84794e12013-11-06 11:24:57 +0200307 if (reason)
Brian Gix4f957a72011-11-23 08:28:36 -0800308 smp_send_cmd(conn, SMP_CMD_PAIRING_FAIL, sizeof(reason),
Marcel Holtmannf1560462013-10-13 05:43:25 -0700309 &reason);
Brian Gix4f957a72011-11-23 08:28:36 -0800310
Marcel Holtmannce39fb42013-10-13 02:23:39 -0700311 clear_bit(HCI_CONN_ENCRYPT_PEND, &hcon->flags);
312 mgmt_auth_failed(hcon->hdev, &hcon->dst, hcon->type, hcon->dst_type,
313 HCI_ERROR_AUTH_FAILURE);
Vinicius Costa Gomesf1c09c02012-02-01 18:27:56 -0300314
Andre Guedes61a0cfb2012-08-01 20:34:15 -0300315 cancel_delayed_work_sync(&conn->security_timer);
316
Marcel Holtmannce39fb42013-10-13 02:23:39 -0700317 if (test_and_clear_bit(HCI_CONN_LE_SMP_PEND, &hcon->flags))
Vinicius Costa Gomesf1c09c02012-02-01 18:27:56 -0300318 smp_chan_destroy(conn);
Brian Gix4f957a72011-11-23 08:28:36 -0800319}
320
Brian Gix2b64d152011-12-21 16:12:12 -0800321#define JUST_WORKS 0x00
322#define JUST_CFM 0x01
323#define REQ_PASSKEY 0x02
324#define CFM_PASSKEY 0x03
325#define REQ_OOB 0x04
326#define OVERLAP 0xFF
327
328static const u8 gen_method[5][5] = {
329 { JUST_WORKS, JUST_CFM, REQ_PASSKEY, JUST_WORKS, REQ_PASSKEY },
330 { JUST_WORKS, JUST_CFM, REQ_PASSKEY, JUST_WORKS, REQ_PASSKEY },
331 { CFM_PASSKEY, CFM_PASSKEY, REQ_PASSKEY, JUST_WORKS, CFM_PASSKEY },
332 { JUST_WORKS, JUST_CFM, JUST_WORKS, JUST_WORKS, JUST_CFM },
333 { CFM_PASSKEY, CFM_PASSKEY, REQ_PASSKEY, JUST_WORKS, OVERLAP },
334};
335
336static int tk_request(struct l2cap_conn *conn, u8 remote_oob, u8 auth,
337 u8 local_io, u8 remote_io)
338{
339 struct hci_conn *hcon = conn->hcon;
340 struct smp_chan *smp = conn->smp_chan;
341 u8 method;
342 u32 passkey = 0;
343 int ret = 0;
344
345 /* Initialize key for JUST WORKS */
346 memset(smp->tk, 0, sizeof(smp->tk));
347 clear_bit(SMP_FLAG_TK_VALID, &smp->smp_flags);
348
349 BT_DBG("tk_request: auth:%d lcl:%d rem:%d", auth, local_io, remote_io);
350
351 /* If neither side wants MITM, use JUST WORKS */
352 /* If either side has unknown io_caps, use JUST WORKS */
353 /* Otherwise, look up method from the table */
354 if (!(auth & SMP_AUTH_MITM) ||
Marcel Holtmannf1560462013-10-13 05:43:25 -0700355 local_io > SMP_IO_KEYBOARD_DISPLAY ||
356 remote_io > SMP_IO_KEYBOARD_DISPLAY)
Brian Gix2b64d152011-12-21 16:12:12 -0800357 method = JUST_WORKS;
358 else
Ido Yarivb3ff53f2012-03-05 20:07:08 +0200359 method = gen_method[remote_io][local_io];
Brian Gix2b64d152011-12-21 16:12:12 -0800360
361 /* If not bonding, don't ask user to confirm a Zero TK */
362 if (!(auth & SMP_AUTH_BONDING) && method == JUST_CFM)
363 method = JUST_WORKS;
364
365 /* If Just Works, Continue with Zero TK */
366 if (method == JUST_WORKS) {
367 set_bit(SMP_FLAG_TK_VALID, &smp->smp_flags);
368 return 0;
369 }
370
371 /* Not Just Works/Confirm results in MITM Authentication */
372 if (method != JUST_CFM)
373 set_bit(SMP_FLAG_MITM_AUTH, &smp->smp_flags);
374
375 /* If both devices have Keyoard-Display I/O, the master
376 * Confirms and the slave Enters the passkey.
377 */
378 if (method == OVERLAP) {
379 if (hcon->link_mode & HCI_LM_MASTER)
380 method = CFM_PASSKEY;
381 else
382 method = REQ_PASSKEY;
383 }
384
385 /* Generate random passkey. Not valid until confirmed. */
386 if (method == CFM_PASSKEY) {
387 u8 key[16];
388
389 memset(key, 0, sizeof(key));
390 get_random_bytes(&passkey, sizeof(passkey));
391 passkey %= 1000000;
392 put_unaligned_le32(passkey, key);
393 swap128(key, smp->tk);
394 BT_DBG("PassKey: %d", passkey);
395 }
396
397 hci_dev_lock(hcon->hdev);
398
399 if (method == REQ_PASSKEY)
Marcel Holtmannce39fb42013-10-13 02:23:39 -0700400 ret = mgmt_user_passkey_request(hcon->hdev, &hcon->dst,
Johan Hedberg272d90d2012-02-09 15:26:12 +0200401 hcon->type, hcon->dst_type);
Brian Gix2b64d152011-12-21 16:12:12 -0800402 else
Marcel Holtmannce39fb42013-10-13 02:23:39 -0700403 ret = mgmt_user_confirm_request(hcon->hdev, &hcon->dst,
Johan Hedberg272d90d2012-02-09 15:26:12 +0200404 hcon->type, hcon->dst_type,
Brian Gix2b64d152011-12-21 16:12:12 -0800405 cpu_to_le32(passkey), 0);
406
407 hci_dev_unlock(hcon->hdev);
408
409 return ret;
410}
411
Vinicius Costa Gomes8aab4752011-09-05 14:31:31 -0300412static void confirm_work(struct work_struct *work)
413{
414 struct smp_chan *smp = container_of(work, struct smp_chan, confirm);
415 struct l2cap_conn *conn = smp->conn;
Johan Hedberg893ce8b2014-02-18 21:41:31 +0200416 struct hci_dev *hdev = conn->hcon->hdev;
417 struct crypto_blkcipher *tfm = hdev->tfm_aes;
Vinicius Costa Gomes8aab4752011-09-05 14:31:31 -0300418 struct smp_cmd_pairing_confirm cp;
419 int ret;
420 u8 res[16], reason;
421
422 BT_DBG("conn %p", conn);
423
Johan Hedberg893ce8b2014-02-18 21:41:31 +0200424 /* Prevent mutual access to hdev->tfm_aes */
425 hci_dev_lock(hdev);
Vinicius Costa Gomes8aab4752011-09-05 14:31:31 -0300426
427 if (conn->hcon->out)
Marcel Holtmannc8462ca2013-10-13 05:24:02 -0700428 ret = smp_c1(tfm, smp->tk, smp->prnd, smp->preq, smp->prsp,
429 conn->hcon->src_type, &conn->hcon->src,
430 conn->hcon->dst_type, &conn->hcon->dst, res);
Vinicius Costa Gomes8aab4752011-09-05 14:31:31 -0300431 else
432 ret = smp_c1(tfm, smp->tk, smp->prnd, smp->preq, smp->prsp,
Marcel Holtmannc8462ca2013-10-13 05:24:02 -0700433 conn->hcon->dst_type, &conn->hcon->dst,
434 conn->hcon->src_type, &conn->hcon->src, res);
Johan Hedberg893ce8b2014-02-18 21:41:31 +0200435
436 hci_dev_unlock(hdev);
437
Vinicius Costa Gomes8aab4752011-09-05 14:31:31 -0300438 if (ret) {
439 reason = SMP_UNSPECIFIED;
440 goto error;
441 }
442
Brian Gix2b64d152011-12-21 16:12:12 -0800443 clear_bit(SMP_FLAG_CFM_PENDING, &smp->smp_flags);
444
Vinicius Costa Gomes8aab4752011-09-05 14:31:31 -0300445 swap128(res, cp.confirm_val);
446 smp_send_cmd(smp->conn, SMP_CMD_PAIRING_CONFIRM, sizeof(cp), &cp);
447
448 return;
449
450error:
Johan Hedberg84794e12013-11-06 11:24:57 +0200451 smp_failure(conn, reason);
Vinicius Costa Gomes8aab4752011-09-05 14:31:31 -0300452}
453
454static void random_work(struct work_struct *work)
455{
456 struct smp_chan *smp = container_of(work, struct smp_chan, random);
457 struct l2cap_conn *conn = smp->conn;
458 struct hci_conn *hcon = conn->hcon;
Johan Hedberg893ce8b2014-02-18 21:41:31 +0200459 struct hci_dev *hdev = hcon->hdev;
460 struct crypto_blkcipher *tfm = hdev->tfm_aes;
Vinicius Costa Gomes8aab4752011-09-05 14:31:31 -0300461 u8 reason, confirm[16], res[16], key[16];
462 int ret;
463
464 if (IS_ERR_OR_NULL(tfm)) {
465 reason = SMP_UNSPECIFIED;
466 goto error;
467 }
468
469 BT_DBG("conn %p %s", conn, conn->hcon->out ? "master" : "slave");
470
Johan Hedberg893ce8b2014-02-18 21:41:31 +0200471 /* Prevent mutual access to hdev->tfm_aes */
472 hci_dev_lock(hdev);
473
Vinicius Costa Gomes8aab4752011-09-05 14:31:31 -0300474 if (hcon->out)
Marcel Holtmannc8462ca2013-10-13 05:24:02 -0700475 ret = smp_c1(tfm, smp->tk, smp->rrnd, smp->preq, smp->prsp,
476 hcon->src_type, &hcon->src,
477 hcon->dst_type, &hcon->dst, res);
Vinicius Costa Gomes8aab4752011-09-05 14:31:31 -0300478 else
479 ret = smp_c1(tfm, smp->tk, smp->rrnd, smp->preq, smp->prsp,
Marcel Holtmannc8462ca2013-10-13 05:24:02 -0700480 hcon->dst_type, &hcon->dst,
481 hcon->src_type, &hcon->src, res);
Johan Hedberg893ce8b2014-02-18 21:41:31 +0200482
483 hci_dev_unlock(hdev);
484
Vinicius Costa Gomes8aab4752011-09-05 14:31:31 -0300485 if (ret) {
486 reason = SMP_UNSPECIFIED;
487 goto error;
488 }
489
490 swap128(res, confirm);
491
492 if (memcmp(smp->pcnf, confirm, sizeof(smp->pcnf)) != 0) {
493 BT_ERR("Pairing failed (confirmation values mismatch)");
494 reason = SMP_CONFIRM_FAILED;
495 goto error;
496 }
497
498 if (hcon->out) {
499 u8 stk[16], rand[8];
500 __le16 ediv;
501
502 memset(rand, 0, sizeof(rand));
503 ediv = 0;
504
505 smp_s1(tfm, smp->tk, smp->rrnd, smp->prnd, key);
506 swap128(key, stk);
507
Vinicius Costa Gomesf7aa6112012-01-30 19:29:12 -0300508 memset(stk + smp->enc_key_size, 0,
Gustavo F. Padovan04124682012-03-08 01:25:00 -0300509 SMP_MAX_ENC_KEY_SIZE - smp->enc_key_size);
Vinicius Costa Gomes8aab4752011-09-05 14:31:31 -0300510
Johan Hedberg51a8efd2012-01-16 06:10:31 +0200511 if (test_and_set_bit(HCI_CONN_ENCRYPT_PEND, &hcon->flags)) {
Vinicius Costa Gomes8aab4752011-09-05 14:31:31 -0300512 reason = SMP_UNSPECIFIED;
513 goto error;
514 }
515
516 hci_le_start_enc(hcon, ediv, rand, stk);
Vinicius Costa Gomesf7aa6112012-01-30 19:29:12 -0300517 hcon->enc_key_size = smp->enc_key_size;
Vinicius Costa Gomes8aab4752011-09-05 14:31:31 -0300518 } else {
519 u8 stk[16], r[16], rand[8];
520 __le16 ediv;
521
522 memset(rand, 0, sizeof(rand));
523 ediv = 0;
524
525 swap128(smp->prnd, r);
526 smp_send_cmd(conn, SMP_CMD_PAIRING_RANDOM, sizeof(r), r);
527
528 smp_s1(tfm, smp->tk, smp->prnd, smp->rrnd, key);
529 swap128(key, stk);
530
Vinicius Costa Gomesf7aa6112012-01-30 19:29:12 -0300531 memset(stk + smp->enc_key_size, 0,
Marcel Holtmannf1560462013-10-13 05:43:25 -0700532 SMP_MAX_ENC_KEY_SIZE - smp->enc_key_size);
Vinicius Costa Gomes8aab4752011-09-05 14:31:31 -0300533
Marcel Holtmannce39fb42013-10-13 02:23:39 -0700534 hci_add_ltk(hcon->hdev, &hcon->dst, hcon->dst_type,
Johan Hedberg35d70272014-02-19 14:57:47 +0200535 HCI_SMP_STK_SLAVE, 0, stk, smp->enc_key_size,
Gustavo F. Padovan04124682012-03-08 01:25:00 -0300536 ediv, rand);
Vinicius Costa Gomes8aab4752011-09-05 14:31:31 -0300537 }
538
539 return;
540
541error:
Johan Hedberg84794e12013-11-06 11:24:57 +0200542 smp_failure(conn, reason);
Vinicius Costa Gomes8aab4752011-09-05 14:31:31 -0300543}
544
545static struct smp_chan *smp_chan_create(struct l2cap_conn *conn)
546{
547 struct smp_chan *smp;
548
Marcel Holtmannf1560462013-10-13 05:43:25 -0700549 smp = kzalloc(sizeof(*smp), GFP_ATOMIC);
Vinicius Costa Gomes8aab4752011-09-05 14:31:31 -0300550 if (!smp)
551 return NULL;
552
553 INIT_WORK(&smp->confirm, confirm_work);
554 INIT_WORK(&smp->random, random_work);
555
556 smp->conn = conn;
557 conn->smp_chan = smp;
Brian Gix2b64d152011-12-21 16:12:12 -0800558 conn->hcon->smp_conn = conn;
Vinicius Costa Gomes8aab4752011-09-05 14:31:31 -0300559
560 hci_conn_hold(conn->hcon);
561
562 return smp;
563}
564
565void smp_chan_destroy(struct l2cap_conn *conn)
566{
Brian Gixc8eb9692011-11-23 08:28:35 -0800567 struct smp_chan *smp = conn->smp_chan;
Johan Hedbergf4a407b2014-02-18 21:41:34 +0200568 bool complete;
Brian Gixc8eb9692011-11-23 08:28:35 -0800569
Vinicius Costa Gomesf1c09c02012-02-01 18:27:56 -0300570 BUG_ON(!smp);
Brian Gixc8eb9692011-11-23 08:28:35 -0800571
Johan Hedbergf4a407b2014-02-18 21:41:34 +0200572 complete = test_bit(SMP_FLAG_COMPLETE, &smp->smp_flags);
573 mgmt_smp_complete(conn->hcon, complete);
574
Brian Gixc8eb9692011-11-23 08:28:35 -0800575 kfree(smp);
576 conn->smp_chan = NULL;
Brian Gix2b64d152011-12-21 16:12:12 -0800577 conn->hcon->smp_conn = NULL;
David Herrmann76a68ba2013-04-06 20:28:37 +0200578 hci_conn_drop(conn->hcon);
Vinicius Costa Gomes8aab4752011-09-05 14:31:31 -0300579}
580
Brian Gix2b64d152011-12-21 16:12:12 -0800581int smp_user_confirm_reply(struct hci_conn *hcon, u16 mgmt_op, __le32 passkey)
582{
583 struct l2cap_conn *conn = hcon->smp_conn;
584 struct smp_chan *smp;
585 u32 value;
586 u8 key[16];
587
588 BT_DBG("");
589
590 if (!conn)
591 return -ENOTCONN;
592
593 smp = conn->smp_chan;
594
595 switch (mgmt_op) {
596 case MGMT_OP_USER_PASSKEY_REPLY:
597 value = le32_to_cpu(passkey);
598 memset(key, 0, sizeof(key));
599 BT_DBG("PassKey: %d", value);
600 put_unaligned_le32(value, key);
601 swap128(key, smp->tk);
602 /* Fall Through */
603 case MGMT_OP_USER_CONFIRM_REPLY:
604 set_bit(SMP_FLAG_TK_VALID, &smp->smp_flags);
605 break;
606 case MGMT_OP_USER_PASSKEY_NEG_REPLY:
607 case MGMT_OP_USER_CONFIRM_NEG_REPLY:
Johan Hedberg84794e12013-11-06 11:24:57 +0200608 smp_failure(conn, SMP_PASSKEY_ENTRY_FAILED);
Brian Gix2b64d152011-12-21 16:12:12 -0800609 return 0;
610 default:
Johan Hedberg84794e12013-11-06 11:24:57 +0200611 smp_failure(conn, SMP_PASSKEY_ENTRY_FAILED);
Brian Gix2b64d152011-12-21 16:12:12 -0800612 return -EOPNOTSUPP;
613 }
614
615 /* If it is our turn to send Pairing Confirm, do so now */
616 if (test_bit(SMP_FLAG_CFM_PENDING, &smp->smp_flags))
617 queue_work(hcon->hdev->workqueue, &smp->confirm);
618
619 return 0;
620}
621
Vinicius Costa Gomesda85e5e2011-06-09 18:50:53 -0300622static u8 smp_cmd_pairing_req(struct l2cap_conn *conn, struct sk_buff *skb)
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300623{
Vinicius Costa Gomes3158c502011-06-14 13:37:42 -0300624 struct smp_cmd_pairing rsp, *req = (void *) skb->data;
Vinicius Costa Gomes8aab4752011-09-05 14:31:31 -0300625 struct smp_chan *smp;
Vinicius Costa Gomes3158c502011-06-14 13:37:42 -0300626 u8 key_size;
Brian Gix2b64d152011-12-21 16:12:12 -0800627 u8 auth = SMP_AUTH_NONE;
Vinicius Costa Gomes8aab4752011-09-05 14:31:31 -0300628 int ret;
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300629
630 BT_DBG("conn %p", conn);
631
Johan Hedbergc46b98b2014-02-18 10:19:29 +0200632 if (skb->len < sizeof(*req))
633 return SMP_UNSPECIFIED;
634
Brian Gix2b64d152011-12-21 16:12:12 -0800635 if (conn->hcon->link_mode & HCI_LM_MASTER)
636 return SMP_CMD_NOTSUPP;
637
Johan Hedberg51a8efd2012-01-16 06:10:31 +0200638 if (!test_and_set_bit(HCI_CONN_LE_SMP_PEND, &conn->hcon->flags))
Vinicius Costa Gomes8aab4752011-09-05 14:31:31 -0300639 smp = smp_chan_create(conn);
Andrei Emeltchenkod08fd0e2012-07-19 17:03:43 +0300640 else
641 smp = conn->smp_chan;
Vinicius Costa Gomes8aab4752011-09-05 14:31:31 -0300642
Andrei Emeltchenkod08fd0e2012-07-19 17:03:43 +0300643 if (!smp)
644 return SMP_UNSPECIFIED;
Vinicius Costa Gomesd26a2342011-08-19 21:06:51 -0300645
Vinicius Costa Gomes1c1def02011-09-05 14:31:30 -0300646 smp->preq[0] = SMP_CMD_PAIRING_REQ;
647 memcpy(&smp->preq[1], req, sizeof(*req));
Vinicius Costa Gomes3158c502011-06-14 13:37:42 -0300648 skb_pull(skb, sizeof(*req));
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300649
Brian Gix2b64d152011-12-21 16:12:12 -0800650 /* We didn't start the pairing, so match remote */
651 if (req->auth_req & SMP_AUTH_BONDING)
652 auth = req->auth_req;
Vinicius Costa Gomesda85e5e2011-06-09 18:50:53 -0300653
Ido Yarivfdde0a22012-03-05 20:09:38 +0200654 conn->hcon->pending_sec_level = authreq_to_seclevel(auth);
655
Brian Gix2b64d152011-12-21 16:12:12 -0800656 build_pairing_cmd(conn, req, &rsp, auth);
Vinicius Costa Gomes3158c502011-06-14 13:37:42 -0300657
658 key_size = min(req->max_key_size, rsp.max_key_size);
659 if (check_enc_key_size(conn, key_size))
660 return SMP_ENC_KEY_SIZE;
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300661
Johan Hedberge84a6b12013-12-02 10:49:03 +0200662 get_random_bytes(smp->prnd, sizeof(smp->prnd));
Vinicius Costa Gomes8aab4752011-09-05 14:31:31 -0300663
Vinicius Costa Gomes1c1def02011-09-05 14:31:30 -0300664 smp->prsp[0] = SMP_CMD_PAIRING_RSP;
665 memcpy(&smp->prsp[1], &rsp, sizeof(rsp));
Anderson Brigliaf01ead32011-06-09 18:50:45 -0300666
Vinicius Costa Gomes3158c502011-06-14 13:37:42 -0300667 smp_send_cmd(conn, SMP_CMD_PAIRING_RSP, sizeof(rsp), &rsp);
Vinicius Costa Gomesda85e5e2011-06-09 18:50:53 -0300668
Brian Gix2b64d152011-12-21 16:12:12 -0800669 /* Request setup of TK */
670 ret = tk_request(conn, 0, auth, rsp.io_capability, req->io_capability);
671 if (ret)
672 return SMP_UNSPECIFIED;
673
Vinicius Costa Gomesda85e5e2011-06-09 18:50:53 -0300674 return 0;
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300675}
676
Vinicius Costa Gomesda85e5e2011-06-09 18:50:53 -0300677static u8 smp_cmd_pairing_rsp(struct l2cap_conn *conn, struct sk_buff *skb)
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300678{
Vinicius Costa Gomes3158c502011-06-14 13:37:42 -0300679 struct smp_cmd_pairing *req, *rsp = (void *) skb->data;
Vinicius Costa Gomes1c1def02011-09-05 14:31:30 -0300680 struct smp_chan *smp = conn->smp_chan;
Vinicius Costa Gomes8aab4752011-09-05 14:31:31 -0300681 struct hci_dev *hdev = conn->hcon->hdev;
Brian Gix2b64d152011-12-21 16:12:12 -0800682 u8 key_size, auth = SMP_AUTH_NONE;
Anderson Briglia7d24ddc2011-06-09 18:50:46 -0300683 int ret;
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300684
685 BT_DBG("conn %p", conn);
686
Johan Hedbergc46b98b2014-02-18 10:19:29 +0200687 if (skb->len < sizeof(*rsp))
688 return SMP_UNSPECIFIED;
689
Brian Gix2b64d152011-12-21 16:12:12 -0800690 if (!(conn->hcon->link_mode & HCI_LM_MASTER))
691 return SMP_CMD_NOTSUPP;
692
Vinicius Costa Gomes3158c502011-06-14 13:37:42 -0300693 skb_pull(skb, sizeof(*rsp));
Vinicius Costa Gomesda85e5e2011-06-09 18:50:53 -0300694
Vinicius Costa Gomes1c1def02011-09-05 14:31:30 -0300695 req = (void *) &smp->preq[1];
Vinicius Costa Gomes3158c502011-06-14 13:37:42 -0300696
697 key_size = min(req->max_key_size, rsp->max_key_size);
698 if (check_enc_key_size(conn, key_size))
699 return SMP_ENC_KEY_SIZE;
700
Johan Hedberge84a6b12013-12-02 10:49:03 +0200701 get_random_bytes(smp->prnd, sizeof(smp->prnd));
Anderson Briglia7d24ddc2011-06-09 18:50:46 -0300702
Vinicius Costa Gomes8aab4752011-09-05 14:31:31 -0300703 smp->prsp[0] = SMP_CMD_PAIRING_RSP;
704 memcpy(&smp->prsp[1], rsp, sizeof(*rsp));
Anderson Briglia7d24ddc2011-06-09 18:50:46 -0300705
Brian Gix2b64d152011-12-21 16:12:12 -0800706 if ((req->auth_req & SMP_AUTH_BONDING) &&
Marcel Holtmannf1560462013-10-13 05:43:25 -0700707 (rsp->auth_req & SMP_AUTH_BONDING))
Brian Gix2b64d152011-12-21 16:12:12 -0800708 auth = SMP_AUTH_BONDING;
709
710 auth |= (req->auth_req | rsp->auth_req) & SMP_AUTH_MITM;
711
Johan Hedberg476585e2012-06-06 18:54:15 +0800712 ret = tk_request(conn, 0, auth, req->io_capability, rsp->io_capability);
Brian Gix2b64d152011-12-21 16:12:12 -0800713 if (ret)
714 return SMP_UNSPECIFIED;
715
716 set_bit(SMP_FLAG_CFM_PENDING, &smp->smp_flags);
717
718 /* Can't compose response until we have been confirmed */
719 if (!test_bit(SMP_FLAG_TK_VALID, &smp->smp_flags))
720 return 0;
721
Vinicius Costa Gomes8aab4752011-09-05 14:31:31 -0300722 queue_work(hdev->workqueue, &smp->confirm);
Vinicius Costa Gomesda85e5e2011-06-09 18:50:53 -0300723
724 return 0;
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300725}
726
Vinicius Costa Gomesda85e5e2011-06-09 18:50:53 -0300727static u8 smp_cmd_pairing_confirm(struct l2cap_conn *conn, struct sk_buff *skb)
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300728{
Vinicius Costa Gomes1c1def02011-09-05 14:31:30 -0300729 struct smp_chan *smp = conn->smp_chan;
Vinicius Costa Gomes8aab4752011-09-05 14:31:31 -0300730 struct hci_dev *hdev = conn->hcon->hdev;
Anderson Briglia7d24ddc2011-06-09 18:50:46 -0300731
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300732 BT_DBG("conn %p %s", conn, conn->hcon->out ? "master" : "slave");
733
Johan Hedbergc46b98b2014-02-18 10:19:29 +0200734 if (skb->len < sizeof(smp->pcnf))
735 return SMP_UNSPECIFIED;
736
Vinicius Costa Gomes1c1def02011-09-05 14:31:30 -0300737 memcpy(smp->pcnf, skb->data, sizeof(smp->pcnf));
738 skb_pull(skb, sizeof(smp->pcnf));
Anderson Briglia7d24ddc2011-06-09 18:50:46 -0300739
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300740 if (conn->hcon->out) {
Anderson Briglia7d24ddc2011-06-09 18:50:46 -0300741 u8 random[16];
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300742
Vinicius Costa Gomes1c1def02011-09-05 14:31:30 -0300743 swap128(smp->prnd, random);
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300744 smp_send_cmd(conn, SMP_CMD_PAIRING_RANDOM, sizeof(random),
Marcel Holtmannf1560462013-10-13 05:43:25 -0700745 random);
Brian Gix2b64d152011-12-21 16:12:12 -0800746 } else if (test_bit(SMP_FLAG_TK_VALID, &smp->smp_flags)) {
Vinicius Costa Gomes8aab4752011-09-05 14:31:31 -0300747 queue_work(hdev->workqueue, &smp->confirm);
Brian Gix2b64d152011-12-21 16:12:12 -0800748 } else {
749 set_bit(SMP_FLAG_CFM_PENDING, &smp->smp_flags);
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300750 }
Vinicius Costa Gomesda85e5e2011-06-09 18:50:53 -0300751
752 return 0;
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300753}
754
Vinicius Costa Gomesda85e5e2011-06-09 18:50:53 -0300755static u8 smp_cmd_pairing_random(struct l2cap_conn *conn, struct sk_buff *skb)
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300756{
Vinicius Costa Gomes1c1def02011-09-05 14:31:30 -0300757 struct smp_chan *smp = conn->smp_chan;
Vinicius Costa Gomes8aab4752011-09-05 14:31:31 -0300758 struct hci_dev *hdev = conn->hcon->hdev;
Anderson Briglia7d24ddc2011-06-09 18:50:46 -0300759
Vinicius Costa Gomes8aab4752011-09-05 14:31:31 -0300760 BT_DBG("conn %p", conn);
Anderson Briglia7d24ddc2011-06-09 18:50:46 -0300761
Johan Hedbergc46b98b2014-02-18 10:19:29 +0200762 if (skb->len < sizeof(smp->rrnd))
763 return SMP_UNSPECIFIED;
764
Vinicius Costa Gomes8aab4752011-09-05 14:31:31 -0300765 swap128(skb->data, smp->rrnd);
766 skb_pull(skb, sizeof(smp->rrnd));
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300767
Vinicius Costa Gomes8aab4752011-09-05 14:31:31 -0300768 queue_work(hdev->workqueue, &smp->random);
Vinicius Costa Gomesda85e5e2011-06-09 18:50:53 -0300769
770 return 0;
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300771}
772
Johan Hedberg4dab7862012-06-07 14:58:37 +0800773static u8 smp_ltk_encrypt(struct l2cap_conn *conn, u8 sec_level)
Vinicius Costa Gomes988c5992011-08-25 20:02:28 -0300774{
Vinicius Costa Gomesc9839a12012-02-02 21:08:01 -0300775 struct smp_ltk *key;
Vinicius Costa Gomes988c5992011-08-25 20:02:28 -0300776 struct hci_conn *hcon = conn->hcon;
777
Johan Hedberg98a0b842014-01-30 19:40:00 -0800778 key = hci_find_ltk_by_addr(hcon->hdev, &hcon->dst, hcon->dst_type,
779 hcon->out);
Vinicius Costa Gomes988c5992011-08-25 20:02:28 -0300780 if (!key)
781 return 0;
782
Johan Hedberg4dab7862012-06-07 14:58:37 +0800783 if (sec_level > BT_SECURITY_MEDIUM && !key->authenticated)
784 return 0;
785
Johan Hedberg51a8efd2012-01-16 06:10:31 +0200786 if (test_and_set_bit(HCI_CONN_ENCRYPT_PEND, &hcon->flags))
Vinicius Costa Gomes988c5992011-08-25 20:02:28 -0300787 return 1;
788
Vinicius Costa Gomesc9839a12012-02-02 21:08:01 -0300789 hci_le_start_enc(hcon, key->ediv, key->rand, key->val);
790 hcon->enc_key_size = key->enc_size;
Vinicius Costa Gomes988c5992011-08-25 20:02:28 -0300791
792 return 1;
Vinicius Costa Gomes988c5992011-08-25 20:02:28 -0300793}
Marcel Holtmannf1560462013-10-13 05:43:25 -0700794
Vinicius Costa Gomesda85e5e2011-06-09 18:50:53 -0300795static u8 smp_cmd_security_req(struct l2cap_conn *conn, struct sk_buff *skb)
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300796{
797 struct smp_cmd_security_req *rp = (void *) skb->data;
798 struct smp_cmd_pairing cp;
Vinicius Costa Gomesf1cb9af2011-01-26 21:42:57 -0300799 struct hci_conn *hcon = conn->hcon;
Vinicius Costa Gomes8aab4752011-09-05 14:31:31 -0300800 struct smp_chan *smp;
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300801
802 BT_DBG("conn %p", conn);
803
Johan Hedbergc46b98b2014-02-18 10:19:29 +0200804 if (skb->len < sizeof(*rp))
805 return SMP_UNSPECIFIED;
806
Johan Hedberg86ca9ea2013-11-05 11:30:39 +0200807 if (!(conn->hcon->link_mode & HCI_LM_MASTER))
808 return SMP_CMD_NOTSUPP;
809
Brian Gix2b64d152011-12-21 16:12:12 -0800810 hcon->pending_sec_level = authreq_to_seclevel(rp->auth_req);
Vinicius Costa Gomesfeb45eb2011-08-25 20:02:35 -0300811
Johan Hedberg4dab7862012-06-07 14:58:37 +0800812 if (smp_ltk_encrypt(conn, hcon->pending_sec_level))
Vinicius Costa Gomes988c5992011-08-25 20:02:28 -0300813 return 0;
814
Johan Hedberg51a8efd2012-01-16 06:10:31 +0200815 if (test_and_set_bit(HCI_CONN_LE_SMP_PEND, &hcon->flags))
Vinicius Costa Gomesda85e5e2011-06-09 18:50:53 -0300816 return 0;
Vinicius Costa Gomesf1cb9af2011-01-26 21:42:57 -0300817
Vinicius Costa Gomes8aab4752011-09-05 14:31:31 -0300818 smp = smp_chan_create(conn);
Vinicius Costa Gomesd26a2342011-08-19 21:06:51 -0300819
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300820 skb_pull(skb, sizeof(*rp));
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300821
Vinicius Costa Gomesda85e5e2011-06-09 18:50:53 -0300822 memset(&cp, 0, sizeof(cp));
Vinicius Costa Gomes54790f72011-07-07 18:59:38 -0300823 build_pairing_cmd(conn, &cp, NULL, rp->auth_req);
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300824
Vinicius Costa Gomes1c1def02011-09-05 14:31:30 -0300825 smp->preq[0] = SMP_CMD_PAIRING_REQ;
826 memcpy(&smp->preq[1], &cp, sizeof(cp));
Anderson Brigliaf01ead32011-06-09 18:50:45 -0300827
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300828 smp_send_cmd(conn, SMP_CMD_PAIRING_REQ, sizeof(cp), &cp);
Vinicius Costa Gomesf1cb9af2011-01-26 21:42:57 -0300829
Vinicius Costa Gomesda85e5e2011-06-09 18:50:53 -0300830 return 0;
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300831}
832
Johan Hedbergad32a2f2013-05-14 18:05:12 +0300833bool smp_sufficient_security(struct hci_conn *hcon, u8 sec_level)
834{
835 if (sec_level == BT_SECURITY_LOW)
836 return true;
837
838 if (hcon->sec_level >= sec_level)
839 return true;
840
841 return false;
842}
843
Vinicius Costa Gomescc110922012-08-23 21:32:43 -0300844int smp_conn_security(struct hci_conn *hcon, __u8 sec_level)
Anderson Brigliaeb492e02011-06-09 18:50:40 -0300845{
Vinicius Costa Gomescc110922012-08-23 21:32:43 -0300846 struct l2cap_conn *conn = hcon->l2cap_data;
Vinicius Costa Gomes1c1def02011-09-05 14:31:30 -0300847 struct smp_chan *smp = conn->smp_chan;
Brian Gix2b64d152011-12-21 16:12:12 -0800848 __u8 authreq;
Anderson Brigliaeb492e02011-06-09 18:50:40 -0300849
Vinicius Costa Gomes3a0259b2011-06-09 18:50:43 -0300850 BT_DBG("conn %p hcon %p level 0x%2.2x", conn, hcon, sec_level);
851
Johan Hedberg757aee02013-04-24 13:05:32 +0300852 if (!test_bit(HCI_LE_ENABLED, &hcon->hdev->dev_flags))
Andre Guedes2e65c9d2011-06-30 19:20:56 -0300853 return 1;
854
Johan Hedbergad32a2f2013-05-14 18:05:12 +0300855 if (smp_sufficient_security(hcon, sec_level))
Vinicius Costa Gomesf1cb9af2011-01-26 21:42:57 -0300856 return 1;
857
Vinicius Costa Gomes988c5992011-08-25 20:02:28 -0300858 if (hcon->link_mode & HCI_LM_MASTER)
Johan Hedberg4dab7862012-06-07 14:58:37 +0800859 if (smp_ltk_encrypt(conn, sec_level))
Vinicius Costa Gomes02bc7452011-07-07 18:59:41 -0300860 goto done;
Vinicius Costa Gomesd26a2342011-08-19 21:06:51 -0300861
Johan Hedberg51a8efd2012-01-16 06:10:31 +0200862 if (test_and_set_bit(HCI_CONN_LE_SMP_PEND, &hcon->flags))
Vinicius Costa Gomesd26a2342011-08-19 21:06:51 -0300863 return 0;
864
Vinicius Costa Gomes8aab4752011-09-05 14:31:31 -0300865 smp = smp_chan_create(conn);
Brian Gix2b64d152011-12-21 16:12:12 -0800866 if (!smp)
867 return 1;
868
869 authreq = seclevel_to_authreq(sec_level);
Vinicius Costa Gomesd26a2342011-08-19 21:06:51 -0300870
Vinicius Costa Gomesd26a2342011-08-19 21:06:51 -0300871 if (hcon->link_mode & HCI_LM_MASTER) {
872 struct smp_cmd_pairing cp;
Anderson Brigliaf01ead32011-06-09 18:50:45 -0300873
Brian Gix2b64d152011-12-21 16:12:12 -0800874 build_pairing_cmd(conn, &cp, NULL, authreq);
Vinicius Costa Gomes1c1def02011-09-05 14:31:30 -0300875 smp->preq[0] = SMP_CMD_PAIRING_REQ;
876 memcpy(&smp->preq[1], &cp, sizeof(cp));
Anderson Brigliaf01ead32011-06-09 18:50:45 -0300877
Anderson Brigliaeb492e02011-06-09 18:50:40 -0300878 smp_send_cmd(conn, SMP_CMD_PAIRING_REQ, sizeof(cp), &cp);
879 } else {
880 struct smp_cmd_security_req cp;
Brian Gix2b64d152011-12-21 16:12:12 -0800881 cp.auth_req = authreq;
Anderson Brigliaeb492e02011-06-09 18:50:40 -0300882 smp_send_cmd(conn, SMP_CMD_SECURITY_REQ, sizeof(cp), &cp);
883 }
884
Vinicius Costa Gomes02bc7452011-07-07 18:59:41 -0300885done:
Vinicius Costa Gomesf1cb9af2011-01-26 21:42:57 -0300886 hcon->pending_sec_level = sec_level;
Vinicius Costa Gomesf1cb9af2011-01-26 21:42:57 -0300887
Anderson Brigliaeb492e02011-06-09 18:50:40 -0300888 return 0;
889}
890
Vinicius Costa Gomes7034b912011-07-07 18:59:34 -0300891static int smp_cmd_encrypt_info(struct l2cap_conn *conn, struct sk_buff *skb)
892{
Vinicius Costa Gomes16b90832011-07-07 18:59:39 -0300893 struct smp_cmd_encrypt_info *rp = (void *) skb->data;
Vinicius Costa Gomes1c1def02011-09-05 14:31:30 -0300894 struct smp_chan *smp = conn->smp_chan;
Vinicius Costa Gomes16b90832011-07-07 18:59:39 -0300895
Johan Hedbergc46b98b2014-02-18 10:19:29 +0200896 BT_DBG("conn %p", conn);
897
898 if (skb->len < sizeof(*rp))
899 return SMP_UNSPECIFIED;
900
Johan Hedberg6131ddc2014-02-18 10:19:37 +0200901 /* Ignore this PDU if it wasn't requested */
902 if (!(smp->remote_key_dist & SMP_DIST_ENC_KEY))
903 return 0;
904
Vinicius Costa Gomes16b90832011-07-07 18:59:39 -0300905 skb_pull(skb, sizeof(*rp));
906
Vinicius Costa Gomes1c1def02011-09-05 14:31:30 -0300907 memcpy(smp->tk, rp->ltk, sizeof(smp->tk));
Vinicius Costa Gomes16b90832011-07-07 18:59:39 -0300908
Vinicius Costa Gomes7034b912011-07-07 18:59:34 -0300909 return 0;
910}
911
912static int smp_cmd_master_ident(struct l2cap_conn *conn, struct sk_buff *skb)
913{
Vinicius Costa Gomes16b90832011-07-07 18:59:39 -0300914 struct smp_cmd_master_ident *rp = (void *) skb->data;
Vinicius Costa Gomes1c1def02011-09-05 14:31:30 -0300915 struct smp_chan *smp = conn->smp_chan;
Vinicius Costa Gomesc9839a12012-02-02 21:08:01 -0300916 struct hci_dev *hdev = conn->hcon->hdev;
917 struct hci_conn *hcon = conn->hcon;
Johan Hedberg23d0e122014-02-19 14:57:46 +0200918 struct smp_ltk *ltk;
Vinicius Costa Gomesc9839a12012-02-02 21:08:01 -0300919 u8 authenticated;
Vinicius Costa Gomes7034b912011-07-07 18:59:34 -0300920
Johan Hedbergc46b98b2014-02-18 10:19:29 +0200921 BT_DBG("conn %p", conn);
922
923 if (skb->len < sizeof(*rp))
924 return SMP_UNSPECIFIED;
925
Johan Hedberg6131ddc2014-02-18 10:19:37 +0200926 /* Ignore this PDU if it wasn't requested */
927 if (!(smp->remote_key_dist & SMP_DIST_ENC_KEY))
928 return 0;
929
Vinicius Costa Gomes16b90832011-07-07 18:59:39 -0300930 skb_pull(skb, sizeof(*rp));
931
Vinicius Costa Gomesc9839a12012-02-02 21:08:01 -0300932 hci_dev_lock(hdev);
Marcel Holtmannce39fb42013-10-13 02:23:39 -0700933 authenticated = (hcon->sec_level == BT_SECURITY_HIGH);
Johan Hedberg35d70272014-02-19 14:57:47 +0200934 ltk = hci_add_ltk(hdev, &hcon->dst, hcon->dst_type, HCI_SMP_LTK,
Johan Hedberg23d0e122014-02-19 14:57:46 +0200935 authenticated, smp->tk, smp->enc_key_size,
936 rp->ediv, rp->rand);
937 smp->ltk = ltk;
Johan Hedbergfd349c02014-02-18 10:19:36 +0200938 if (!(smp->remote_key_dist & SMP_DIST_ID_KEY))
939 smp_distribute_keys(conn, 1);
Vinicius Costa Gomesc9839a12012-02-02 21:08:01 -0300940 hci_dev_unlock(hdev);
Vinicius Costa Gomes7034b912011-07-07 18:59:34 -0300941
942 return 0;
943}
944
Johan Hedbergfd349c02014-02-18 10:19:36 +0200945static int smp_cmd_ident_info(struct l2cap_conn *conn, struct sk_buff *skb)
946{
947 struct smp_cmd_ident_info *info = (void *) skb->data;
948 struct smp_chan *smp = conn->smp_chan;
949
950 BT_DBG("");
951
952 if (skb->len < sizeof(*info))
953 return SMP_UNSPECIFIED;
954
Johan Hedberg6131ddc2014-02-18 10:19:37 +0200955 /* Ignore this PDU if it wasn't requested */
956 if (!(smp->remote_key_dist & SMP_DIST_ID_KEY))
957 return 0;
958
Johan Hedbergfd349c02014-02-18 10:19:36 +0200959 skb_pull(skb, sizeof(*info));
960
961 memcpy(smp->irk, info->irk, 16);
962
963 return 0;
964}
965
966static int smp_cmd_ident_addr_info(struct l2cap_conn *conn,
967 struct sk_buff *skb)
968{
969 struct smp_cmd_ident_addr_info *info = (void *) skb->data;
970 struct smp_chan *smp = conn->smp_chan;
971 struct hci_conn *hcon = conn->hcon;
972 bdaddr_t rpa;
973
974 BT_DBG("");
975
976 if (skb->len < sizeof(*info))
977 return SMP_UNSPECIFIED;
978
Johan Hedberg6131ddc2014-02-18 10:19:37 +0200979 /* Ignore this PDU if it wasn't requested */
980 if (!(smp->remote_key_dist & SMP_DIST_ID_KEY))
981 return 0;
982
Johan Hedbergfd349c02014-02-18 10:19:36 +0200983 skb_pull(skb, sizeof(*info));
984
985 bacpy(&smp->id_addr, &info->bdaddr);
986 smp->id_addr_type = info->addr_type;
987
988 if (hci_bdaddr_is_rpa(&hcon->dst, hcon->dst_type))
989 bacpy(&rpa, &hcon->dst);
990 else
991 bacpy(&rpa, BDADDR_ANY);
992
Johan Hedberg23d0e122014-02-19 14:57:46 +0200993 smp->remote_irk = hci_add_irk(conn->hcon->hdev, &smp->id_addr,
994 smp->id_addr_type, smp->irk, &rpa);
Johan Hedbergfd349c02014-02-18 10:19:36 +0200995
Johan Hedberg68d6f6d2014-02-18 21:41:32 +0200996 /* Track the connection based on the Identity Address from now on */
997 bacpy(&hcon->dst, &smp->id_addr);
998 hcon->dst_type = smp->id_addr_type;
999
Johan Hedberg387a33e2014-02-18 21:41:33 +02001000 l2cap_conn_update_id_addr(hcon);
1001
Johan Hedbergfd349c02014-02-18 10:19:36 +02001002 smp_distribute_keys(conn, 1);
1003
1004 return 0;
1005}
1006
Anderson Brigliaeb492e02011-06-09 18:50:40 -03001007int smp_sig_channel(struct l2cap_conn *conn, struct sk_buff *skb)
1008{
Marcel Holtmann7b9899d2013-10-03 00:00:57 -07001009 struct hci_conn *hcon = conn->hcon;
Marcel Holtmann92381f52013-10-03 01:23:08 -07001010 __u8 code, reason;
Anderson Brigliaeb492e02011-06-09 18:50:40 -03001011 int err = 0;
1012
Marcel Holtmann7b9899d2013-10-03 00:00:57 -07001013 if (hcon->type != LE_LINK) {
1014 kfree_skb(skb);
Johan Hedberg34327112013-10-16 11:37:01 +03001015 return 0;
Marcel Holtmann7b9899d2013-10-03 00:00:57 -07001016 }
1017
Marcel Holtmann92381f52013-10-03 01:23:08 -07001018 if (skb->len < 1) {
1019 kfree_skb(skb);
1020 return -EILSEQ;
1021 }
1022
Marcel Holtmann06ae3312013-10-18 03:43:00 -07001023 if (!test_bit(HCI_LE_ENABLED, &hcon->hdev->dev_flags)) {
Andre Guedes2e65c9d2011-06-30 19:20:56 -03001024 err = -ENOTSUPP;
1025 reason = SMP_PAIRING_NOTSUPP;
1026 goto done;
1027 }
1028
Marcel Holtmann92381f52013-10-03 01:23:08 -07001029 code = skb->data[0];
Anderson Brigliaeb492e02011-06-09 18:50:40 -03001030 skb_pull(skb, sizeof(code));
1031
Johan Hedberg8cf9fa12013-01-29 10:44:23 -06001032 /*
1033 * The SMP context must be initialized for all other PDUs except
1034 * pairing and security requests. If we get any other PDU when
1035 * not initialized simply disconnect (done if this function
1036 * returns an error).
1037 */
1038 if (code != SMP_CMD_PAIRING_REQ && code != SMP_CMD_SECURITY_REQ &&
1039 !conn->smp_chan) {
1040 BT_ERR("Unexpected SMP command 0x%02x. Disconnecting.", code);
1041 kfree_skb(skb);
1042 return -ENOTSUPP;
1043 }
1044
Anderson Brigliaeb492e02011-06-09 18:50:40 -03001045 switch (code) {
1046 case SMP_CMD_PAIRING_REQ:
Vinicius Costa Gomesda85e5e2011-06-09 18:50:53 -03001047 reason = smp_cmd_pairing_req(conn, skb);
Anderson Brigliaeb492e02011-06-09 18:50:40 -03001048 break;
1049
1050 case SMP_CMD_PAIRING_FAIL:
Johan Hedberg84794e12013-11-06 11:24:57 +02001051 smp_failure(conn, 0);
Vinicius Costa Gomesda85e5e2011-06-09 18:50:53 -03001052 reason = 0;
1053 err = -EPERM;
Anderson Brigliaeb492e02011-06-09 18:50:40 -03001054 break;
1055
1056 case SMP_CMD_PAIRING_RSP:
Vinicius Costa Gomesda85e5e2011-06-09 18:50:53 -03001057 reason = smp_cmd_pairing_rsp(conn, skb);
Anderson Briglia88ba43b2011-06-09 18:50:42 -03001058 break;
1059
1060 case SMP_CMD_SECURITY_REQ:
Vinicius Costa Gomesda85e5e2011-06-09 18:50:53 -03001061 reason = smp_cmd_security_req(conn, skb);
Anderson Briglia88ba43b2011-06-09 18:50:42 -03001062 break;
1063
Anderson Brigliaeb492e02011-06-09 18:50:40 -03001064 case SMP_CMD_PAIRING_CONFIRM:
Vinicius Costa Gomesda85e5e2011-06-09 18:50:53 -03001065 reason = smp_cmd_pairing_confirm(conn, skb);
Anderson Briglia88ba43b2011-06-09 18:50:42 -03001066 break;
1067
Anderson Brigliaeb492e02011-06-09 18:50:40 -03001068 case SMP_CMD_PAIRING_RANDOM:
Vinicius Costa Gomesda85e5e2011-06-09 18:50:53 -03001069 reason = smp_cmd_pairing_random(conn, skb);
Anderson Briglia88ba43b2011-06-09 18:50:42 -03001070 break;
1071
Anderson Brigliaeb492e02011-06-09 18:50:40 -03001072 case SMP_CMD_ENCRYPT_INFO:
Vinicius Costa Gomes7034b912011-07-07 18:59:34 -03001073 reason = smp_cmd_encrypt_info(conn, skb);
1074 break;
1075
Anderson Brigliaeb492e02011-06-09 18:50:40 -03001076 case SMP_CMD_MASTER_IDENT:
Vinicius Costa Gomes7034b912011-07-07 18:59:34 -03001077 reason = smp_cmd_master_ident(conn, skb);
1078 break;
1079
Anderson Brigliaeb492e02011-06-09 18:50:40 -03001080 case SMP_CMD_IDENT_INFO:
Johan Hedbergfd349c02014-02-18 10:19:36 +02001081 reason = smp_cmd_ident_info(conn, skb);
1082 break;
1083
Anderson Brigliaeb492e02011-06-09 18:50:40 -03001084 case SMP_CMD_IDENT_ADDR_INFO:
Johan Hedbergfd349c02014-02-18 10:19:36 +02001085 reason = smp_cmd_ident_addr_info(conn, skb);
1086 break;
1087
Anderson Brigliaeb492e02011-06-09 18:50:40 -03001088 case SMP_CMD_SIGN_INFO:
Vinicius Costa Gomes7034b912011-07-07 18:59:34 -03001089 /* Just ignored */
1090 reason = 0;
1091 break;
1092
Anderson Brigliaeb492e02011-06-09 18:50:40 -03001093 default:
1094 BT_DBG("Unknown command code 0x%2.2x", code);
1095
1096 reason = SMP_CMD_NOTSUPP;
Vinicius Costa Gomes3a0259b2011-06-09 18:50:43 -03001097 err = -EOPNOTSUPP;
1098 goto done;
1099 }
1100
1101done:
1102 if (reason)
Johan Hedberg84794e12013-11-06 11:24:57 +02001103 smp_failure(conn, reason);
Anderson Brigliaeb492e02011-06-09 18:50:40 -03001104
1105 kfree_skb(skb);
1106 return err;
1107}
Vinicius Costa Gomes7034b912011-07-07 18:59:34 -03001108
Johan Hedberg35d70272014-02-19 14:57:47 +02001109static void smp_notify_keys(struct l2cap_conn *conn)
1110{
1111 struct smp_chan *smp = conn->smp_chan;
1112 struct hci_conn *hcon = conn->hcon;
1113 struct hci_dev *hdev = hcon->hdev;
1114
Johan Hedberg95fbac82014-02-19 15:18:31 +02001115 if (smp->remote_irk)
1116 mgmt_new_irk(hdev, smp->remote_irk);
1117
Johan Hedberg35d70272014-02-19 14:57:47 +02001118 if (smp->ltk) {
1119 smp->ltk->bdaddr_type = hcon->dst_type;
1120 bacpy(&smp->ltk->bdaddr, &hcon->dst);
1121 mgmt_new_ltk(hdev, smp->ltk);
1122 }
1123
1124 if (smp->slave_ltk) {
1125 smp->slave_ltk->bdaddr_type = hcon->dst_type;
1126 bacpy(&smp->slave_ltk->bdaddr, &hcon->dst);
1127 mgmt_new_ltk(hdev, smp->slave_ltk);
1128 }
1129}
1130
Vinicius Costa Gomes7034b912011-07-07 18:59:34 -03001131int smp_distribute_keys(struct l2cap_conn *conn, __u8 force)
1132{
1133 struct smp_cmd_pairing *req, *rsp;
Vinicius Costa Gomes1c1def02011-09-05 14:31:30 -03001134 struct smp_chan *smp = conn->smp_chan;
Johan Hedberg524237c2014-02-22 19:06:31 +02001135 struct hci_conn *hcon = conn->hcon;
1136 struct hci_dev *hdev = hcon->hdev;
Vinicius Costa Gomes7034b912011-07-07 18:59:34 -03001137 __u8 *keydist;
1138
1139 BT_DBG("conn %p force %d", conn, force);
1140
Johan Hedberg524237c2014-02-22 19:06:31 +02001141 if (!test_bit(HCI_CONN_LE_SMP_PEND, &hcon->flags))
Vinicius Costa Gomesd26a2342011-08-19 21:06:51 -03001142 return 0;
1143
Vinicius Costa Gomes1c1def02011-09-05 14:31:30 -03001144 rsp = (void *) &smp->prsp[1];
Vinicius Costa Gomes7034b912011-07-07 18:59:34 -03001145
1146 /* The responder sends its keys first */
Johan Hedberg524237c2014-02-22 19:06:31 +02001147 if (!force && hcon->out && (rsp->resp_key_dist & 0x07))
Vinicius Costa Gomes7034b912011-07-07 18:59:34 -03001148 return 0;
1149
Vinicius Costa Gomes1c1def02011-09-05 14:31:30 -03001150 req = (void *) &smp->preq[1];
Vinicius Costa Gomes7034b912011-07-07 18:59:34 -03001151
Johan Hedberg524237c2014-02-22 19:06:31 +02001152 if (hcon->out) {
Vinicius Costa Gomes7034b912011-07-07 18:59:34 -03001153 keydist = &rsp->init_key_dist;
1154 *keydist &= req->init_key_dist;
1155 } else {
1156 keydist = &rsp->resp_key_dist;
1157 *keydist &= req->resp_key_dist;
1158 }
1159
Vinicius Costa Gomes7034b912011-07-07 18:59:34 -03001160 BT_DBG("keydist 0x%x", *keydist);
1161
1162 if (*keydist & SMP_DIST_ENC_KEY) {
1163 struct smp_cmd_encrypt_info enc;
1164 struct smp_cmd_master_ident ident;
Johan Hedberg23d0e122014-02-19 14:57:46 +02001165 struct smp_ltk *ltk;
Vinicius Costa Gomesc9839a12012-02-02 21:08:01 -03001166 u8 authenticated;
Vinicius Costa Gomes7034b912011-07-07 18:59:34 -03001167 __le16 ediv;
1168
1169 get_random_bytes(enc.ltk, sizeof(enc.ltk));
1170 get_random_bytes(&ediv, sizeof(ediv));
1171 get_random_bytes(ident.rand, sizeof(ident.rand));
1172
1173 smp_send_cmd(conn, SMP_CMD_ENCRYPT_INFO, sizeof(enc), &enc);
1174
Vinicius Costa Gomesc9839a12012-02-02 21:08:01 -03001175 authenticated = hcon->sec_level == BT_SECURITY_HIGH;
Johan Hedberg524237c2014-02-22 19:06:31 +02001176 ltk = hci_add_ltk(hdev, &hcon->dst, hcon->dst_type,
Johan Hedberg35d70272014-02-19 14:57:47 +02001177 HCI_SMP_LTK_SLAVE, authenticated, enc.ltk,
1178 smp->enc_key_size, ediv, ident.rand);
Johan Hedberg23d0e122014-02-19 14:57:46 +02001179 smp->slave_ltk = ltk;
Vinicius Costa Gomes16b90832011-07-07 18:59:39 -03001180
Andrei Emeltchenko58115372012-03-12 12:13:06 +02001181 ident.ediv = ediv;
Vinicius Costa Gomes7034b912011-07-07 18:59:34 -03001182
1183 smp_send_cmd(conn, SMP_CMD_MASTER_IDENT, sizeof(ident), &ident);
1184
1185 *keydist &= ~SMP_DIST_ENC_KEY;
1186 }
1187
1188 if (*keydist & SMP_DIST_ID_KEY) {
1189 struct smp_cmd_ident_addr_info addrinfo;
1190 struct smp_cmd_ident_info idinfo;
1191
1192 /* Send a dummy key */
1193 get_random_bytes(idinfo.irk, sizeof(idinfo.irk));
1194
1195 smp_send_cmd(conn, SMP_CMD_IDENT_INFO, sizeof(idinfo), &idinfo);
1196
1197 /* Just public address */
1198 memset(&addrinfo, 0, sizeof(addrinfo));
Johan Hedberg524237c2014-02-22 19:06:31 +02001199 bacpy(&addrinfo.bdaddr, &hcon->src);
Vinicius Costa Gomes7034b912011-07-07 18:59:34 -03001200
1201 smp_send_cmd(conn, SMP_CMD_IDENT_ADDR_INFO, sizeof(addrinfo),
Marcel Holtmannf1560462013-10-13 05:43:25 -07001202 &addrinfo);
Vinicius Costa Gomes7034b912011-07-07 18:59:34 -03001203
1204 *keydist &= ~SMP_DIST_ID_KEY;
1205 }
1206
1207 if (*keydist & SMP_DIST_SIGN) {
1208 struct smp_cmd_sign_info sign;
1209
1210 /* Send a dummy key */
1211 get_random_bytes(sign.csrk, sizeof(sign.csrk));
1212
1213 smp_send_cmd(conn, SMP_CMD_SIGN_INFO, sizeof(sign), &sign);
1214
1215 *keydist &= ~SMP_DIST_SIGN;
1216 }
1217
Johan Hedberg524237c2014-02-22 19:06:31 +02001218 if (hcon->out || force || !(rsp->init_key_dist & 0x07)) {
1219 clear_bit(HCI_CONN_LE_SMP_PEND, &hcon->flags);
Gustavo F. Padovan6c9d42a2011-12-20 10:57:27 -02001220 cancel_delayed_work_sync(&conn->security_timer);
Johan Hedbergf4a407b2014-02-18 21:41:34 +02001221 set_bit(SMP_FLAG_COMPLETE, &smp->smp_flags);
Johan Hedberg35d70272014-02-19 14:57:47 +02001222 smp_notify_keys(conn);
Vinicius Costa Gomes8aab4752011-09-05 14:31:31 -03001223 smp_chan_destroy(conn);
Vinicius Costa Gomesd26a2342011-08-19 21:06:51 -03001224 }
1225
Vinicius Costa Gomes7034b912011-07-07 18:59:34 -03001226 return 0;
1227}