blob: 8517d1f0984df4261349a6840d85828630e3a36f [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,
Gustavo F. Padovan04124682012-03-08 01:25:00 -0300535 HCI_SMP_STK_SLAVE, 0, 0, stk, smp->enc_key_size,
536 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;
568
Vinicius Costa Gomesf1c09c02012-02-01 18:27:56 -0300569 BUG_ON(!smp);
Brian Gixc8eb9692011-11-23 08:28:35 -0800570
Brian Gixc8eb9692011-11-23 08:28:35 -0800571 kfree(smp);
572 conn->smp_chan = NULL;
Brian Gix2b64d152011-12-21 16:12:12 -0800573 conn->hcon->smp_conn = NULL;
David Herrmann76a68ba2013-04-06 20:28:37 +0200574 hci_conn_drop(conn->hcon);
Vinicius Costa Gomes8aab4752011-09-05 14:31:31 -0300575}
576
Brian Gix2b64d152011-12-21 16:12:12 -0800577int smp_user_confirm_reply(struct hci_conn *hcon, u16 mgmt_op, __le32 passkey)
578{
579 struct l2cap_conn *conn = hcon->smp_conn;
580 struct smp_chan *smp;
581 u32 value;
582 u8 key[16];
583
584 BT_DBG("");
585
586 if (!conn)
587 return -ENOTCONN;
588
589 smp = conn->smp_chan;
590
591 switch (mgmt_op) {
592 case MGMT_OP_USER_PASSKEY_REPLY:
593 value = le32_to_cpu(passkey);
594 memset(key, 0, sizeof(key));
595 BT_DBG("PassKey: %d", value);
596 put_unaligned_le32(value, key);
597 swap128(key, smp->tk);
598 /* Fall Through */
599 case MGMT_OP_USER_CONFIRM_REPLY:
600 set_bit(SMP_FLAG_TK_VALID, &smp->smp_flags);
601 break;
602 case MGMT_OP_USER_PASSKEY_NEG_REPLY:
603 case MGMT_OP_USER_CONFIRM_NEG_REPLY:
Johan Hedberg84794e12013-11-06 11:24:57 +0200604 smp_failure(conn, SMP_PASSKEY_ENTRY_FAILED);
Brian Gix2b64d152011-12-21 16:12:12 -0800605 return 0;
606 default:
Johan Hedberg84794e12013-11-06 11:24:57 +0200607 smp_failure(conn, SMP_PASSKEY_ENTRY_FAILED);
Brian Gix2b64d152011-12-21 16:12:12 -0800608 return -EOPNOTSUPP;
609 }
610
611 /* If it is our turn to send Pairing Confirm, do so now */
612 if (test_bit(SMP_FLAG_CFM_PENDING, &smp->smp_flags))
613 queue_work(hcon->hdev->workqueue, &smp->confirm);
614
615 return 0;
616}
617
Vinicius Costa Gomesda85e5e2011-06-09 18:50:53 -0300618static u8 smp_cmd_pairing_req(struct l2cap_conn *conn, struct sk_buff *skb)
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300619{
Vinicius Costa Gomes3158c502011-06-14 13:37:42 -0300620 struct smp_cmd_pairing rsp, *req = (void *) skb->data;
Vinicius Costa Gomes8aab4752011-09-05 14:31:31 -0300621 struct smp_chan *smp;
Vinicius Costa Gomes3158c502011-06-14 13:37:42 -0300622 u8 key_size;
Brian Gix2b64d152011-12-21 16:12:12 -0800623 u8 auth = SMP_AUTH_NONE;
Vinicius Costa Gomes8aab4752011-09-05 14:31:31 -0300624 int ret;
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300625
626 BT_DBG("conn %p", conn);
627
Johan Hedbergc46b98b2014-02-18 10:19:29 +0200628 if (skb->len < sizeof(*req))
629 return SMP_UNSPECIFIED;
630
Brian Gix2b64d152011-12-21 16:12:12 -0800631 if (conn->hcon->link_mode & HCI_LM_MASTER)
632 return SMP_CMD_NOTSUPP;
633
Johan Hedberg51a8efd2012-01-16 06:10:31 +0200634 if (!test_and_set_bit(HCI_CONN_LE_SMP_PEND, &conn->hcon->flags))
Vinicius Costa Gomes8aab4752011-09-05 14:31:31 -0300635 smp = smp_chan_create(conn);
Andrei Emeltchenkod08fd0e2012-07-19 17:03:43 +0300636 else
637 smp = conn->smp_chan;
Vinicius Costa Gomes8aab4752011-09-05 14:31:31 -0300638
Andrei Emeltchenkod08fd0e2012-07-19 17:03:43 +0300639 if (!smp)
640 return SMP_UNSPECIFIED;
Vinicius Costa Gomesd26a2342011-08-19 21:06:51 -0300641
Vinicius Costa Gomes1c1def02011-09-05 14:31:30 -0300642 smp->preq[0] = SMP_CMD_PAIRING_REQ;
643 memcpy(&smp->preq[1], req, sizeof(*req));
Vinicius Costa Gomes3158c502011-06-14 13:37:42 -0300644 skb_pull(skb, sizeof(*req));
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300645
Brian Gix2b64d152011-12-21 16:12:12 -0800646 /* We didn't start the pairing, so match remote */
647 if (req->auth_req & SMP_AUTH_BONDING)
648 auth = req->auth_req;
Vinicius Costa Gomesda85e5e2011-06-09 18:50:53 -0300649
Ido Yarivfdde0a22012-03-05 20:09:38 +0200650 conn->hcon->pending_sec_level = authreq_to_seclevel(auth);
651
Brian Gix2b64d152011-12-21 16:12:12 -0800652 build_pairing_cmd(conn, req, &rsp, auth);
Vinicius Costa Gomes3158c502011-06-14 13:37:42 -0300653
654 key_size = min(req->max_key_size, rsp.max_key_size);
655 if (check_enc_key_size(conn, key_size))
656 return SMP_ENC_KEY_SIZE;
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300657
Johan Hedberge84a6b12013-12-02 10:49:03 +0200658 get_random_bytes(smp->prnd, sizeof(smp->prnd));
Vinicius Costa Gomes8aab4752011-09-05 14:31:31 -0300659
Vinicius Costa Gomes1c1def02011-09-05 14:31:30 -0300660 smp->prsp[0] = SMP_CMD_PAIRING_RSP;
661 memcpy(&smp->prsp[1], &rsp, sizeof(rsp));
Anderson Brigliaf01ead32011-06-09 18:50:45 -0300662
Vinicius Costa Gomes3158c502011-06-14 13:37:42 -0300663 smp_send_cmd(conn, SMP_CMD_PAIRING_RSP, sizeof(rsp), &rsp);
Vinicius Costa Gomesda85e5e2011-06-09 18:50:53 -0300664
Brian Gix2b64d152011-12-21 16:12:12 -0800665 /* Request setup of TK */
666 ret = tk_request(conn, 0, auth, rsp.io_capability, req->io_capability);
667 if (ret)
668 return SMP_UNSPECIFIED;
669
Vinicius Costa Gomesda85e5e2011-06-09 18:50:53 -0300670 return 0;
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300671}
672
Vinicius Costa Gomesda85e5e2011-06-09 18:50:53 -0300673static u8 smp_cmd_pairing_rsp(struct l2cap_conn *conn, struct sk_buff *skb)
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300674{
Vinicius Costa Gomes3158c502011-06-14 13:37:42 -0300675 struct smp_cmd_pairing *req, *rsp = (void *) skb->data;
Vinicius Costa Gomes1c1def02011-09-05 14:31:30 -0300676 struct smp_chan *smp = conn->smp_chan;
Vinicius Costa Gomes8aab4752011-09-05 14:31:31 -0300677 struct hci_dev *hdev = conn->hcon->hdev;
Brian Gix2b64d152011-12-21 16:12:12 -0800678 u8 key_size, auth = SMP_AUTH_NONE;
Anderson Briglia7d24ddc2011-06-09 18:50:46 -0300679 int ret;
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300680
681 BT_DBG("conn %p", conn);
682
Johan Hedbergc46b98b2014-02-18 10:19:29 +0200683 if (skb->len < sizeof(*rsp))
684 return SMP_UNSPECIFIED;
685
Brian Gix2b64d152011-12-21 16:12:12 -0800686 if (!(conn->hcon->link_mode & HCI_LM_MASTER))
687 return SMP_CMD_NOTSUPP;
688
Vinicius Costa Gomes3158c502011-06-14 13:37:42 -0300689 skb_pull(skb, sizeof(*rsp));
Vinicius Costa Gomesda85e5e2011-06-09 18:50:53 -0300690
Vinicius Costa Gomes1c1def02011-09-05 14:31:30 -0300691 req = (void *) &smp->preq[1];
Vinicius Costa Gomes3158c502011-06-14 13:37:42 -0300692
693 key_size = min(req->max_key_size, rsp->max_key_size);
694 if (check_enc_key_size(conn, key_size))
695 return SMP_ENC_KEY_SIZE;
696
Johan Hedberge84a6b12013-12-02 10:49:03 +0200697 get_random_bytes(smp->prnd, sizeof(smp->prnd));
Anderson Briglia7d24ddc2011-06-09 18:50:46 -0300698
Vinicius Costa Gomes8aab4752011-09-05 14:31:31 -0300699 smp->prsp[0] = SMP_CMD_PAIRING_RSP;
700 memcpy(&smp->prsp[1], rsp, sizeof(*rsp));
Anderson Briglia7d24ddc2011-06-09 18:50:46 -0300701
Brian Gix2b64d152011-12-21 16:12:12 -0800702 if ((req->auth_req & SMP_AUTH_BONDING) &&
Marcel Holtmannf1560462013-10-13 05:43:25 -0700703 (rsp->auth_req & SMP_AUTH_BONDING))
Brian Gix2b64d152011-12-21 16:12:12 -0800704 auth = SMP_AUTH_BONDING;
705
706 auth |= (req->auth_req | rsp->auth_req) & SMP_AUTH_MITM;
707
Johan Hedberg476585e2012-06-06 18:54:15 +0800708 ret = tk_request(conn, 0, auth, req->io_capability, rsp->io_capability);
Brian Gix2b64d152011-12-21 16:12:12 -0800709 if (ret)
710 return SMP_UNSPECIFIED;
711
712 set_bit(SMP_FLAG_CFM_PENDING, &smp->smp_flags);
713
714 /* Can't compose response until we have been confirmed */
715 if (!test_bit(SMP_FLAG_TK_VALID, &smp->smp_flags))
716 return 0;
717
Vinicius Costa Gomes8aab4752011-09-05 14:31:31 -0300718 queue_work(hdev->workqueue, &smp->confirm);
Vinicius Costa Gomesda85e5e2011-06-09 18:50:53 -0300719
720 return 0;
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300721}
722
Vinicius Costa Gomesda85e5e2011-06-09 18:50:53 -0300723static u8 smp_cmd_pairing_confirm(struct l2cap_conn *conn, struct sk_buff *skb)
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300724{
Vinicius Costa Gomes1c1def02011-09-05 14:31:30 -0300725 struct smp_chan *smp = conn->smp_chan;
Vinicius Costa Gomes8aab4752011-09-05 14:31:31 -0300726 struct hci_dev *hdev = conn->hcon->hdev;
Anderson Briglia7d24ddc2011-06-09 18:50:46 -0300727
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300728 BT_DBG("conn %p %s", conn, conn->hcon->out ? "master" : "slave");
729
Johan Hedbergc46b98b2014-02-18 10:19:29 +0200730 if (skb->len < sizeof(smp->pcnf))
731 return SMP_UNSPECIFIED;
732
Vinicius Costa Gomes1c1def02011-09-05 14:31:30 -0300733 memcpy(smp->pcnf, skb->data, sizeof(smp->pcnf));
734 skb_pull(skb, sizeof(smp->pcnf));
Anderson Briglia7d24ddc2011-06-09 18:50:46 -0300735
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300736 if (conn->hcon->out) {
Anderson Briglia7d24ddc2011-06-09 18:50:46 -0300737 u8 random[16];
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300738
Vinicius Costa Gomes1c1def02011-09-05 14:31:30 -0300739 swap128(smp->prnd, random);
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300740 smp_send_cmd(conn, SMP_CMD_PAIRING_RANDOM, sizeof(random),
Marcel Holtmannf1560462013-10-13 05:43:25 -0700741 random);
Brian Gix2b64d152011-12-21 16:12:12 -0800742 } else if (test_bit(SMP_FLAG_TK_VALID, &smp->smp_flags)) {
Vinicius Costa Gomes8aab4752011-09-05 14:31:31 -0300743 queue_work(hdev->workqueue, &smp->confirm);
Brian Gix2b64d152011-12-21 16:12:12 -0800744 } else {
745 set_bit(SMP_FLAG_CFM_PENDING, &smp->smp_flags);
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300746 }
Vinicius Costa Gomesda85e5e2011-06-09 18:50:53 -0300747
748 return 0;
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300749}
750
Vinicius Costa Gomesda85e5e2011-06-09 18:50:53 -0300751static u8 smp_cmd_pairing_random(struct l2cap_conn *conn, struct sk_buff *skb)
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300752{
Vinicius Costa Gomes1c1def02011-09-05 14:31:30 -0300753 struct smp_chan *smp = conn->smp_chan;
Vinicius Costa Gomes8aab4752011-09-05 14:31:31 -0300754 struct hci_dev *hdev = conn->hcon->hdev;
Anderson Briglia7d24ddc2011-06-09 18:50:46 -0300755
Vinicius Costa Gomes8aab4752011-09-05 14:31:31 -0300756 BT_DBG("conn %p", conn);
Anderson Briglia7d24ddc2011-06-09 18:50:46 -0300757
Johan Hedbergc46b98b2014-02-18 10:19:29 +0200758 if (skb->len < sizeof(smp->rrnd))
759 return SMP_UNSPECIFIED;
760
Vinicius Costa Gomes8aab4752011-09-05 14:31:31 -0300761 swap128(skb->data, smp->rrnd);
762 skb_pull(skb, sizeof(smp->rrnd));
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300763
Vinicius Costa Gomes8aab4752011-09-05 14:31:31 -0300764 queue_work(hdev->workqueue, &smp->random);
Vinicius Costa Gomesda85e5e2011-06-09 18:50:53 -0300765
766 return 0;
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300767}
768
Johan Hedberg4dab7862012-06-07 14:58:37 +0800769static u8 smp_ltk_encrypt(struct l2cap_conn *conn, u8 sec_level)
Vinicius Costa Gomes988c5992011-08-25 20:02:28 -0300770{
Vinicius Costa Gomesc9839a12012-02-02 21:08:01 -0300771 struct smp_ltk *key;
Vinicius Costa Gomes988c5992011-08-25 20:02:28 -0300772 struct hci_conn *hcon = conn->hcon;
773
Johan Hedberg98a0b842014-01-30 19:40:00 -0800774 key = hci_find_ltk_by_addr(hcon->hdev, &hcon->dst, hcon->dst_type,
775 hcon->out);
Vinicius Costa Gomes988c5992011-08-25 20:02:28 -0300776 if (!key)
777 return 0;
778
Johan Hedberg4dab7862012-06-07 14:58:37 +0800779 if (sec_level > BT_SECURITY_MEDIUM && !key->authenticated)
780 return 0;
781
Johan Hedberg51a8efd2012-01-16 06:10:31 +0200782 if (test_and_set_bit(HCI_CONN_ENCRYPT_PEND, &hcon->flags))
Vinicius Costa Gomes988c5992011-08-25 20:02:28 -0300783 return 1;
784
Vinicius Costa Gomesc9839a12012-02-02 21:08:01 -0300785 hci_le_start_enc(hcon, key->ediv, key->rand, key->val);
786 hcon->enc_key_size = key->enc_size;
Vinicius Costa Gomes988c5992011-08-25 20:02:28 -0300787
788 return 1;
Vinicius Costa Gomes988c5992011-08-25 20:02:28 -0300789}
Marcel Holtmannf1560462013-10-13 05:43:25 -0700790
Vinicius Costa Gomesda85e5e2011-06-09 18:50:53 -0300791static u8 smp_cmd_security_req(struct l2cap_conn *conn, struct sk_buff *skb)
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300792{
793 struct smp_cmd_security_req *rp = (void *) skb->data;
794 struct smp_cmd_pairing cp;
Vinicius Costa Gomesf1cb9af2011-01-26 21:42:57 -0300795 struct hci_conn *hcon = conn->hcon;
Vinicius Costa Gomes8aab4752011-09-05 14:31:31 -0300796 struct smp_chan *smp;
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300797
798 BT_DBG("conn %p", conn);
799
Johan Hedbergc46b98b2014-02-18 10:19:29 +0200800 if (skb->len < sizeof(*rp))
801 return SMP_UNSPECIFIED;
802
Johan Hedberg86ca9ea2013-11-05 11:30:39 +0200803 if (!(conn->hcon->link_mode & HCI_LM_MASTER))
804 return SMP_CMD_NOTSUPP;
805
Brian Gix2b64d152011-12-21 16:12:12 -0800806 hcon->pending_sec_level = authreq_to_seclevel(rp->auth_req);
Vinicius Costa Gomesfeb45eb2011-08-25 20:02:35 -0300807
Johan Hedberg4dab7862012-06-07 14:58:37 +0800808 if (smp_ltk_encrypt(conn, hcon->pending_sec_level))
Vinicius Costa Gomes988c5992011-08-25 20:02:28 -0300809 return 0;
810
Johan Hedberg51a8efd2012-01-16 06:10:31 +0200811 if (test_and_set_bit(HCI_CONN_LE_SMP_PEND, &hcon->flags))
Vinicius Costa Gomesda85e5e2011-06-09 18:50:53 -0300812 return 0;
Vinicius Costa Gomesf1cb9af2011-01-26 21:42:57 -0300813
Vinicius Costa Gomes8aab4752011-09-05 14:31:31 -0300814 smp = smp_chan_create(conn);
Vinicius Costa Gomesd26a2342011-08-19 21:06:51 -0300815
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300816 skb_pull(skb, sizeof(*rp));
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300817
Vinicius Costa Gomesda85e5e2011-06-09 18:50:53 -0300818 memset(&cp, 0, sizeof(cp));
Vinicius Costa Gomes54790f72011-07-07 18:59:38 -0300819 build_pairing_cmd(conn, &cp, NULL, rp->auth_req);
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300820
Vinicius Costa Gomes1c1def02011-09-05 14:31:30 -0300821 smp->preq[0] = SMP_CMD_PAIRING_REQ;
822 memcpy(&smp->preq[1], &cp, sizeof(cp));
Anderson Brigliaf01ead32011-06-09 18:50:45 -0300823
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300824 smp_send_cmd(conn, SMP_CMD_PAIRING_REQ, sizeof(cp), &cp);
Vinicius Costa Gomesf1cb9af2011-01-26 21:42:57 -0300825
Vinicius Costa Gomesda85e5e2011-06-09 18:50:53 -0300826 return 0;
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300827}
828
Johan Hedbergad32a2f2013-05-14 18:05:12 +0300829bool smp_sufficient_security(struct hci_conn *hcon, u8 sec_level)
830{
831 if (sec_level == BT_SECURITY_LOW)
832 return true;
833
834 if (hcon->sec_level >= sec_level)
835 return true;
836
837 return false;
838}
839
Vinicius Costa Gomescc110922012-08-23 21:32:43 -0300840int smp_conn_security(struct hci_conn *hcon, __u8 sec_level)
Anderson Brigliaeb492e02011-06-09 18:50:40 -0300841{
Vinicius Costa Gomescc110922012-08-23 21:32:43 -0300842 struct l2cap_conn *conn = hcon->l2cap_data;
Vinicius Costa Gomes1c1def02011-09-05 14:31:30 -0300843 struct smp_chan *smp = conn->smp_chan;
Brian Gix2b64d152011-12-21 16:12:12 -0800844 __u8 authreq;
Anderson Brigliaeb492e02011-06-09 18:50:40 -0300845
Vinicius Costa Gomes3a0259b2011-06-09 18:50:43 -0300846 BT_DBG("conn %p hcon %p level 0x%2.2x", conn, hcon, sec_level);
847
Johan Hedberg757aee02013-04-24 13:05:32 +0300848 if (!test_bit(HCI_LE_ENABLED, &hcon->hdev->dev_flags))
Andre Guedes2e65c9d2011-06-30 19:20:56 -0300849 return 1;
850
Johan Hedbergad32a2f2013-05-14 18:05:12 +0300851 if (smp_sufficient_security(hcon, sec_level))
Vinicius Costa Gomesf1cb9af2011-01-26 21:42:57 -0300852 return 1;
853
Vinicius Costa Gomes988c5992011-08-25 20:02:28 -0300854 if (hcon->link_mode & HCI_LM_MASTER)
Johan Hedberg4dab7862012-06-07 14:58:37 +0800855 if (smp_ltk_encrypt(conn, sec_level))
Vinicius Costa Gomes02bc7452011-07-07 18:59:41 -0300856 goto done;
Vinicius Costa Gomesd26a2342011-08-19 21:06:51 -0300857
Johan Hedberg51a8efd2012-01-16 06:10:31 +0200858 if (test_and_set_bit(HCI_CONN_LE_SMP_PEND, &hcon->flags))
Vinicius Costa Gomesd26a2342011-08-19 21:06:51 -0300859 return 0;
860
Vinicius Costa Gomes8aab4752011-09-05 14:31:31 -0300861 smp = smp_chan_create(conn);
Brian Gix2b64d152011-12-21 16:12:12 -0800862 if (!smp)
863 return 1;
864
865 authreq = seclevel_to_authreq(sec_level);
Vinicius Costa Gomesd26a2342011-08-19 21:06:51 -0300866
Vinicius Costa Gomesd26a2342011-08-19 21:06:51 -0300867 if (hcon->link_mode & HCI_LM_MASTER) {
868 struct smp_cmd_pairing cp;
Anderson Brigliaf01ead32011-06-09 18:50:45 -0300869
Brian Gix2b64d152011-12-21 16:12:12 -0800870 build_pairing_cmd(conn, &cp, NULL, authreq);
Vinicius Costa Gomes1c1def02011-09-05 14:31:30 -0300871 smp->preq[0] = SMP_CMD_PAIRING_REQ;
872 memcpy(&smp->preq[1], &cp, sizeof(cp));
Anderson Brigliaf01ead32011-06-09 18:50:45 -0300873
Anderson Brigliaeb492e02011-06-09 18:50:40 -0300874 smp_send_cmd(conn, SMP_CMD_PAIRING_REQ, sizeof(cp), &cp);
875 } else {
876 struct smp_cmd_security_req cp;
Brian Gix2b64d152011-12-21 16:12:12 -0800877 cp.auth_req = authreq;
Anderson Brigliaeb492e02011-06-09 18:50:40 -0300878 smp_send_cmd(conn, SMP_CMD_SECURITY_REQ, sizeof(cp), &cp);
879 }
880
Vinicius Costa Gomes02bc7452011-07-07 18:59:41 -0300881done:
Vinicius Costa Gomesf1cb9af2011-01-26 21:42:57 -0300882 hcon->pending_sec_level = sec_level;
Vinicius Costa Gomesf1cb9af2011-01-26 21:42:57 -0300883
Anderson Brigliaeb492e02011-06-09 18:50:40 -0300884 return 0;
885}
886
Vinicius Costa Gomes7034b912011-07-07 18:59:34 -0300887static int smp_cmd_encrypt_info(struct l2cap_conn *conn, struct sk_buff *skb)
888{
Vinicius Costa Gomes16b90832011-07-07 18:59:39 -0300889 struct smp_cmd_encrypt_info *rp = (void *) skb->data;
Vinicius Costa Gomes1c1def02011-09-05 14:31:30 -0300890 struct smp_chan *smp = conn->smp_chan;
Vinicius Costa Gomes16b90832011-07-07 18:59:39 -0300891
Johan Hedbergc46b98b2014-02-18 10:19:29 +0200892 BT_DBG("conn %p", conn);
893
894 if (skb->len < sizeof(*rp))
895 return SMP_UNSPECIFIED;
896
Johan Hedberg6131ddc2014-02-18 10:19:37 +0200897 /* Ignore this PDU if it wasn't requested */
898 if (!(smp->remote_key_dist & SMP_DIST_ENC_KEY))
899 return 0;
900
Vinicius Costa Gomes16b90832011-07-07 18:59:39 -0300901 skb_pull(skb, sizeof(*rp));
902
Vinicius Costa Gomes1c1def02011-09-05 14:31:30 -0300903 memcpy(smp->tk, rp->ltk, sizeof(smp->tk));
Vinicius Costa Gomes16b90832011-07-07 18:59:39 -0300904
Vinicius Costa Gomes7034b912011-07-07 18:59:34 -0300905 return 0;
906}
907
908static int smp_cmd_master_ident(struct l2cap_conn *conn, struct sk_buff *skb)
909{
Vinicius Costa Gomes16b90832011-07-07 18:59:39 -0300910 struct smp_cmd_master_ident *rp = (void *) skb->data;
Vinicius Costa Gomes1c1def02011-09-05 14:31:30 -0300911 struct smp_chan *smp = conn->smp_chan;
Vinicius Costa Gomesc9839a12012-02-02 21:08:01 -0300912 struct hci_dev *hdev = conn->hcon->hdev;
913 struct hci_conn *hcon = conn->hcon;
914 u8 authenticated;
Vinicius Costa Gomes7034b912011-07-07 18:59:34 -0300915
Johan Hedbergc46b98b2014-02-18 10:19:29 +0200916 BT_DBG("conn %p", conn);
917
918 if (skb->len < sizeof(*rp))
919 return SMP_UNSPECIFIED;
920
Johan Hedberg6131ddc2014-02-18 10:19:37 +0200921 /* Ignore this PDU if it wasn't requested */
922 if (!(smp->remote_key_dist & SMP_DIST_ENC_KEY))
923 return 0;
924
Vinicius Costa Gomes16b90832011-07-07 18:59:39 -0300925 skb_pull(skb, sizeof(*rp));
926
Vinicius Costa Gomesc9839a12012-02-02 21:08:01 -0300927 hci_dev_lock(hdev);
Marcel Holtmannce39fb42013-10-13 02:23:39 -0700928 authenticated = (hcon->sec_level == BT_SECURITY_HIGH);
929 hci_add_ltk(hdev, &hcon->dst, hcon->dst_type, HCI_SMP_LTK, 1,
930 authenticated, smp->tk, smp->enc_key_size,
Gustavo F. Padovan04124682012-03-08 01:25:00 -0300931 rp->ediv, rp->rand);
Johan Hedbergfd349c02014-02-18 10:19:36 +0200932 if (!(smp->remote_key_dist & SMP_DIST_ID_KEY))
933 smp_distribute_keys(conn, 1);
Vinicius Costa Gomesc9839a12012-02-02 21:08:01 -0300934 hci_dev_unlock(hdev);
Vinicius Costa Gomes7034b912011-07-07 18:59:34 -0300935
936 return 0;
937}
938
Johan Hedbergfd349c02014-02-18 10:19:36 +0200939static int smp_cmd_ident_info(struct l2cap_conn *conn, struct sk_buff *skb)
940{
941 struct smp_cmd_ident_info *info = (void *) skb->data;
942 struct smp_chan *smp = conn->smp_chan;
943
944 BT_DBG("");
945
946 if (skb->len < sizeof(*info))
947 return SMP_UNSPECIFIED;
948
Johan Hedberg6131ddc2014-02-18 10:19:37 +0200949 /* Ignore this PDU if it wasn't requested */
950 if (!(smp->remote_key_dist & SMP_DIST_ID_KEY))
951 return 0;
952
Johan Hedbergfd349c02014-02-18 10:19:36 +0200953 skb_pull(skb, sizeof(*info));
954
955 memcpy(smp->irk, info->irk, 16);
956
957 return 0;
958}
959
960static int smp_cmd_ident_addr_info(struct l2cap_conn *conn,
961 struct sk_buff *skb)
962{
963 struct smp_cmd_ident_addr_info *info = (void *) skb->data;
964 struct smp_chan *smp = conn->smp_chan;
965 struct hci_conn *hcon = conn->hcon;
966 bdaddr_t rpa;
967
968 BT_DBG("");
969
970 if (skb->len < sizeof(*info))
971 return SMP_UNSPECIFIED;
972
Johan Hedberg6131ddc2014-02-18 10:19:37 +0200973 /* Ignore this PDU if it wasn't requested */
974 if (!(smp->remote_key_dist & SMP_DIST_ID_KEY))
975 return 0;
976
Johan Hedbergfd349c02014-02-18 10:19:36 +0200977 skb_pull(skb, sizeof(*info));
978
979 bacpy(&smp->id_addr, &info->bdaddr);
980 smp->id_addr_type = info->addr_type;
981
982 if (hci_bdaddr_is_rpa(&hcon->dst, hcon->dst_type))
983 bacpy(&rpa, &hcon->dst);
984 else
985 bacpy(&rpa, BDADDR_ANY);
986
987 hci_add_irk(conn->hcon->hdev, &smp->id_addr, smp->id_addr_type,
988 smp->irk, &rpa);
989
990 smp_distribute_keys(conn, 1);
991
992 return 0;
993}
994
Anderson Brigliaeb492e02011-06-09 18:50:40 -0300995int smp_sig_channel(struct l2cap_conn *conn, struct sk_buff *skb)
996{
Marcel Holtmann7b9899d2013-10-03 00:00:57 -0700997 struct hci_conn *hcon = conn->hcon;
Marcel Holtmann92381f52013-10-03 01:23:08 -0700998 __u8 code, reason;
Anderson Brigliaeb492e02011-06-09 18:50:40 -0300999 int err = 0;
1000
Marcel Holtmann7b9899d2013-10-03 00:00:57 -07001001 if (hcon->type != LE_LINK) {
1002 kfree_skb(skb);
Johan Hedberg34327112013-10-16 11:37:01 +03001003 return 0;
Marcel Holtmann7b9899d2013-10-03 00:00:57 -07001004 }
1005
Marcel Holtmann92381f52013-10-03 01:23:08 -07001006 if (skb->len < 1) {
1007 kfree_skb(skb);
1008 return -EILSEQ;
1009 }
1010
Marcel Holtmann06ae3312013-10-18 03:43:00 -07001011 if (!test_bit(HCI_LE_ENABLED, &hcon->hdev->dev_flags)) {
Andre Guedes2e65c9d2011-06-30 19:20:56 -03001012 err = -ENOTSUPP;
1013 reason = SMP_PAIRING_NOTSUPP;
1014 goto done;
1015 }
1016
Marcel Holtmann92381f52013-10-03 01:23:08 -07001017 code = skb->data[0];
Anderson Brigliaeb492e02011-06-09 18:50:40 -03001018 skb_pull(skb, sizeof(code));
1019
Johan Hedberg8cf9fa12013-01-29 10:44:23 -06001020 /*
1021 * The SMP context must be initialized for all other PDUs except
1022 * pairing and security requests. If we get any other PDU when
1023 * not initialized simply disconnect (done if this function
1024 * returns an error).
1025 */
1026 if (code != SMP_CMD_PAIRING_REQ && code != SMP_CMD_SECURITY_REQ &&
1027 !conn->smp_chan) {
1028 BT_ERR("Unexpected SMP command 0x%02x. Disconnecting.", code);
1029 kfree_skb(skb);
1030 return -ENOTSUPP;
1031 }
1032
Anderson Brigliaeb492e02011-06-09 18:50:40 -03001033 switch (code) {
1034 case SMP_CMD_PAIRING_REQ:
Vinicius Costa Gomesda85e5e2011-06-09 18:50:53 -03001035 reason = smp_cmd_pairing_req(conn, skb);
Anderson Brigliaeb492e02011-06-09 18:50:40 -03001036 break;
1037
1038 case SMP_CMD_PAIRING_FAIL:
Johan Hedberg84794e12013-11-06 11:24:57 +02001039 smp_failure(conn, 0);
Vinicius Costa Gomesda85e5e2011-06-09 18:50:53 -03001040 reason = 0;
1041 err = -EPERM;
Anderson Brigliaeb492e02011-06-09 18:50:40 -03001042 break;
1043
1044 case SMP_CMD_PAIRING_RSP:
Vinicius Costa Gomesda85e5e2011-06-09 18:50:53 -03001045 reason = smp_cmd_pairing_rsp(conn, skb);
Anderson Briglia88ba43b2011-06-09 18:50:42 -03001046 break;
1047
1048 case SMP_CMD_SECURITY_REQ:
Vinicius Costa Gomesda85e5e2011-06-09 18:50:53 -03001049 reason = smp_cmd_security_req(conn, skb);
Anderson Briglia88ba43b2011-06-09 18:50:42 -03001050 break;
1051
Anderson Brigliaeb492e02011-06-09 18:50:40 -03001052 case SMP_CMD_PAIRING_CONFIRM:
Vinicius Costa Gomesda85e5e2011-06-09 18:50:53 -03001053 reason = smp_cmd_pairing_confirm(conn, skb);
Anderson Briglia88ba43b2011-06-09 18:50:42 -03001054 break;
1055
Anderson Brigliaeb492e02011-06-09 18:50:40 -03001056 case SMP_CMD_PAIRING_RANDOM:
Vinicius Costa Gomesda85e5e2011-06-09 18:50:53 -03001057 reason = smp_cmd_pairing_random(conn, skb);
Anderson Briglia88ba43b2011-06-09 18:50:42 -03001058 break;
1059
Anderson Brigliaeb492e02011-06-09 18:50:40 -03001060 case SMP_CMD_ENCRYPT_INFO:
Vinicius Costa Gomes7034b912011-07-07 18:59:34 -03001061 reason = smp_cmd_encrypt_info(conn, skb);
1062 break;
1063
Anderson Brigliaeb492e02011-06-09 18:50:40 -03001064 case SMP_CMD_MASTER_IDENT:
Vinicius Costa Gomes7034b912011-07-07 18:59:34 -03001065 reason = smp_cmd_master_ident(conn, skb);
1066 break;
1067
Anderson Brigliaeb492e02011-06-09 18:50:40 -03001068 case SMP_CMD_IDENT_INFO:
Johan Hedbergfd349c02014-02-18 10:19:36 +02001069 reason = smp_cmd_ident_info(conn, skb);
1070 break;
1071
Anderson Brigliaeb492e02011-06-09 18:50:40 -03001072 case SMP_CMD_IDENT_ADDR_INFO:
Johan Hedbergfd349c02014-02-18 10:19:36 +02001073 reason = smp_cmd_ident_addr_info(conn, skb);
1074 break;
1075
Anderson Brigliaeb492e02011-06-09 18:50:40 -03001076 case SMP_CMD_SIGN_INFO:
Vinicius Costa Gomes7034b912011-07-07 18:59:34 -03001077 /* Just ignored */
1078 reason = 0;
1079 break;
1080
Anderson Brigliaeb492e02011-06-09 18:50:40 -03001081 default:
1082 BT_DBG("Unknown command code 0x%2.2x", code);
1083
1084 reason = SMP_CMD_NOTSUPP;
Vinicius Costa Gomes3a0259b2011-06-09 18:50:43 -03001085 err = -EOPNOTSUPP;
1086 goto done;
1087 }
1088
1089done:
1090 if (reason)
Johan Hedberg84794e12013-11-06 11:24:57 +02001091 smp_failure(conn, reason);
Anderson Brigliaeb492e02011-06-09 18:50:40 -03001092
1093 kfree_skb(skb);
1094 return err;
1095}
Vinicius Costa Gomes7034b912011-07-07 18:59:34 -03001096
1097int smp_distribute_keys(struct l2cap_conn *conn, __u8 force)
1098{
1099 struct smp_cmd_pairing *req, *rsp;
Vinicius Costa Gomes1c1def02011-09-05 14:31:30 -03001100 struct smp_chan *smp = conn->smp_chan;
Vinicius Costa Gomes7034b912011-07-07 18:59:34 -03001101 __u8 *keydist;
1102
1103 BT_DBG("conn %p force %d", conn, force);
1104
Johan Hedberg51a8efd2012-01-16 06:10:31 +02001105 if (!test_bit(HCI_CONN_LE_SMP_PEND, &conn->hcon->flags))
Vinicius Costa Gomesd26a2342011-08-19 21:06:51 -03001106 return 0;
1107
Vinicius Costa Gomes1c1def02011-09-05 14:31:30 -03001108 rsp = (void *) &smp->prsp[1];
Vinicius Costa Gomes7034b912011-07-07 18:59:34 -03001109
1110 /* The responder sends its keys first */
1111 if (!force && conn->hcon->out && (rsp->resp_key_dist & 0x07))
1112 return 0;
1113
Vinicius Costa Gomes1c1def02011-09-05 14:31:30 -03001114 req = (void *) &smp->preq[1];
Vinicius Costa Gomes7034b912011-07-07 18:59:34 -03001115
1116 if (conn->hcon->out) {
1117 keydist = &rsp->init_key_dist;
1118 *keydist &= req->init_key_dist;
1119 } else {
1120 keydist = &rsp->resp_key_dist;
1121 *keydist &= req->resp_key_dist;
1122 }
1123
Vinicius Costa Gomes7034b912011-07-07 18:59:34 -03001124 BT_DBG("keydist 0x%x", *keydist);
1125
1126 if (*keydist & SMP_DIST_ENC_KEY) {
1127 struct smp_cmd_encrypt_info enc;
1128 struct smp_cmd_master_ident ident;
Vinicius Costa Gomesc9839a12012-02-02 21:08:01 -03001129 struct hci_conn *hcon = conn->hcon;
1130 u8 authenticated;
Vinicius Costa Gomes7034b912011-07-07 18:59:34 -03001131 __le16 ediv;
1132
1133 get_random_bytes(enc.ltk, sizeof(enc.ltk));
1134 get_random_bytes(&ediv, sizeof(ediv));
1135 get_random_bytes(ident.rand, sizeof(ident.rand));
1136
1137 smp_send_cmd(conn, SMP_CMD_ENCRYPT_INFO, sizeof(enc), &enc);
1138
Vinicius Costa Gomesc9839a12012-02-02 21:08:01 -03001139 authenticated = hcon->sec_level == BT_SECURITY_HIGH;
Marcel Holtmannce39fb42013-10-13 02:23:39 -07001140 hci_add_ltk(hcon->hdev, &hcon->dst, hcon->dst_type,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001141 HCI_SMP_LTK_SLAVE, 1, authenticated,
1142 enc.ltk, smp->enc_key_size, ediv, ident.rand);
Vinicius Costa Gomes16b90832011-07-07 18:59:39 -03001143
Andrei Emeltchenko58115372012-03-12 12:13:06 +02001144 ident.ediv = ediv;
Vinicius Costa Gomes7034b912011-07-07 18:59:34 -03001145
1146 smp_send_cmd(conn, SMP_CMD_MASTER_IDENT, sizeof(ident), &ident);
1147
1148 *keydist &= ~SMP_DIST_ENC_KEY;
1149 }
1150
1151 if (*keydist & SMP_DIST_ID_KEY) {
1152 struct smp_cmd_ident_addr_info addrinfo;
1153 struct smp_cmd_ident_info idinfo;
1154
1155 /* Send a dummy key */
1156 get_random_bytes(idinfo.irk, sizeof(idinfo.irk));
1157
1158 smp_send_cmd(conn, SMP_CMD_IDENT_INFO, sizeof(idinfo), &idinfo);
1159
1160 /* Just public address */
1161 memset(&addrinfo, 0, sizeof(addrinfo));
Marcel Holtmann2b36a562013-10-13 05:24:00 -07001162 bacpy(&addrinfo.bdaddr, &conn->hcon->src);
Vinicius Costa Gomes7034b912011-07-07 18:59:34 -03001163
1164 smp_send_cmd(conn, SMP_CMD_IDENT_ADDR_INFO, sizeof(addrinfo),
Marcel Holtmannf1560462013-10-13 05:43:25 -07001165 &addrinfo);
Vinicius Costa Gomes7034b912011-07-07 18:59:34 -03001166
1167 *keydist &= ~SMP_DIST_ID_KEY;
1168 }
1169
1170 if (*keydist & SMP_DIST_SIGN) {
1171 struct smp_cmd_sign_info sign;
1172
1173 /* Send a dummy key */
1174 get_random_bytes(sign.csrk, sizeof(sign.csrk));
1175
1176 smp_send_cmd(conn, SMP_CMD_SIGN_INFO, sizeof(sign), &sign);
1177
1178 *keydist &= ~SMP_DIST_SIGN;
1179 }
1180
Johan Hedbergb7d448d2014-02-18 17:14:34 +02001181 if (conn->hcon->out || force || !(rsp->init_key_dist & 0x07)) {
Johan Hedberg51a8efd2012-01-16 06:10:31 +02001182 clear_bit(HCI_CONN_LE_SMP_PEND, &conn->hcon->flags);
Gustavo F. Padovan6c9d42a2011-12-20 10:57:27 -02001183 cancel_delayed_work_sync(&conn->security_timer);
Vinicius Costa Gomes8aab4752011-09-05 14:31:31 -03001184 smp_chan_destroy(conn);
Vinicius Costa Gomesd26a2342011-08-19 21:06:51 -03001185 }
1186
Vinicius Costa Gomes7034b912011-07-07 18:59:34 -03001187 return 0;
1188}