blob: 8ef50c790b962f855f4a4509ce37e213281e06ff [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
Johan Hedberg863efaf2014-02-22 19:06:32 +0200268 if (test_bit(HCI_PRIVACY, &hdev->dev_flags))
269 local_dist |= SMP_DIST_ID_KEY;
270
Vinicius Costa Gomes54790f72011-07-07 18:59:38 -0300271 if (rsp == NULL) {
272 req->io_capability = conn->hcon->io_capability;
273 req->oob_flag = SMP_OOB_NOT_PRESENT;
274 req->max_key_size = SMP_MAX_ENC_KEY_SIZE;
Johan Hedbergfd349c02014-02-18 10:19:36 +0200275 req->init_key_dist = local_dist;
276 req->resp_key_dist = remote_dist;
Johan Hedberg065a13e2012-10-11 16:26:06 +0200277 req->auth_req = (authreq & AUTH_REQ_MASK);
Johan Hedbergfd349c02014-02-18 10:19:36 +0200278
279 smp->remote_key_dist = remote_dist;
Vinicius Costa Gomes54790f72011-07-07 18:59:38 -0300280 return;
281 }
282
283 rsp->io_capability = conn->hcon->io_capability;
284 rsp->oob_flag = SMP_OOB_NOT_PRESENT;
285 rsp->max_key_size = SMP_MAX_ENC_KEY_SIZE;
Johan Hedbergfd349c02014-02-18 10:19:36 +0200286 rsp->init_key_dist = req->init_key_dist & remote_dist;
287 rsp->resp_key_dist = req->resp_key_dist & local_dist;
Johan Hedberg065a13e2012-10-11 16:26:06 +0200288 rsp->auth_req = (authreq & AUTH_REQ_MASK);
Johan Hedbergfd349c02014-02-18 10:19:36 +0200289
290 smp->remote_key_dist = rsp->init_key_dist;
Vinicius Costa Gomesb8e66ea2011-06-09 18:50:52 -0300291}
292
Vinicius Costa Gomes3158c502011-06-14 13:37:42 -0300293static u8 check_enc_key_size(struct l2cap_conn *conn, __u8 max_key_size)
294{
Vinicius Costa Gomes1c1def02011-09-05 14:31:30 -0300295 struct smp_chan *smp = conn->smp_chan;
296
Vinicius Costa Gomes3158c502011-06-14 13:37:42 -0300297 if ((max_key_size > SMP_MAX_ENC_KEY_SIZE) ||
Marcel Holtmannf1560462013-10-13 05:43:25 -0700298 (max_key_size < SMP_MIN_ENC_KEY_SIZE))
Vinicius Costa Gomes3158c502011-06-14 13:37:42 -0300299 return SMP_ENC_KEY_SIZE;
300
Vinicius Costa Gomesf7aa6112012-01-30 19:29:12 -0300301 smp->enc_key_size = max_key_size;
Vinicius Costa Gomes3158c502011-06-14 13:37:42 -0300302
303 return 0;
304}
305
Johan Hedberg84794e12013-11-06 11:24:57 +0200306static void smp_failure(struct l2cap_conn *conn, u8 reason)
Brian Gix4f957a72011-11-23 08:28:36 -0800307{
Johan Hedbergbab73cb2012-02-09 16:07:29 +0200308 struct hci_conn *hcon = conn->hcon;
309
Johan Hedberg84794e12013-11-06 11:24:57 +0200310 if (reason)
Brian Gix4f957a72011-11-23 08:28:36 -0800311 smp_send_cmd(conn, SMP_CMD_PAIRING_FAIL, sizeof(reason),
Marcel Holtmannf1560462013-10-13 05:43:25 -0700312 &reason);
Brian Gix4f957a72011-11-23 08:28:36 -0800313
Marcel Holtmannce39fb42013-10-13 02:23:39 -0700314 clear_bit(HCI_CONN_ENCRYPT_PEND, &hcon->flags);
315 mgmt_auth_failed(hcon->hdev, &hcon->dst, hcon->type, hcon->dst_type,
316 HCI_ERROR_AUTH_FAILURE);
Vinicius Costa Gomesf1c09c02012-02-01 18:27:56 -0300317
Andre Guedes61a0cfb2012-08-01 20:34:15 -0300318 cancel_delayed_work_sync(&conn->security_timer);
319
Marcel Holtmannce39fb42013-10-13 02:23:39 -0700320 if (test_and_clear_bit(HCI_CONN_LE_SMP_PEND, &hcon->flags))
Vinicius Costa Gomesf1c09c02012-02-01 18:27:56 -0300321 smp_chan_destroy(conn);
Brian Gix4f957a72011-11-23 08:28:36 -0800322}
323
Brian Gix2b64d152011-12-21 16:12:12 -0800324#define JUST_WORKS 0x00
325#define JUST_CFM 0x01
326#define REQ_PASSKEY 0x02
327#define CFM_PASSKEY 0x03
328#define REQ_OOB 0x04
329#define OVERLAP 0xFF
330
331static const u8 gen_method[5][5] = {
332 { JUST_WORKS, JUST_CFM, REQ_PASSKEY, JUST_WORKS, REQ_PASSKEY },
333 { JUST_WORKS, JUST_CFM, REQ_PASSKEY, JUST_WORKS, REQ_PASSKEY },
334 { CFM_PASSKEY, CFM_PASSKEY, REQ_PASSKEY, JUST_WORKS, CFM_PASSKEY },
335 { JUST_WORKS, JUST_CFM, JUST_WORKS, JUST_WORKS, JUST_CFM },
336 { CFM_PASSKEY, CFM_PASSKEY, REQ_PASSKEY, JUST_WORKS, OVERLAP },
337};
338
339static int tk_request(struct l2cap_conn *conn, u8 remote_oob, u8 auth,
340 u8 local_io, u8 remote_io)
341{
342 struct hci_conn *hcon = conn->hcon;
343 struct smp_chan *smp = conn->smp_chan;
344 u8 method;
345 u32 passkey = 0;
346 int ret = 0;
347
348 /* Initialize key for JUST WORKS */
349 memset(smp->tk, 0, sizeof(smp->tk));
350 clear_bit(SMP_FLAG_TK_VALID, &smp->smp_flags);
351
352 BT_DBG("tk_request: auth:%d lcl:%d rem:%d", auth, local_io, remote_io);
353
354 /* If neither side wants MITM, use JUST WORKS */
355 /* If either side has unknown io_caps, use JUST WORKS */
356 /* Otherwise, look up method from the table */
357 if (!(auth & SMP_AUTH_MITM) ||
Marcel Holtmannf1560462013-10-13 05:43:25 -0700358 local_io > SMP_IO_KEYBOARD_DISPLAY ||
359 remote_io > SMP_IO_KEYBOARD_DISPLAY)
Brian Gix2b64d152011-12-21 16:12:12 -0800360 method = JUST_WORKS;
361 else
Ido Yarivb3ff53f2012-03-05 20:07:08 +0200362 method = gen_method[remote_io][local_io];
Brian Gix2b64d152011-12-21 16:12:12 -0800363
364 /* If not bonding, don't ask user to confirm a Zero TK */
365 if (!(auth & SMP_AUTH_BONDING) && method == JUST_CFM)
366 method = JUST_WORKS;
367
368 /* If Just Works, Continue with Zero TK */
369 if (method == JUST_WORKS) {
370 set_bit(SMP_FLAG_TK_VALID, &smp->smp_flags);
371 return 0;
372 }
373
374 /* Not Just Works/Confirm results in MITM Authentication */
375 if (method != JUST_CFM)
376 set_bit(SMP_FLAG_MITM_AUTH, &smp->smp_flags);
377
378 /* If both devices have Keyoard-Display I/O, the master
379 * Confirms and the slave Enters the passkey.
380 */
381 if (method == OVERLAP) {
382 if (hcon->link_mode & HCI_LM_MASTER)
383 method = CFM_PASSKEY;
384 else
385 method = REQ_PASSKEY;
386 }
387
388 /* Generate random passkey. Not valid until confirmed. */
389 if (method == CFM_PASSKEY) {
390 u8 key[16];
391
392 memset(key, 0, sizeof(key));
393 get_random_bytes(&passkey, sizeof(passkey));
394 passkey %= 1000000;
395 put_unaligned_le32(passkey, key);
396 swap128(key, smp->tk);
397 BT_DBG("PassKey: %d", passkey);
398 }
399
400 hci_dev_lock(hcon->hdev);
401
402 if (method == REQ_PASSKEY)
Marcel Holtmannce39fb42013-10-13 02:23:39 -0700403 ret = mgmt_user_passkey_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 else
Marcel Holtmannce39fb42013-10-13 02:23:39 -0700406 ret = mgmt_user_confirm_request(hcon->hdev, &hcon->dst,
Johan Hedberg272d90d2012-02-09 15:26:12 +0200407 hcon->type, hcon->dst_type,
Brian Gix2b64d152011-12-21 16:12:12 -0800408 cpu_to_le32(passkey), 0);
409
410 hci_dev_unlock(hcon->hdev);
411
412 return ret;
413}
414
Vinicius Costa Gomes8aab4752011-09-05 14:31:31 -0300415static void confirm_work(struct work_struct *work)
416{
417 struct smp_chan *smp = container_of(work, struct smp_chan, confirm);
418 struct l2cap_conn *conn = smp->conn;
Johan Hedberg893ce8b2014-02-18 21:41:31 +0200419 struct hci_dev *hdev = conn->hcon->hdev;
420 struct crypto_blkcipher *tfm = hdev->tfm_aes;
Vinicius Costa Gomes8aab4752011-09-05 14:31:31 -0300421 struct smp_cmd_pairing_confirm cp;
422 int ret;
423 u8 res[16], reason;
424
425 BT_DBG("conn %p", conn);
426
Johan Hedberg893ce8b2014-02-18 21:41:31 +0200427 /* Prevent mutual access to hdev->tfm_aes */
428 hci_dev_lock(hdev);
Vinicius Costa Gomes8aab4752011-09-05 14:31:31 -0300429
430 if (conn->hcon->out)
Marcel Holtmannc8462ca2013-10-13 05:24:02 -0700431 ret = smp_c1(tfm, smp->tk, smp->prnd, smp->preq, smp->prsp,
432 conn->hcon->src_type, &conn->hcon->src,
433 conn->hcon->dst_type, &conn->hcon->dst, res);
Vinicius Costa Gomes8aab4752011-09-05 14:31:31 -0300434 else
435 ret = smp_c1(tfm, smp->tk, smp->prnd, smp->preq, smp->prsp,
Marcel Holtmannc8462ca2013-10-13 05:24:02 -0700436 conn->hcon->dst_type, &conn->hcon->dst,
437 conn->hcon->src_type, &conn->hcon->src, res);
Johan Hedberg893ce8b2014-02-18 21:41:31 +0200438
439 hci_dev_unlock(hdev);
440
Vinicius Costa Gomes8aab4752011-09-05 14:31:31 -0300441 if (ret) {
442 reason = SMP_UNSPECIFIED;
443 goto error;
444 }
445
Brian Gix2b64d152011-12-21 16:12:12 -0800446 clear_bit(SMP_FLAG_CFM_PENDING, &smp->smp_flags);
447
Vinicius Costa Gomes8aab4752011-09-05 14:31:31 -0300448 swap128(res, cp.confirm_val);
449 smp_send_cmd(smp->conn, SMP_CMD_PAIRING_CONFIRM, sizeof(cp), &cp);
450
451 return;
452
453error:
Johan Hedberg84794e12013-11-06 11:24:57 +0200454 smp_failure(conn, reason);
Vinicius Costa Gomes8aab4752011-09-05 14:31:31 -0300455}
456
457static void random_work(struct work_struct *work)
458{
459 struct smp_chan *smp = container_of(work, struct smp_chan, random);
460 struct l2cap_conn *conn = smp->conn;
461 struct hci_conn *hcon = conn->hcon;
Johan Hedberg893ce8b2014-02-18 21:41:31 +0200462 struct hci_dev *hdev = hcon->hdev;
463 struct crypto_blkcipher *tfm = hdev->tfm_aes;
Vinicius Costa Gomes8aab4752011-09-05 14:31:31 -0300464 u8 reason, confirm[16], res[16], key[16];
465 int ret;
466
467 if (IS_ERR_OR_NULL(tfm)) {
468 reason = SMP_UNSPECIFIED;
469 goto error;
470 }
471
472 BT_DBG("conn %p %s", conn, conn->hcon->out ? "master" : "slave");
473
Johan Hedberg893ce8b2014-02-18 21:41:31 +0200474 /* Prevent mutual access to hdev->tfm_aes */
475 hci_dev_lock(hdev);
476
Vinicius Costa Gomes8aab4752011-09-05 14:31:31 -0300477 if (hcon->out)
Marcel Holtmannc8462ca2013-10-13 05:24:02 -0700478 ret = smp_c1(tfm, smp->tk, smp->rrnd, smp->preq, smp->prsp,
479 hcon->src_type, &hcon->src,
480 hcon->dst_type, &hcon->dst, res);
Vinicius Costa Gomes8aab4752011-09-05 14:31:31 -0300481 else
482 ret = smp_c1(tfm, smp->tk, smp->rrnd, smp->preq, smp->prsp,
Marcel Holtmannc8462ca2013-10-13 05:24:02 -0700483 hcon->dst_type, &hcon->dst,
484 hcon->src_type, &hcon->src, res);
Johan Hedberg893ce8b2014-02-18 21:41:31 +0200485
486 hci_dev_unlock(hdev);
487
Vinicius Costa Gomes8aab4752011-09-05 14:31:31 -0300488 if (ret) {
489 reason = SMP_UNSPECIFIED;
490 goto error;
491 }
492
493 swap128(res, confirm);
494
495 if (memcmp(smp->pcnf, confirm, sizeof(smp->pcnf)) != 0) {
496 BT_ERR("Pairing failed (confirmation values mismatch)");
497 reason = SMP_CONFIRM_FAILED;
498 goto error;
499 }
500
501 if (hcon->out) {
502 u8 stk[16], rand[8];
503 __le16 ediv;
504
505 memset(rand, 0, sizeof(rand));
506 ediv = 0;
507
508 smp_s1(tfm, smp->tk, smp->rrnd, smp->prnd, key);
509 swap128(key, stk);
510
Vinicius Costa Gomesf7aa6112012-01-30 19:29:12 -0300511 memset(stk + smp->enc_key_size, 0,
Gustavo F. Padovan04124682012-03-08 01:25:00 -0300512 SMP_MAX_ENC_KEY_SIZE - smp->enc_key_size);
Vinicius Costa Gomes8aab4752011-09-05 14:31:31 -0300513
Johan Hedberg51a8efd2012-01-16 06:10:31 +0200514 if (test_and_set_bit(HCI_CONN_ENCRYPT_PEND, &hcon->flags)) {
Vinicius Costa Gomes8aab4752011-09-05 14:31:31 -0300515 reason = SMP_UNSPECIFIED;
516 goto error;
517 }
518
519 hci_le_start_enc(hcon, ediv, rand, stk);
Vinicius Costa Gomesf7aa6112012-01-30 19:29:12 -0300520 hcon->enc_key_size = smp->enc_key_size;
Vinicius Costa Gomes8aab4752011-09-05 14:31:31 -0300521 } else {
522 u8 stk[16], r[16], rand[8];
523 __le16 ediv;
524
525 memset(rand, 0, sizeof(rand));
526 ediv = 0;
527
528 swap128(smp->prnd, r);
529 smp_send_cmd(conn, SMP_CMD_PAIRING_RANDOM, sizeof(r), r);
530
531 smp_s1(tfm, smp->tk, smp->prnd, smp->rrnd, key);
532 swap128(key, stk);
533
Vinicius Costa Gomesf7aa6112012-01-30 19:29:12 -0300534 memset(stk + smp->enc_key_size, 0,
Marcel Holtmannf1560462013-10-13 05:43:25 -0700535 SMP_MAX_ENC_KEY_SIZE - smp->enc_key_size);
Vinicius Costa Gomes8aab4752011-09-05 14:31:31 -0300536
Marcel Holtmannce39fb42013-10-13 02:23:39 -0700537 hci_add_ltk(hcon->hdev, &hcon->dst, hcon->dst_type,
Johan Hedberg35d70272014-02-19 14:57:47 +0200538 HCI_SMP_STK_SLAVE, 0, stk, smp->enc_key_size,
Gustavo F. Padovan04124682012-03-08 01:25:00 -0300539 ediv, rand);
Vinicius Costa Gomes8aab4752011-09-05 14:31:31 -0300540 }
541
542 return;
543
544error:
Johan Hedberg84794e12013-11-06 11:24:57 +0200545 smp_failure(conn, reason);
Vinicius Costa Gomes8aab4752011-09-05 14:31:31 -0300546}
547
548static struct smp_chan *smp_chan_create(struct l2cap_conn *conn)
549{
550 struct smp_chan *smp;
551
Marcel Holtmannf1560462013-10-13 05:43:25 -0700552 smp = kzalloc(sizeof(*smp), GFP_ATOMIC);
Vinicius Costa Gomes8aab4752011-09-05 14:31:31 -0300553 if (!smp)
554 return NULL;
555
556 INIT_WORK(&smp->confirm, confirm_work);
557 INIT_WORK(&smp->random, random_work);
558
559 smp->conn = conn;
560 conn->smp_chan = smp;
Brian Gix2b64d152011-12-21 16:12:12 -0800561 conn->hcon->smp_conn = conn;
Vinicius Costa Gomes8aab4752011-09-05 14:31:31 -0300562
563 hci_conn_hold(conn->hcon);
564
565 return smp;
566}
567
568void smp_chan_destroy(struct l2cap_conn *conn)
569{
Brian Gixc8eb9692011-11-23 08:28:35 -0800570 struct smp_chan *smp = conn->smp_chan;
Johan Hedbergf4a407b2014-02-18 21:41:34 +0200571 bool complete;
Brian Gixc8eb9692011-11-23 08:28:35 -0800572
Vinicius Costa Gomesf1c09c02012-02-01 18:27:56 -0300573 BUG_ON(!smp);
Brian Gixc8eb9692011-11-23 08:28:35 -0800574
Johan Hedbergf4a407b2014-02-18 21:41:34 +0200575 complete = test_bit(SMP_FLAG_COMPLETE, &smp->smp_flags);
576 mgmt_smp_complete(conn->hcon, complete);
577
Brian Gixc8eb9692011-11-23 08:28:35 -0800578 kfree(smp);
579 conn->smp_chan = NULL;
Brian Gix2b64d152011-12-21 16:12:12 -0800580 conn->hcon->smp_conn = NULL;
David Herrmann76a68ba2013-04-06 20:28:37 +0200581 hci_conn_drop(conn->hcon);
Vinicius Costa Gomes8aab4752011-09-05 14:31:31 -0300582}
583
Brian Gix2b64d152011-12-21 16:12:12 -0800584int smp_user_confirm_reply(struct hci_conn *hcon, u16 mgmt_op, __le32 passkey)
585{
586 struct l2cap_conn *conn = hcon->smp_conn;
587 struct smp_chan *smp;
588 u32 value;
589 u8 key[16];
590
591 BT_DBG("");
592
593 if (!conn)
594 return -ENOTCONN;
595
596 smp = conn->smp_chan;
597
598 switch (mgmt_op) {
599 case MGMT_OP_USER_PASSKEY_REPLY:
600 value = le32_to_cpu(passkey);
601 memset(key, 0, sizeof(key));
602 BT_DBG("PassKey: %d", value);
603 put_unaligned_le32(value, key);
604 swap128(key, smp->tk);
605 /* Fall Through */
606 case MGMT_OP_USER_CONFIRM_REPLY:
607 set_bit(SMP_FLAG_TK_VALID, &smp->smp_flags);
608 break;
609 case MGMT_OP_USER_PASSKEY_NEG_REPLY:
610 case MGMT_OP_USER_CONFIRM_NEG_REPLY:
Johan Hedberg84794e12013-11-06 11:24:57 +0200611 smp_failure(conn, SMP_PASSKEY_ENTRY_FAILED);
Brian Gix2b64d152011-12-21 16:12:12 -0800612 return 0;
613 default:
Johan Hedberg84794e12013-11-06 11:24:57 +0200614 smp_failure(conn, SMP_PASSKEY_ENTRY_FAILED);
Brian Gix2b64d152011-12-21 16:12:12 -0800615 return -EOPNOTSUPP;
616 }
617
618 /* If it is our turn to send Pairing Confirm, do so now */
619 if (test_bit(SMP_FLAG_CFM_PENDING, &smp->smp_flags))
620 queue_work(hcon->hdev->workqueue, &smp->confirm);
621
622 return 0;
623}
624
Vinicius Costa Gomesda85e5e2011-06-09 18:50:53 -0300625static u8 smp_cmd_pairing_req(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 rsp, *req = (void *) skb->data;
Vinicius Costa Gomes8aab4752011-09-05 14:31:31 -0300628 struct smp_chan *smp;
Vinicius Costa Gomes3158c502011-06-14 13:37:42 -0300629 u8 key_size;
Brian Gix2b64d152011-12-21 16:12:12 -0800630 u8 auth = SMP_AUTH_NONE;
Vinicius Costa Gomes8aab4752011-09-05 14:31:31 -0300631 int ret;
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300632
633 BT_DBG("conn %p", conn);
634
Johan Hedbergc46b98b2014-02-18 10:19:29 +0200635 if (skb->len < sizeof(*req))
636 return SMP_UNSPECIFIED;
637
Brian Gix2b64d152011-12-21 16:12:12 -0800638 if (conn->hcon->link_mode & HCI_LM_MASTER)
639 return SMP_CMD_NOTSUPP;
640
Johan Hedberg51a8efd2012-01-16 06:10:31 +0200641 if (!test_and_set_bit(HCI_CONN_LE_SMP_PEND, &conn->hcon->flags))
Vinicius Costa Gomes8aab4752011-09-05 14:31:31 -0300642 smp = smp_chan_create(conn);
Andrei Emeltchenkod08fd0e2012-07-19 17:03:43 +0300643 else
644 smp = conn->smp_chan;
Vinicius Costa Gomes8aab4752011-09-05 14:31:31 -0300645
Andrei Emeltchenkod08fd0e2012-07-19 17:03:43 +0300646 if (!smp)
647 return SMP_UNSPECIFIED;
Vinicius Costa Gomesd26a2342011-08-19 21:06:51 -0300648
Vinicius Costa Gomes1c1def02011-09-05 14:31:30 -0300649 smp->preq[0] = SMP_CMD_PAIRING_REQ;
650 memcpy(&smp->preq[1], req, sizeof(*req));
Vinicius Costa Gomes3158c502011-06-14 13:37:42 -0300651 skb_pull(skb, sizeof(*req));
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300652
Brian Gix2b64d152011-12-21 16:12:12 -0800653 /* We didn't start the pairing, so match remote */
654 if (req->auth_req & SMP_AUTH_BONDING)
655 auth = req->auth_req;
Vinicius Costa Gomesda85e5e2011-06-09 18:50:53 -0300656
Ido Yarivfdde0a22012-03-05 20:09:38 +0200657 conn->hcon->pending_sec_level = authreq_to_seclevel(auth);
658
Brian Gix2b64d152011-12-21 16:12:12 -0800659 build_pairing_cmd(conn, req, &rsp, auth);
Vinicius Costa Gomes3158c502011-06-14 13:37:42 -0300660
661 key_size = min(req->max_key_size, rsp.max_key_size);
662 if (check_enc_key_size(conn, key_size))
663 return SMP_ENC_KEY_SIZE;
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300664
Johan Hedberge84a6b12013-12-02 10:49:03 +0200665 get_random_bytes(smp->prnd, sizeof(smp->prnd));
Vinicius Costa Gomes8aab4752011-09-05 14:31:31 -0300666
Vinicius Costa Gomes1c1def02011-09-05 14:31:30 -0300667 smp->prsp[0] = SMP_CMD_PAIRING_RSP;
668 memcpy(&smp->prsp[1], &rsp, sizeof(rsp));
Anderson Brigliaf01ead32011-06-09 18:50:45 -0300669
Vinicius Costa Gomes3158c502011-06-14 13:37:42 -0300670 smp_send_cmd(conn, SMP_CMD_PAIRING_RSP, sizeof(rsp), &rsp);
Vinicius Costa Gomesda85e5e2011-06-09 18:50:53 -0300671
Brian Gix2b64d152011-12-21 16:12:12 -0800672 /* Request setup of TK */
673 ret = tk_request(conn, 0, auth, rsp.io_capability, req->io_capability);
674 if (ret)
675 return SMP_UNSPECIFIED;
676
Vinicius Costa Gomesda85e5e2011-06-09 18:50:53 -0300677 return 0;
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300678}
679
Vinicius Costa Gomesda85e5e2011-06-09 18:50:53 -0300680static u8 smp_cmd_pairing_rsp(struct l2cap_conn *conn, struct sk_buff *skb)
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300681{
Vinicius Costa Gomes3158c502011-06-14 13:37:42 -0300682 struct smp_cmd_pairing *req, *rsp = (void *) skb->data;
Vinicius Costa Gomes1c1def02011-09-05 14:31:30 -0300683 struct smp_chan *smp = conn->smp_chan;
Vinicius Costa Gomes8aab4752011-09-05 14:31:31 -0300684 struct hci_dev *hdev = conn->hcon->hdev;
Brian Gix2b64d152011-12-21 16:12:12 -0800685 u8 key_size, auth = SMP_AUTH_NONE;
Anderson Briglia7d24ddc2011-06-09 18:50:46 -0300686 int ret;
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300687
688 BT_DBG("conn %p", conn);
689
Johan Hedbergc46b98b2014-02-18 10:19:29 +0200690 if (skb->len < sizeof(*rsp))
691 return SMP_UNSPECIFIED;
692
Brian Gix2b64d152011-12-21 16:12:12 -0800693 if (!(conn->hcon->link_mode & HCI_LM_MASTER))
694 return SMP_CMD_NOTSUPP;
695
Vinicius Costa Gomes3158c502011-06-14 13:37:42 -0300696 skb_pull(skb, sizeof(*rsp));
Vinicius Costa Gomesda85e5e2011-06-09 18:50:53 -0300697
Vinicius Costa Gomes1c1def02011-09-05 14:31:30 -0300698 req = (void *) &smp->preq[1];
Vinicius Costa Gomes3158c502011-06-14 13:37:42 -0300699
700 key_size = min(req->max_key_size, rsp->max_key_size);
701 if (check_enc_key_size(conn, key_size))
702 return SMP_ENC_KEY_SIZE;
703
Johan Hedberge84a6b12013-12-02 10:49:03 +0200704 get_random_bytes(smp->prnd, sizeof(smp->prnd));
Anderson Briglia7d24ddc2011-06-09 18:50:46 -0300705
Vinicius Costa Gomes8aab4752011-09-05 14:31:31 -0300706 smp->prsp[0] = SMP_CMD_PAIRING_RSP;
707 memcpy(&smp->prsp[1], rsp, sizeof(*rsp));
Anderson Briglia7d24ddc2011-06-09 18:50:46 -0300708
Brian Gix2b64d152011-12-21 16:12:12 -0800709 if ((req->auth_req & SMP_AUTH_BONDING) &&
Marcel Holtmannf1560462013-10-13 05:43:25 -0700710 (rsp->auth_req & SMP_AUTH_BONDING))
Brian Gix2b64d152011-12-21 16:12:12 -0800711 auth = SMP_AUTH_BONDING;
712
713 auth |= (req->auth_req | rsp->auth_req) & SMP_AUTH_MITM;
714
Johan Hedberg476585e2012-06-06 18:54:15 +0800715 ret = tk_request(conn, 0, auth, req->io_capability, rsp->io_capability);
Brian Gix2b64d152011-12-21 16:12:12 -0800716 if (ret)
717 return SMP_UNSPECIFIED;
718
719 set_bit(SMP_FLAG_CFM_PENDING, &smp->smp_flags);
720
721 /* Can't compose response until we have been confirmed */
722 if (!test_bit(SMP_FLAG_TK_VALID, &smp->smp_flags))
723 return 0;
724
Vinicius Costa Gomes8aab4752011-09-05 14:31:31 -0300725 queue_work(hdev->workqueue, &smp->confirm);
Vinicius Costa Gomesda85e5e2011-06-09 18:50:53 -0300726
727 return 0;
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300728}
729
Vinicius Costa Gomesda85e5e2011-06-09 18:50:53 -0300730static u8 smp_cmd_pairing_confirm(struct l2cap_conn *conn, struct sk_buff *skb)
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300731{
Vinicius Costa Gomes1c1def02011-09-05 14:31:30 -0300732 struct smp_chan *smp = conn->smp_chan;
Vinicius Costa Gomes8aab4752011-09-05 14:31:31 -0300733 struct hci_dev *hdev = conn->hcon->hdev;
Anderson Briglia7d24ddc2011-06-09 18:50:46 -0300734
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300735 BT_DBG("conn %p %s", conn, conn->hcon->out ? "master" : "slave");
736
Johan Hedbergc46b98b2014-02-18 10:19:29 +0200737 if (skb->len < sizeof(smp->pcnf))
738 return SMP_UNSPECIFIED;
739
Vinicius Costa Gomes1c1def02011-09-05 14:31:30 -0300740 memcpy(smp->pcnf, skb->data, sizeof(smp->pcnf));
741 skb_pull(skb, sizeof(smp->pcnf));
Anderson Briglia7d24ddc2011-06-09 18:50:46 -0300742
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300743 if (conn->hcon->out) {
Anderson Briglia7d24ddc2011-06-09 18:50:46 -0300744 u8 random[16];
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300745
Vinicius Costa Gomes1c1def02011-09-05 14:31:30 -0300746 swap128(smp->prnd, random);
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300747 smp_send_cmd(conn, SMP_CMD_PAIRING_RANDOM, sizeof(random),
Marcel Holtmannf1560462013-10-13 05:43:25 -0700748 random);
Brian Gix2b64d152011-12-21 16:12:12 -0800749 } else if (test_bit(SMP_FLAG_TK_VALID, &smp->smp_flags)) {
Vinicius Costa Gomes8aab4752011-09-05 14:31:31 -0300750 queue_work(hdev->workqueue, &smp->confirm);
Brian Gix2b64d152011-12-21 16:12:12 -0800751 } else {
752 set_bit(SMP_FLAG_CFM_PENDING, &smp->smp_flags);
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300753 }
Vinicius Costa Gomesda85e5e2011-06-09 18:50:53 -0300754
755 return 0;
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300756}
757
Vinicius Costa Gomesda85e5e2011-06-09 18:50:53 -0300758static u8 smp_cmd_pairing_random(struct l2cap_conn *conn, struct sk_buff *skb)
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300759{
Vinicius Costa Gomes1c1def02011-09-05 14:31:30 -0300760 struct smp_chan *smp = conn->smp_chan;
Vinicius Costa Gomes8aab4752011-09-05 14:31:31 -0300761 struct hci_dev *hdev = conn->hcon->hdev;
Anderson Briglia7d24ddc2011-06-09 18:50:46 -0300762
Vinicius Costa Gomes8aab4752011-09-05 14:31:31 -0300763 BT_DBG("conn %p", conn);
Anderson Briglia7d24ddc2011-06-09 18:50:46 -0300764
Johan Hedbergc46b98b2014-02-18 10:19:29 +0200765 if (skb->len < sizeof(smp->rrnd))
766 return SMP_UNSPECIFIED;
767
Vinicius Costa Gomes8aab4752011-09-05 14:31:31 -0300768 swap128(skb->data, smp->rrnd);
769 skb_pull(skb, sizeof(smp->rrnd));
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300770
Vinicius Costa Gomes8aab4752011-09-05 14:31:31 -0300771 queue_work(hdev->workqueue, &smp->random);
Vinicius Costa Gomesda85e5e2011-06-09 18:50:53 -0300772
773 return 0;
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300774}
775
Johan Hedberg4dab7862012-06-07 14:58:37 +0800776static u8 smp_ltk_encrypt(struct l2cap_conn *conn, u8 sec_level)
Vinicius Costa Gomes988c5992011-08-25 20:02:28 -0300777{
Vinicius Costa Gomesc9839a12012-02-02 21:08:01 -0300778 struct smp_ltk *key;
Vinicius Costa Gomes988c5992011-08-25 20:02:28 -0300779 struct hci_conn *hcon = conn->hcon;
780
Johan Hedberg98a0b842014-01-30 19:40:00 -0800781 key = hci_find_ltk_by_addr(hcon->hdev, &hcon->dst, hcon->dst_type,
782 hcon->out);
Vinicius Costa Gomes988c5992011-08-25 20:02:28 -0300783 if (!key)
784 return 0;
785
Johan Hedberg4dab7862012-06-07 14:58:37 +0800786 if (sec_level > BT_SECURITY_MEDIUM && !key->authenticated)
787 return 0;
788
Johan Hedberg51a8efd2012-01-16 06:10:31 +0200789 if (test_and_set_bit(HCI_CONN_ENCRYPT_PEND, &hcon->flags))
Vinicius Costa Gomes988c5992011-08-25 20:02:28 -0300790 return 1;
791
Vinicius Costa Gomesc9839a12012-02-02 21:08:01 -0300792 hci_le_start_enc(hcon, key->ediv, key->rand, key->val);
793 hcon->enc_key_size = key->enc_size;
Vinicius Costa Gomes988c5992011-08-25 20:02:28 -0300794
795 return 1;
Vinicius Costa Gomes988c5992011-08-25 20:02:28 -0300796}
Marcel Holtmannf1560462013-10-13 05:43:25 -0700797
Vinicius Costa Gomesda85e5e2011-06-09 18:50:53 -0300798static u8 smp_cmd_security_req(struct l2cap_conn *conn, struct sk_buff *skb)
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300799{
800 struct smp_cmd_security_req *rp = (void *) skb->data;
801 struct smp_cmd_pairing cp;
Vinicius Costa Gomesf1cb9af2011-01-26 21:42:57 -0300802 struct hci_conn *hcon = conn->hcon;
Vinicius Costa Gomes8aab4752011-09-05 14:31:31 -0300803 struct smp_chan *smp;
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300804
805 BT_DBG("conn %p", conn);
806
Johan Hedbergc46b98b2014-02-18 10:19:29 +0200807 if (skb->len < sizeof(*rp))
808 return SMP_UNSPECIFIED;
809
Johan Hedberg86ca9ea2013-11-05 11:30:39 +0200810 if (!(conn->hcon->link_mode & HCI_LM_MASTER))
811 return SMP_CMD_NOTSUPP;
812
Brian Gix2b64d152011-12-21 16:12:12 -0800813 hcon->pending_sec_level = authreq_to_seclevel(rp->auth_req);
Vinicius Costa Gomesfeb45eb2011-08-25 20:02:35 -0300814
Johan Hedberg4dab7862012-06-07 14:58:37 +0800815 if (smp_ltk_encrypt(conn, hcon->pending_sec_level))
Vinicius Costa Gomes988c5992011-08-25 20:02:28 -0300816 return 0;
817
Johan Hedberg51a8efd2012-01-16 06:10:31 +0200818 if (test_and_set_bit(HCI_CONN_LE_SMP_PEND, &hcon->flags))
Vinicius Costa Gomesda85e5e2011-06-09 18:50:53 -0300819 return 0;
Vinicius Costa Gomesf1cb9af2011-01-26 21:42:57 -0300820
Vinicius Costa Gomes8aab4752011-09-05 14:31:31 -0300821 smp = smp_chan_create(conn);
Vinicius Costa Gomesd26a2342011-08-19 21:06:51 -0300822
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300823 skb_pull(skb, sizeof(*rp));
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300824
Vinicius Costa Gomesda85e5e2011-06-09 18:50:53 -0300825 memset(&cp, 0, sizeof(cp));
Vinicius Costa Gomes54790f72011-07-07 18:59:38 -0300826 build_pairing_cmd(conn, &cp, NULL, rp->auth_req);
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300827
Vinicius Costa Gomes1c1def02011-09-05 14:31:30 -0300828 smp->preq[0] = SMP_CMD_PAIRING_REQ;
829 memcpy(&smp->preq[1], &cp, sizeof(cp));
Anderson Brigliaf01ead32011-06-09 18:50:45 -0300830
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300831 smp_send_cmd(conn, SMP_CMD_PAIRING_REQ, sizeof(cp), &cp);
Vinicius Costa Gomesf1cb9af2011-01-26 21:42:57 -0300832
Vinicius Costa Gomesda85e5e2011-06-09 18:50:53 -0300833 return 0;
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300834}
835
Johan Hedbergad32a2f2013-05-14 18:05:12 +0300836bool smp_sufficient_security(struct hci_conn *hcon, u8 sec_level)
837{
838 if (sec_level == BT_SECURITY_LOW)
839 return true;
840
841 if (hcon->sec_level >= sec_level)
842 return true;
843
844 return false;
845}
846
Vinicius Costa Gomescc110922012-08-23 21:32:43 -0300847int smp_conn_security(struct hci_conn *hcon, __u8 sec_level)
Anderson Brigliaeb492e02011-06-09 18:50:40 -0300848{
Vinicius Costa Gomescc110922012-08-23 21:32:43 -0300849 struct l2cap_conn *conn = hcon->l2cap_data;
Vinicius Costa Gomes1c1def02011-09-05 14:31:30 -0300850 struct smp_chan *smp = conn->smp_chan;
Brian Gix2b64d152011-12-21 16:12:12 -0800851 __u8 authreq;
Anderson Brigliaeb492e02011-06-09 18:50:40 -0300852
Vinicius Costa Gomes3a0259b2011-06-09 18:50:43 -0300853 BT_DBG("conn %p hcon %p level 0x%2.2x", conn, hcon, sec_level);
854
Johan Hedberg757aee02013-04-24 13:05:32 +0300855 if (!test_bit(HCI_LE_ENABLED, &hcon->hdev->dev_flags))
Andre Guedes2e65c9d2011-06-30 19:20:56 -0300856 return 1;
857
Johan Hedbergad32a2f2013-05-14 18:05:12 +0300858 if (smp_sufficient_security(hcon, sec_level))
Vinicius Costa Gomesf1cb9af2011-01-26 21:42:57 -0300859 return 1;
860
Vinicius Costa Gomes988c5992011-08-25 20:02:28 -0300861 if (hcon->link_mode & HCI_LM_MASTER)
Johan Hedberg4dab7862012-06-07 14:58:37 +0800862 if (smp_ltk_encrypt(conn, sec_level))
Vinicius Costa Gomes02bc7452011-07-07 18:59:41 -0300863 goto done;
Vinicius Costa Gomesd26a2342011-08-19 21:06:51 -0300864
Johan Hedberg51a8efd2012-01-16 06:10:31 +0200865 if (test_and_set_bit(HCI_CONN_LE_SMP_PEND, &hcon->flags))
Vinicius Costa Gomesd26a2342011-08-19 21:06:51 -0300866 return 0;
867
Vinicius Costa Gomes8aab4752011-09-05 14:31:31 -0300868 smp = smp_chan_create(conn);
Brian Gix2b64d152011-12-21 16:12:12 -0800869 if (!smp)
870 return 1;
871
872 authreq = seclevel_to_authreq(sec_level);
Vinicius Costa Gomesd26a2342011-08-19 21:06:51 -0300873
Vinicius Costa Gomesd26a2342011-08-19 21:06:51 -0300874 if (hcon->link_mode & HCI_LM_MASTER) {
875 struct smp_cmd_pairing cp;
Anderson Brigliaf01ead32011-06-09 18:50:45 -0300876
Brian Gix2b64d152011-12-21 16:12:12 -0800877 build_pairing_cmd(conn, &cp, NULL, authreq);
Vinicius Costa Gomes1c1def02011-09-05 14:31:30 -0300878 smp->preq[0] = SMP_CMD_PAIRING_REQ;
879 memcpy(&smp->preq[1], &cp, sizeof(cp));
Anderson Brigliaf01ead32011-06-09 18:50:45 -0300880
Anderson Brigliaeb492e02011-06-09 18:50:40 -0300881 smp_send_cmd(conn, SMP_CMD_PAIRING_REQ, sizeof(cp), &cp);
882 } else {
883 struct smp_cmd_security_req cp;
Brian Gix2b64d152011-12-21 16:12:12 -0800884 cp.auth_req = authreq;
Anderson Brigliaeb492e02011-06-09 18:50:40 -0300885 smp_send_cmd(conn, SMP_CMD_SECURITY_REQ, sizeof(cp), &cp);
886 }
887
Vinicius Costa Gomes02bc7452011-07-07 18:59:41 -0300888done:
Vinicius Costa Gomesf1cb9af2011-01-26 21:42:57 -0300889 hcon->pending_sec_level = sec_level;
Vinicius Costa Gomesf1cb9af2011-01-26 21:42:57 -0300890
Anderson Brigliaeb492e02011-06-09 18:50:40 -0300891 return 0;
892}
893
Vinicius Costa Gomes7034b912011-07-07 18:59:34 -0300894static int smp_cmd_encrypt_info(struct l2cap_conn *conn, struct sk_buff *skb)
895{
Vinicius Costa Gomes16b90832011-07-07 18:59:39 -0300896 struct smp_cmd_encrypt_info *rp = (void *) skb->data;
Vinicius Costa Gomes1c1def02011-09-05 14:31:30 -0300897 struct smp_chan *smp = conn->smp_chan;
Vinicius Costa Gomes16b90832011-07-07 18:59:39 -0300898
Johan Hedbergc46b98b2014-02-18 10:19:29 +0200899 BT_DBG("conn %p", conn);
900
901 if (skb->len < sizeof(*rp))
902 return SMP_UNSPECIFIED;
903
Johan Hedberg6131ddc2014-02-18 10:19:37 +0200904 /* Ignore this PDU if it wasn't requested */
905 if (!(smp->remote_key_dist & SMP_DIST_ENC_KEY))
906 return 0;
907
Vinicius Costa Gomes16b90832011-07-07 18:59:39 -0300908 skb_pull(skb, sizeof(*rp));
909
Vinicius Costa Gomes1c1def02011-09-05 14:31:30 -0300910 memcpy(smp->tk, rp->ltk, sizeof(smp->tk));
Vinicius Costa Gomes16b90832011-07-07 18:59:39 -0300911
Vinicius Costa Gomes7034b912011-07-07 18:59:34 -0300912 return 0;
913}
914
915static int smp_cmd_master_ident(struct l2cap_conn *conn, struct sk_buff *skb)
916{
Vinicius Costa Gomes16b90832011-07-07 18:59:39 -0300917 struct smp_cmd_master_ident *rp = (void *) skb->data;
Vinicius Costa Gomes1c1def02011-09-05 14:31:30 -0300918 struct smp_chan *smp = conn->smp_chan;
Vinicius Costa Gomesc9839a12012-02-02 21:08:01 -0300919 struct hci_dev *hdev = conn->hcon->hdev;
920 struct hci_conn *hcon = conn->hcon;
Johan Hedberg23d0e122014-02-19 14:57:46 +0200921 struct smp_ltk *ltk;
Vinicius Costa Gomesc9839a12012-02-02 21:08:01 -0300922 u8 authenticated;
Vinicius Costa Gomes7034b912011-07-07 18:59:34 -0300923
Johan Hedbergc46b98b2014-02-18 10:19:29 +0200924 BT_DBG("conn %p", conn);
925
926 if (skb->len < sizeof(*rp))
927 return SMP_UNSPECIFIED;
928
Johan Hedberg6131ddc2014-02-18 10:19:37 +0200929 /* Ignore this PDU if it wasn't requested */
930 if (!(smp->remote_key_dist & SMP_DIST_ENC_KEY))
931 return 0;
932
Vinicius Costa Gomes16b90832011-07-07 18:59:39 -0300933 skb_pull(skb, sizeof(*rp));
934
Vinicius Costa Gomesc9839a12012-02-02 21:08:01 -0300935 hci_dev_lock(hdev);
Marcel Holtmannce39fb42013-10-13 02:23:39 -0700936 authenticated = (hcon->sec_level == BT_SECURITY_HIGH);
Johan Hedberg35d70272014-02-19 14:57:47 +0200937 ltk = hci_add_ltk(hdev, &hcon->dst, hcon->dst_type, HCI_SMP_LTK,
Johan Hedberg23d0e122014-02-19 14:57:46 +0200938 authenticated, smp->tk, smp->enc_key_size,
939 rp->ediv, rp->rand);
940 smp->ltk = ltk;
Johan Hedbergfd349c02014-02-18 10:19:36 +0200941 if (!(smp->remote_key_dist & SMP_DIST_ID_KEY))
942 smp_distribute_keys(conn, 1);
Vinicius Costa Gomesc9839a12012-02-02 21:08:01 -0300943 hci_dev_unlock(hdev);
Vinicius Costa Gomes7034b912011-07-07 18:59:34 -0300944
945 return 0;
946}
947
Johan Hedbergfd349c02014-02-18 10:19:36 +0200948static int smp_cmd_ident_info(struct l2cap_conn *conn, struct sk_buff *skb)
949{
950 struct smp_cmd_ident_info *info = (void *) skb->data;
951 struct smp_chan *smp = conn->smp_chan;
952
953 BT_DBG("");
954
955 if (skb->len < sizeof(*info))
956 return SMP_UNSPECIFIED;
957
Johan Hedberg6131ddc2014-02-18 10:19:37 +0200958 /* Ignore this PDU if it wasn't requested */
959 if (!(smp->remote_key_dist & SMP_DIST_ID_KEY))
960 return 0;
961
Johan Hedbergfd349c02014-02-18 10:19:36 +0200962 skb_pull(skb, sizeof(*info));
963
964 memcpy(smp->irk, info->irk, 16);
965
966 return 0;
967}
968
969static int smp_cmd_ident_addr_info(struct l2cap_conn *conn,
970 struct sk_buff *skb)
971{
972 struct smp_cmd_ident_addr_info *info = (void *) skb->data;
973 struct smp_chan *smp = conn->smp_chan;
974 struct hci_conn *hcon = conn->hcon;
975 bdaddr_t rpa;
976
977 BT_DBG("");
978
979 if (skb->len < sizeof(*info))
980 return SMP_UNSPECIFIED;
981
Johan Hedberg6131ddc2014-02-18 10:19:37 +0200982 /* Ignore this PDU if it wasn't requested */
983 if (!(smp->remote_key_dist & SMP_DIST_ID_KEY))
984 return 0;
985
Johan Hedbergfd349c02014-02-18 10:19:36 +0200986 skb_pull(skb, sizeof(*info));
987
988 bacpy(&smp->id_addr, &info->bdaddr);
989 smp->id_addr_type = info->addr_type;
990
991 if (hci_bdaddr_is_rpa(&hcon->dst, hcon->dst_type))
992 bacpy(&rpa, &hcon->dst);
993 else
994 bacpy(&rpa, BDADDR_ANY);
995
Johan Hedberg23d0e122014-02-19 14:57:46 +0200996 smp->remote_irk = hci_add_irk(conn->hcon->hdev, &smp->id_addr,
997 smp->id_addr_type, smp->irk, &rpa);
Johan Hedbergfd349c02014-02-18 10:19:36 +0200998
Johan Hedberg68d6f6d2014-02-18 21:41:32 +0200999 /* Track the connection based on the Identity Address from now on */
1000 bacpy(&hcon->dst, &smp->id_addr);
1001 hcon->dst_type = smp->id_addr_type;
1002
Johan Hedberg387a33e2014-02-18 21:41:33 +02001003 l2cap_conn_update_id_addr(hcon);
1004
Johan Hedbergfd349c02014-02-18 10:19:36 +02001005 smp_distribute_keys(conn, 1);
1006
1007 return 0;
1008}
1009
Anderson Brigliaeb492e02011-06-09 18:50:40 -03001010int smp_sig_channel(struct l2cap_conn *conn, struct sk_buff *skb)
1011{
Marcel Holtmann7b9899d2013-10-03 00:00:57 -07001012 struct hci_conn *hcon = conn->hcon;
Marcel Holtmann92381f52013-10-03 01:23:08 -07001013 __u8 code, reason;
Anderson Brigliaeb492e02011-06-09 18:50:40 -03001014 int err = 0;
1015
Marcel Holtmann7b9899d2013-10-03 00:00:57 -07001016 if (hcon->type != LE_LINK) {
1017 kfree_skb(skb);
Johan Hedberg34327112013-10-16 11:37:01 +03001018 return 0;
Marcel Holtmann7b9899d2013-10-03 00:00:57 -07001019 }
1020
Marcel Holtmann92381f52013-10-03 01:23:08 -07001021 if (skb->len < 1) {
1022 kfree_skb(skb);
1023 return -EILSEQ;
1024 }
1025
Marcel Holtmann06ae3312013-10-18 03:43:00 -07001026 if (!test_bit(HCI_LE_ENABLED, &hcon->hdev->dev_flags)) {
Andre Guedes2e65c9d2011-06-30 19:20:56 -03001027 err = -ENOTSUPP;
1028 reason = SMP_PAIRING_NOTSUPP;
1029 goto done;
1030 }
1031
Marcel Holtmann92381f52013-10-03 01:23:08 -07001032 code = skb->data[0];
Anderson Brigliaeb492e02011-06-09 18:50:40 -03001033 skb_pull(skb, sizeof(code));
1034
Johan Hedberg8cf9fa12013-01-29 10:44:23 -06001035 /*
1036 * The SMP context must be initialized for all other PDUs except
1037 * pairing and security requests. If we get any other PDU when
1038 * not initialized simply disconnect (done if this function
1039 * returns an error).
1040 */
1041 if (code != SMP_CMD_PAIRING_REQ && code != SMP_CMD_SECURITY_REQ &&
1042 !conn->smp_chan) {
1043 BT_ERR("Unexpected SMP command 0x%02x. Disconnecting.", code);
1044 kfree_skb(skb);
1045 return -ENOTSUPP;
1046 }
1047
Anderson Brigliaeb492e02011-06-09 18:50:40 -03001048 switch (code) {
1049 case SMP_CMD_PAIRING_REQ:
Vinicius Costa Gomesda85e5e2011-06-09 18:50:53 -03001050 reason = smp_cmd_pairing_req(conn, skb);
Anderson Brigliaeb492e02011-06-09 18:50:40 -03001051 break;
1052
1053 case SMP_CMD_PAIRING_FAIL:
Johan Hedberg84794e12013-11-06 11:24:57 +02001054 smp_failure(conn, 0);
Vinicius Costa Gomesda85e5e2011-06-09 18:50:53 -03001055 reason = 0;
1056 err = -EPERM;
Anderson Brigliaeb492e02011-06-09 18:50:40 -03001057 break;
1058
1059 case SMP_CMD_PAIRING_RSP:
Vinicius Costa Gomesda85e5e2011-06-09 18:50:53 -03001060 reason = smp_cmd_pairing_rsp(conn, skb);
Anderson Briglia88ba43b2011-06-09 18:50:42 -03001061 break;
1062
1063 case SMP_CMD_SECURITY_REQ:
Vinicius Costa Gomesda85e5e2011-06-09 18:50:53 -03001064 reason = smp_cmd_security_req(conn, skb);
Anderson Briglia88ba43b2011-06-09 18:50:42 -03001065 break;
1066
Anderson Brigliaeb492e02011-06-09 18:50:40 -03001067 case SMP_CMD_PAIRING_CONFIRM:
Vinicius Costa Gomesda85e5e2011-06-09 18:50:53 -03001068 reason = smp_cmd_pairing_confirm(conn, skb);
Anderson Briglia88ba43b2011-06-09 18:50:42 -03001069 break;
1070
Anderson Brigliaeb492e02011-06-09 18:50:40 -03001071 case SMP_CMD_PAIRING_RANDOM:
Vinicius Costa Gomesda85e5e2011-06-09 18:50:53 -03001072 reason = smp_cmd_pairing_random(conn, skb);
Anderson Briglia88ba43b2011-06-09 18:50:42 -03001073 break;
1074
Anderson Brigliaeb492e02011-06-09 18:50:40 -03001075 case SMP_CMD_ENCRYPT_INFO:
Vinicius Costa Gomes7034b912011-07-07 18:59:34 -03001076 reason = smp_cmd_encrypt_info(conn, skb);
1077 break;
1078
Anderson Brigliaeb492e02011-06-09 18:50:40 -03001079 case SMP_CMD_MASTER_IDENT:
Vinicius Costa Gomes7034b912011-07-07 18:59:34 -03001080 reason = smp_cmd_master_ident(conn, skb);
1081 break;
1082
Anderson Brigliaeb492e02011-06-09 18:50:40 -03001083 case SMP_CMD_IDENT_INFO:
Johan Hedbergfd349c02014-02-18 10:19:36 +02001084 reason = smp_cmd_ident_info(conn, skb);
1085 break;
1086
Anderson Brigliaeb492e02011-06-09 18:50:40 -03001087 case SMP_CMD_IDENT_ADDR_INFO:
Johan Hedbergfd349c02014-02-18 10:19:36 +02001088 reason = smp_cmd_ident_addr_info(conn, skb);
1089 break;
1090
Anderson Brigliaeb492e02011-06-09 18:50:40 -03001091 case SMP_CMD_SIGN_INFO:
Vinicius Costa Gomes7034b912011-07-07 18:59:34 -03001092 /* Just ignored */
1093 reason = 0;
1094 break;
1095
Anderson Brigliaeb492e02011-06-09 18:50:40 -03001096 default:
1097 BT_DBG("Unknown command code 0x%2.2x", code);
1098
1099 reason = SMP_CMD_NOTSUPP;
Vinicius Costa Gomes3a0259b2011-06-09 18:50:43 -03001100 err = -EOPNOTSUPP;
1101 goto done;
1102 }
1103
1104done:
1105 if (reason)
Johan Hedberg84794e12013-11-06 11:24:57 +02001106 smp_failure(conn, reason);
Anderson Brigliaeb492e02011-06-09 18:50:40 -03001107
1108 kfree_skb(skb);
1109 return err;
1110}
Vinicius Costa Gomes7034b912011-07-07 18:59:34 -03001111
Johan Hedberg35d70272014-02-19 14:57:47 +02001112static void smp_notify_keys(struct l2cap_conn *conn)
1113{
1114 struct smp_chan *smp = conn->smp_chan;
1115 struct hci_conn *hcon = conn->hcon;
1116 struct hci_dev *hdev = hcon->hdev;
1117
Johan Hedberg95fbac82014-02-19 15:18:31 +02001118 if (smp->remote_irk)
1119 mgmt_new_irk(hdev, smp->remote_irk);
1120
Johan Hedberg35d70272014-02-19 14:57:47 +02001121 if (smp->ltk) {
1122 smp->ltk->bdaddr_type = hcon->dst_type;
1123 bacpy(&smp->ltk->bdaddr, &hcon->dst);
1124 mgmt_new_ltk(hdev, smp->ltk);
1125 }
1126
1127 if (smp->slave_ltk) {
1128 smp->slave_ltk->bdaddr_type = hcon->dst_type;
1129 bacpy(&smp->slave_ltk->bdaddr, &hcon->dst);
1130 mgmt_new_ltk(hdev, smp->slave_ltk);
1131 }
1132}
1133
Vinicius Costa Gomes7034b912011-07-07 18:59:34 -03001134int smp_distribute_keys(struct l2cap_conn *conn, __u8 force)
1135{
1136 struct smp_cmd_pairing *req, *rsp;
Vinicius Costa Gomes1c1def02011-09-05 14:31:30 -03001137 struct smp_chan *smp = conn->smp_chan;
Johan Hedberg524237c2014-02-22 19:06:31 +02001138 struct hci_conn *hcon = conn->hcon;
1139 struct hci_dev *hdev = hcon->hdev;
Vinicius Costa Gomes7034b912011-07-07 18:59:34 -03001140 __u8 *keydist;
1141
1142 BT_DBG("conn %p force %d", conn, force);
1143
Johan Hedberg524237c2014-02-22 19:06:31 +02001144 if (!test_bit(HCI_CONN_LE_SMP_PEND, &hcon->flags))
Vinicius Costa Gomesd26a2342011-08-19 21:06:51 -03001145 return 0;
1146
Vinicius Costa Gomes1c1def02011-09-05 14:31:30 -03001147 rsp = (void *) &smp->prsp[1];
Vinicius Costa Gomes7034b912011-07-07 18:59:34 -03001148
1149 /* The responder sends its keys first */
Johan Hedberg524237c2014-02-22 19:06:31 +02001150 if (!force && hcon->out && (rsp->resp_key_dist & 0x07))
Vinicius Costa Gomes7034b912011-07-07 18:59:34 -03001151 return 0;
1152
Vinicius Costa Gomes1c1def02011-09-05 14:31:30 -03001153 req = (void *) &smp->preq[1];
Vinicius Costa Gomes7034b912011-07-07 18:59:34 -03001154
Johan Hedberg524237c2014-02-22 19:06:31 +02001155 if (hcon->out) {
Vinicius Costa Gomes7034b912011-07-07 18:59:34 -03001156 keydist = &rsp->init_key_dist;
1157 *keydist &= req->init_key_dist;
1158 } else {
1159 keydist = &rsp->resp_key_dist;
1160 *keydist &= req->resp_key_dist;
1161 }
1162
Vinicius Costa Gomes7034b912011-07-07 18:59:34 -03001163 BT_DBG("keydist 0x%x", *keydist);
1164
1165 if (*keydist & SMP_DIST_ENC_KEY) {
1166 struct smp_cmd_encrypt_info enc;
1167 struct smp_cmd_master_ident ident;
Johan Hedberg23d0e122014-02-19 14:57:46 +02001168 struct smp_ltk *ltk;
Vinicius Costa Gomesc9839a12012-02-02 21:08:01 -03001169 u8 authenticated;
Vinicius Costa Gomes7034b912011-07-07 18:59:34 -03001170 __le16 ediv;
1171
1172 get_random_bytes(enc.ltk, sizeof(enc.ltk));
1173 get_random_bytes(&ediv, sizeof(ediv));
1174 get_random_bytes(ident.rand, sizeof(ident.rand));
1175
1176 smp_send_cmd(conn, SMP_CMD_ENCRYPT_INFO, sizeof(enc), &enc);
1177
Vinicius Costa Gomesc9839a12012-02-02 21:08:01 -03001178 authenticated = hcon->sec_level == BT_SECURITY_HIGH;
Johan Hedberg524237c2014-02-22 19:06:31 +02001179 ltk = hci_add_ltk(hdev, &hcon->dst, hcon->dst_type,
Johan Hedberg35d70272014-02-19 14:57:47 +02001180 HCI_SMP_LTK_SLAVE, authenticated, enc.ltk,
1181 smp->enc_key_size, ediv, ident.rand);
Johan Hedberg23d0e122014-02-19 14:57:46 +02001182 smp->slave_ltk = ltk;
Vinicius Costa Gomes16b90832011-07-07 18:59:39 -03001183
Andrei Emeltchenko58115372012-03-12 12:13:06 +02001184 ident.ediv = ediv;
Vinicius Costa Gomes7034b912011-07-07 18:59:34 -03001185
1186 smp_send_cmd(conn, SMP_CMD_MASTER_IDENT, sizeof(ident), &ident);
1187
1188 *keydist &= ~SMP_DIST_ENC_KEY;
1189 }
1190
1191 if (*keydist & SMP_DIST_ID_KEY) {
1192 struct smp_cmd_ident_addr_info addrinfo;
1193 struct smp_cmd_ident_info idinfo;
1194
Johan Hedberg863efaf2014-02-22 19:06:32 +02001195 memcpy(idinfo.irk, hdev->irk, sizeof(idinfo.irk));
Vinicius Costa Gomes7034b912011-07-07 18:59:34 -03001196
1197 smp_send_cmd(conn, SMP_CMD_IDENT_INFO, sizeof(idinfo), &idinfo);
1198
1199 /* Just public address */
1200 memset(&addrinfo, 0, sizeof(addrinfo));
Johan Hedberg524237c2014-02-22 19:06:31 +02001201 bacpy(&addrinfo.bdaddr, &hcon->src);
Vinicius Costa Gomes7034b912011-07-07 18:59:34 -03001202
1203 smp_send_cmd(conn, SMP_CMD_IDENT_ADDR_INFO, sizeof(addrinfo),
Marcel Holtmannf1560462013-10-13 05:43:25 -07001204 &addrinfo);
Vinicius Costa Gomes7034b912011-07-07 18:59:34 -03001205
1206 *keydist &= ~SMP_DIST_ID_KEY;
1207 }
1208
1209 if (*keydist & SMP_DIST_SIGN) {
1210 struct smp_cmd_sign_info sign;
1211
1212 /* Send a dummy key */
1213 get_random_bytes(sign.csrk, sizeof(sign.csrk));
1214
1215 smp_send_cmd(conn, SMP_CMD_SIGN_INFO, sizeof(sign), &sign);
1216
1217 *keydist &= ~SMP_DIST_SIGN;
1218 }
1219
Johan Hedberg524237c2014-02-22 19:06:31 +02001220 if (hcon->out || force || !(rsp->init_key_dist & 0x07)) {
1221 clear_bit(HCI_CONN_LE_SMP_PEND, &hcon->flags);
Gustavo F. Padovan6c9d42a2011-12-20 10:57:27 -02001222 cancel_delayed_work_sync(&conn->security_timer);
Johan Hedbergf4a407b2014-02-18 21:41:34 +02001223 set_bit(SMP_FLAG_COMPLETE, &smp->smp_flags);
Johan Hedberg35d70272014-02-19 14:57:47 +02001224 smp_notify_keys(conn);
Vinicius Costa Gomes8aab4752011-09-05 14:31:31 -03001225 smp_chan_destroy(conn);
Vinicius Costa Gomesd26a2342011-08-19 21:06:51 -03001226 }
1227
Vinicius Costa Gomes7034b912011-07-07 18:59:34 -03001228 return 0;
1229}