blob: 5867c1c3f4367253386691482286a1c21b074ae6 [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;
416 struct crypto_blkcipher *tfm;
417 struct smp_cmd_pairing_confirm cp;
418 int ret;
419 u8 res[16], reason;
420
421 BT_DBG("conn %p", conn);
422
423 tfm = crypto_alloc_blkcipher("ecb(aes)", 0, CRYPTO_ALG_ASYNC);
424 if (IS_ERR(tfm)) {
425 reason = SMP_UNSPECIFIED;
426 goto error;
427 }
428
429 smp->tfm = tfm;
430
431 if (conn->hcon->out)
Marcel Holtmannc8462ca2013-10-13 05:24:02 -0700432 ret = smp_c1(tfm, smp->tk, smp->prnd, smp->preq, smp->prsp,
433 conn->hcon->src_type, &conn->hcon->src,
434 conn->hcon->dst_type, &conn->hcon->dst, res);
Vinicius Costa Gomes8aab4752011-09-05 14:31:31 -0300435 else
436 ret = smp_c1(tfm, smp->tk, smp->prnd, smp->preq, smp->prsp,
Marcel Holtmannc8462ca2013-10-13 05:24:02 -0700437 conn->hcon->dst_type, &conn->hcon->dst,
438 conn->hcon->src_type, &conn->hcon->src, res);
Vinicius Costa Gomes8aab4752011-09-05 14:31:31 -0300439 if (ret) {
440 reason = SMP_UNSPECIFIED;
441 goto error;
442 }
443
Brian Gix2b64d152011-12-21 16:12:12 -0800444 clear_bit(SMP_FLAG_CFM_PENDING, &smp->smp_flags);
445
Vinicius Costa Gomes8aab4752011-09-05 14:31:31 -0300446 swap128(res, cp.confirm_val);
447 smp_send_cmd(smp->conn, SMP_CMD_PAIRING_CONFIRM, sizeof(cp), &cp);
448
449 return;
450
451error:
Johan Hedberg84794e12013-11-06 11:24:57 +0200452 smp_failure(conn, reason);
Vinicius Costa Gomes8aab4752011-09-05 14:31:31 -0300453}
454
455static void random_work(struct work_struct *work)
456{
457 struct smp_chan *smp = container_of(work, struct smp_chan, random);
458 struct l2cap_conn *conn = smp->conn;
459 struct hci_conn *hcon = conn->hcon;
460 struct crypto_blkcipher *tfm = smp->tfm;
461 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
471 if (hcon->out)
Marcel Holtmannc8462ca2013-10-13 05:24:02 -0700472 ret = smp_c1(tfm, smp->tk, smp->rrnd, smp->preq, smp->prsp,
473 hcon->src_type, &hcon->src,
474 hcon->dst_type, &hcon->dst, res);
Vinicius Costa Gomes8aab4752011-09-05 14:31:31 -0300475 else
476 ret = smp_c1(tfm, smp->tk, smp->rrnd, smp->preq, smp->prsp,
Marcel Holtmannc8462ca2013-10-13 05:24:02 -0700477 hcon->dst_type, &hcon->dst,
478 hcon->src_type, &hcon->src, res);
Vinicius Costa Gomes8aab4752011-09-05 14:31:31 -0300479 if (ret) {
480 reason = SMP_UNSPECIFIED;
481 goto error;
482 }
483
484 swap128(res, confirm);
485
486 if (memcmp(smp->pcnf, confirm, sizeof(smp->pcnf)) != 0) {
487 BT_ERR("Pairing failed (confirmation values mismatch)");
488 reason = SMP_CONFIRM_FAILED;
489 goto error;
490 }
491
492 if (hcon->out) {
493 u8 stk[16], rand[8];
494 __le16 ediv;
495
496 memset(rand, 0, sizeof(rand));
497 ediv = 0;
498
499 smp_s1(tfm, smp->tk, smp->rrnd, smp->prnd, key);
500 swap128(key, stk);
501
Vinicius Costa Gomesf7aa6112012-01-30 19:29:12 -0300502 memset(stk + smp->enc_key_size, 0,
Gustavo F. Padovan04124682012-03-08 01:25:00 -0300503 SMP_MAX_ENC_KEY_SIZE - smp->enc_key_size);
Vinicius Costa Gomes8aab4752011-09-05 14:31:31 -0300504
Johan Hedberg51a8efd2012-01-16 06:10:31 +0200505 if (test_and_set_bit(HCI_CONN_ENCRYPT_PEND, &hcon->flags)) {
Vinicius Costa Gomes8aab4752011-09-05 14:31:31 -0300506 reason = SMP_UNSPECIFIED;
507 goto error;
508 }
509
510 hci_le_start_enc(hcon, ediv, rand, stk);
Vinicius Costa Gomesf7aa6112012-01-30 19:29:12 -0300511 hcon->enc_key_size = smp->enc_key_size;
Vinicius Costa Gomes8aab4752011-09-05 14:31:31 -0300512 } else {
513 u8 stk[16], r[16], rand[8];
514 __le16 ediv;
515
516 memset(rand, 0, sizeof(rand));
517 ediv = 0;
518
519 swap128(smp->prnd, r);
520 smp_send_cmd(conn, SMP_CMD_PAIRING_RANDOM, sizeof(r), r);
521
522 smp_s1(tfm, smp->tk, smp->prnd, smp->rrnd, key);
523 swap128(key, stk);
524
Vinicius Costa Gomesf7aa6112012-01-30 19:29:12 -0300525 memset(stk + smp->enc_key_size, 0,
Marcel Holtmannf1560462013-10-13 05:43:25 -0700526 SMP_MAX_ENC_KEY_SIZE - smp->enc_key_size);
Vinicius Costa Gomes8aab4752011-09-05 14:31:31 -0300527
Marcel Holtmannce39fb42013-10-13 02:23:39 -0700528 hci_add_ltk(hcon->hdev, &hcon->dst, hcon->dst_type,
Gustavo F. Padovan04124682012-03-08 01:25:00 -0300529 HCI_SMP_STK_SLAVE, 0, 0, stk, smp->enc_key_size,
530 ediv, rand);
Vinicius Costa Gomes8aab4752011-09-05 14:31:31 -0300531 }
532
533 return;
534
535error:
Johan Hedberg84794e12013-11-06 11:24:57 +0200536 smp_failure(conn, reason);
Vinicius Costa Gomes8aab4752011-09-05 14:31:31 -0300537}
538
539static struct smp_chan *smp_chan_create(struct l2cap_conn *conn)
540{
541 struct smp_chan *smp;
542
Marcel Holtmannf1560462013-10-13 05:43:25 -0700543 smp = kzalloc(sizeof(*smp), GFP_ATOMIC);
Vinicius Costa Gomes8aab4752011-09-05 14:31:31 -0300544 if (!smp)
545 return NULL;
546
547 INIT_WORK(&smp->confirm, confirm_work);
548 INIT_WORK(&smp->random, random_work);
549
550 smp->conn = conn;
551 conn->smp_chan = smp;
Brian Gix2b64d152011-12-21 16:12:12 -0800552 conn->hcon->smp_conn = conn;
Vinicius Costa Gomes8aab4752011-09-05 14:31:31 -0300553
554 hci_conn_hold(conn->hcon);
555
556 return smp;
557}
558
559void smp_chan_destroy(struct l2cap_conn *conn)
560{
Brian Gixc8eb9692011-11-23 08:28:35 -0800561 struct smp_chan *smp = conn->smp_chan;
562
Vinicius Costa Gomesf1c09c02012-02-01 18:27:56 -0300563 BUG_ON(!smp);
Brian Gixc8eb9692011-11-23 08:28:35 -0800564
565 if (smp->tfm)
566 crypto_free_blkcipher(smp->tfm);
567
568 kfree(smp);
569 conn->smp_chan = NULL;
Brian Gix2b64d152011-12-21 16:12:12 -0800570 conn->hcon->smp_conn = NULL;
David Herrmann76a68ba2013-04-06 20:28:37 +0200571 hci_conn_drop(conn->hcon);
Vinicius Costa Gomes8aab4752011-09-05 14:31:31 -0300572}
573
Brian Gix2b64d152011-12-21 16:12:12 -0800574int smp_user_confirm_reply(struct hci_conn *hcon, u16 mgmt_op, __le32 passkey)
575{
576 struct l2cap_conn *conn = hcon->smp_conn;
577 struct smp_chan *smp;
578 u32 value;
579 u8 key[16];
580
581 BT_DBG("");
582
583 if (!conn)
584 return -ENOTCONN;
585
586 smp = conn->smp_chan;
587
588 switch (mgmt_op) {
589 case MGMT_OP_USER_PASSKEY_REPLY:
590 value = le32_to_cpu(passkey);
591 memset(key, 0, sizeof(key));
592 BT_DBG("PassKey: %d", value);
593 put_unaligned_le32(value, key);
594 swap128(key, smp->tk);
595 /* Fall Through */
596 case MGMT_OP_USER_CONFIRM_REPLY:
597 set_bit(SMP_FLAG_TK_VALID, &smp->smp_flags);
598 break;
599 case MGMT_OP_USER_PASSKEY_NEG_REPLY:
600 case MGMT_OP_USER_CONFIRM_NEG_REPLY:
Johan Hedberg84794e12013-11-06 11:24:57 +0200601 smp_failure(conn, SMP_PASSKEY_ENTRY_FAILED);
Brian Gix2b64d152011-12-21 16:12:12 -0800602 return 0;
603 default:
Johan Hedberg84794e12013-11-06 11:24:57 +0200604 smp_failure(conn, SMP_PASSKEY_ENTRY_FAILED);
Brian Gix2b64d152011-12-21 16:12:12 -0800605 return -EOPNOTSUPP;
606 }
607
608 /* If it is our turn to send Pairing Confirm, do so now */
609 if (test_bit(SMP_FLAG_CFM_PENDING, &smp->smp_flags))
610 queue_work(hcon->hdev->workqueue, &smp->confirm);
611
612 return 0;
613}
614
Vinicius Costa Gomesda85e5e2011-06-09 18:50:53 -0300615static u8 smp_cmd_pairing_req(struct l2cap_conn *conn, struct sk_buff *skb)
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300616{
Vinicius Costa Gomes3158c502011-06-14 13:37:42 -0300617 struct smp_cmd_pairing rsp, *req = (void *) skb->data;
Vinicius Costa Gomes8aab4752011-09-05 14:31:31 -0300618 struct smp_chan *smp;
Vinicius Costa Gomes3158c502011-06-14 13:37:42 -0300619 u8 key_size;
Brian Gix2b64d152011-12-21 16:12:12 -0800620 u8 auth = SMP_AUTH_NONE;
Vinicius Costa Gomes8aab4752011-09-05 14:31:31 -0300621 int ret;
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300622
623 BT_DBG("conn %p", conn);
624
Johan Hedbergc46b98b2014-02-18 10:19:29 +0200625 if (skb->len < sizeof(*req))
626 return SMP_UNSPECIFIED;
627
Brian Gix2b64d152011-12-21 16:12:12 -0800628 if (conn->hcon->link_mode & HCI_LM_MASTER)
629 return SMP_CMD_NOTSUPP;
630
Johan Hedberg51a8efd2012-01-16 06:10:31 +0200631 if (!test_and_set_bit(HCI_CONN_LE_SMP_PEND, &conn->hcon->flags))
Vinicius Costa Gomes8aab4752011-09-05 14:31:31 -0300632 smp = smp_chan_create(conn);
Andrei Emeltchenkod08fd0e2012-07-19 17:03:43 +0300633 else
634 smp = conn->smp_chan;
Vinicius Costa Gomes8aab4752011-09-05 14:31:31 -0300635
Andrei Emeltchenkod08fd0e2012-07-19 17:03:43 +0300636 if (!smp)
637 return SMP_UNSPECIFIED;
Vinicius Costa Gomesd26a2342011-08-19 21:06:51 -0300638
Vinicius Costa Gomes1c1def02011-09-05 14:31:30 -0300639 smp->preq[0] = SMP_CMD_PAIRING_REQ;
640 memcpy(&smp->preq[1], req, sizeof(*req));
Vinicius Costa Gomes3158c502011-06-14 13:37:42 -0300641 skb_pull(skb, sizeof(*req));
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300642
Brian Gix2b64d152011-12-21 16:12:12 -0800643 /* We didn't start the pairing, so match remote */
644 if (req->auth_req & SMP_AUTH_BONDING)
645 auth = req->auth_req;
Vinicius Costa Gomesda85e5e2011-06-09 18:50:53 -0300646
Ido Yarivfdde0a22012-03-05 20:09:38 +0200647 conn->hcon->pending_sec_level = authreq_to_seclevel(auth);
648
Brian Gix2b64d152011-12-21 16:12:12 -0800649 build_pairing_cmd(conn, req, &rsp, auth);
Vinicius Costa Gomes3158c502011-06-14 13:37:42 -0300650
651 key_size = min(req->max_key_size, rsp.max_key_size);
652 if (check_enc_key_size(conn, key_size))
653 return SMP_ENC_KEY_SIZE;
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300654
Johan Hedberge84a6b12013-12-02 10:49:03 +0200655 get_random_bytes(smp->prnd, sizeof(smp->prnd));
Vinicius Costa Gomes8aab4752011-09-05 14:31:31 -0300656
Vinicius Costa Gomes1c1def02011-09-05 14:31:30 -0300657 smp->prsp[0] = SMP_CMD_PAIRING_RSP;
658 memcpy(&smp->prsp[1], &rsp, sizeof(rsp));
Anderson Brigliaf01ead32011-06-09 18:50:45 -0300659
Vinicius Costa Gomes3158c502011-06-14 13:37:42 -0300660 smp_send_cmd(conn, SMP_CMD_PAIRING_RSP, sizeof(rsp), &rsp);
Vinicius Costa Gomesda85e5e2011-06-09 18:50:53 -0300661
Brian Gix2b64d152011-12-21 16:12:12 -0800662 /* Request setup of TK */
663 ret = tk_request(conn, 0, auth, rsp.io_capability, req->io_capability);
664 if (ret)
665 return SMP_UNSPECIFIED;
666
Vinicius Costa Gomesda85e5e2011-06-09 18:50:53 -0300667 return 0;
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300668}
669
Vinicius Costa Gomesda85e5e2011-06-09 18:50:53 -0300670static u8 smp_cmd_pairing_rsp(struct l2cap_conn *conn, struct sk_buff *skb)
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300671{
Vinicius Costa Gomes3158c502011-06-14 13:37:42 -0300672 struct smp_cmd_pairing *req, *rsp = (void *) skb->data;
Vinicius Costa Gomes1c1def02011-09-05 14:31:30 -0300673 struct smp_chan *smp = conn->smp_chan;
Vinicius Costa Gomes8aab4752011-09-05 14:31:31 -0300674 struct hci_dev *hdev = conn->hcon->hdev;
Brian Gix2b64d152011-12-21 16:12:12 -0800675 u8 key_size, auth = SMP_AUTH_NONE;
Anderson Briglia7d24ddc2011-06-09 18:50:46 -0300676 int ret;
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300677
678 BT_DBG("conn %p", conn);
679
Johan Hedbergc46b98b2014-02-18 10:19:29 +0200680 if (skb->len < sizeof(*rsp))
681 return SMP_UNSPECIFIED;
682
Brian Gix2b64d152011-12-21 16:12:12 -0800683 if (!(conn->hcon->link_mode & HCI_LM_MASTER))
684 return SMP_CMD_NOTSUPP;
685
Vinicius Costa Gomes3158c502011-06-14 13:37:42 -0300686 skb_pull(skb, sizeof(*rsp));
Vinicius Costa Gomesda85e5e2011-06-09 18:50:53 -0300687
Vinicius Costa Gomes1c1def02011-09-05 14:31:30 -0300688 req = (void *) &smp->preq[1];
Vinicius Costa Gomes3158c502011-06-14 13:37:42 -0300689
690 key_size = min(req->max_key_size, rsp->max_key_size);
691 if (check_enc_key_size(conn, key_size))
692 return SMP_ENC_KEY_SIZE;
693
Johan Hedberge84a6b12013-12-02 10:49:03 +0200694 get_random_bytes(smp->prnd, sizeof(smp->prnd));
Anderson Briglia7d24ddc2011-06-09 18:50:46 -0300695
Vinicius Costa Gomes8aab4752011-09-05 14:31:31 -0300696 smp->prsp[0] = SMP_CMD_PAIRING_RSP;
697 memcpy(&smp->prsp[1], rsp, sizeof(*rsp));
Anderson Briglia7d24ddc2011-06-09 18:50:46 -0300698
Brian Gix2b64d152011-12-21 16:12:12 -0800699 if ((req->auth_req & SMP_AUTH_BONDING) &&
Marcel Holtmannf1560462013-10-13 05:43:25 -0700700 (rsp->auth_req & SMP_AUTH_BONDING))
Brian Gix2b64d152011-12-21 16:12:12 -0800701 auth = SMP_AUTH_BONDING;
702
703 auth |= (req->auth_req | rsp->auth_req) & SMP_AUTH_MITM;
704
Johan Hedberg476585e2012-06-06 18:54:15 +0800705 ret = tk_request(conn, 0, auth, req->io_capability, rsp->io_capability);
Brian Gix2b64d152011-12-21 16:12:12 -0800706 if (ret)
707 return SMP_UNSPECIFIED;
708
709 set_bit(SMP_FLAG_CFM_PENDING, &smp->smp_flags);
710
711 /* Can't compose response until we have been confirmed */
712 if (!test_bit(SMP_FLAG_TK_VALID, &smp->smp_flags))
713 return 0;
714
Vinicius Costa Gomes8aab4752011-09-05 14:31:31 -0300715 queue_work(hdev->workqueue, &smp->confirm);
Vinicius Costa Gomesda85e5e2011-06-09 18:50:53 -0300716
717 return 0;
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300718}
719
Vinicius Costa Gomesda85e5e2011-06-09 18:50:53 -0300720static u8 smp_cmd_pairing_confirm(struct l2cap_conn *conn, struct sk_buff *skb)
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300721{
Vinicius Costa Gomes1c1def02011-09-05 14:31:30 -0300722 struct smp_chan *smp = conn->smp_chan;
Vinicius Costa Gomes8aab4752011-09-05 14:31:31 -0300723 struct hci_dev *hdev = conn->hcon->hdev;
Anderson Briglia7d24ddc2011-06-09 18:50:46 -0300724
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300725 BT_DBG("conn %p %s", conn, conn->hcon->out ? "master" : "slave");
726
Johan Hedbergc46b98b2014-02-18 10:19:29 +0200727 if (skb->len < sizeof(smp->pcnf))
728 return SMP_UNSPECIFIED;
729
Vinicius Costa Gomes1c1def02011-09-05 14:31:30 -0300730 memcpy(smp->pcnf, skb->data, sizeof(smp->pcnf));
731 skb_pull(skb, sizeof(smp->pcnf));
Anderson Briglia7d24ddc2011-06-09 18:50:46 -0300732
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300733 if (conn->hcon->out) {
Anderson Briglia7d24ddc2011-06-09 18:50:46 -0300734 u8 random[16];
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300735
Vinicius Costa Gomes1c1def02011-09-05 14:31:30 -0300736 swap128(smp->prnd, random);
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300737 smp_send_cmd(conn, SMP_CMD_PAIRING_RANDOM, sizeof(random),
Marcel Holtmannf1560462013-10-13 05:43:25 -0700738 random);
Brian Gix2b64d152011-12-21 16:12:12 -0800739 } else if (test_bit(SMP_FLAG_TK_VALID, &smp->smp_flags)) {
Vinicius Costa Gomes8aab4752011-09-05 14:31:31 -0300740 queue_work(hdev->workqueue, &smp->confirm);
Brian Gix2b64d152011-12-21 16:12:12 -0800741 } else {
742 set_bit(SMP_FLAG_CFM_PENDING, &smp->smp_flags);
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300743 }
Vinicius Costa Gomesda85e5e2011-06-09 18:50:53 -0300744
745 return 0;
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300746}
747
Vinicius Costa Gomesda85e5e2011-06-09 18:50:53 -0300748static u8 smp_cmd_pairing_random(struct l2cap_conn *conn, struct sk_buff *skb)
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300749{
Vinicius Costa Gomes1c1def02011-09-05 14:31:30 -0300750 struct smp_chan *smp = conn->smp_chan;
Vinicius Costa Gomes8aab4752011-09-05 14:31:31 -0300751 struct hci_dev *hdev = conn->hcon->hdev;
Anderson Briglia7d24ddc2011-06-09 18:50:46 -0300752
Vinicius Costa Gomes8aab4752011-09-05 14:31:31 -0300753 BT_DBG("conn %p", conn);
Anderson Briglia7d24ddc2011-06-09 18:50:46 -0300754
Johan Hedbergc46b98b2014-02-18 10:19:29 +0200755 if (skb->len < sizeof(smp->rrnd))
756 return SMP_UNSPECIFIED;
757
Vinicius Costa Gomes8aab4752011-09-05 14:31:31 -0300758 swap128(skb->data, smp->rrnd);
759 skb_pull(skb, sizeof(smp->rrnd));
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300760
Vinicius Costa Gomes8aab4752011-09-05 14:31:31 -0300761 queue_work(hdev->workqueue, &smp->random);
Vinicius Costa Gomesda85e5e2011-06-09 18:50:53 -0300762
763 return 0;
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300764}
765
Johan Hedberg4dab7862012-06-07 14:58:37 +0800766static u8 smp_ltk_encrypt(struct l2cap_conn *conn, u8 sec_level)
Vinicius Costa Gomes988c5992011-08-25 20:02:28 -0300767{
Vinicius Costa Gomesc9839a12012-02-02 21:08:01 -0300768 struct smp_ltk *key;
Vinicius Costa Gomes988c5992011-08-25 20:02:28 -0300769 struct hci_conn *hcon = conn->hcon;
770
Johan Hedberg98a0b842014-01-30 19:40:00 -0800771 key = hci_find_ltk_by_addr(hcon->hdev, &hcon->dst, hcon->dst_type,
772 hcon->out);
Vinicius Costa Gomes988c5992011-08-25 20:02:28 -0300773 if (!key)
774 return 0;
775
Johan Hedberg4dab7862012-06-07 14:58:37 +0800776 if (sec_level > BT_SECURITY_MEDIUM && !key->authenticated)
777 return 0;
778
Johan Hedberg51a8efd2012-01-16 06:10:31 +0200779 if (test_and_set_bit(HCI_CONN_ENCRYPT_PEND, &hcon->flags))
Vinicius Costa Gomes988c5992011-08-25 20:02:28 -0300780 return 1;
781
Vinicius Costa Gomesc9839a12012-02-02 21:08:01 -0300782 hci_le_start_enc(hcon, key->ediv, key->rand, key->val);
783 hcon->enc_key_size = key->enc_size;
Vinicius Costa Gomes988c5992011-08-25 20:02:28 -0300784
785 return 1;
Vinicius Costa Gomes988c5992011-08-25 20:02:28 -0300786}
Marcel Holtmannf1560462013-10-13 05:43:25 -0700787
Vinicius Costa Gomesda85e5e2011-06-09 18:50:53 -0300788static u8 smp_cmd_security_req(struct l2cap_conn *conn, struct sk_buff *skb)
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300789{
790 struct smp_cmd_security_req *rp = (void *) skb->data;
791 struct smp_cmd_pairing cp;
Vinicius Costa Gomesf1cb9af2011-01-26 21:42:57 -0300792 struct hci_conn *hcon = conn->hcon;
Vinicius Costa Gomes8aab4752011-09-05 14:31:31 -0300793 struct smp_chan *smp;
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300794
795 BT_DBG("conn %p", conn);
796
Johan Hedbergc46b98b2014-02-18 10:19:29 +0200797 if (skb->len < sizeof(*rp))
798 return SMP_UNSPECIFIED;
799
Johan Hedberg86ca9ea2013-11-05 11:30:39 +0200800 if (!(conn->hcon->link_mode & HCI_LM_MASTER))
801 return SMP_CMD_NOTSUPP;
802
Brian Gix2b64d152011-12-21 16:12:12 -0800803 hcon->pending_sec_level = authreq_to_seclevel(rp->auth_req);
Vinicius Costa Gomesfeb45eb2011-08-25 20:02:35 -0300804
Johan Hedberg4dab7862012-06-07 14:58:37 +0800805 if (smp_ltk_encrypt(conn, hcon->pending_sec_level))
Vinicius Costa Gomes988c5992011-08-25 20:02:28 -0300806 return 0;
807
Johan Hedberg51a8efd2012-01-16 06:10:31 +0200808 if (test_and_set_bit(HCI_CONN_LE_SMP_PEND, &hcon->flags))
Vinicius Costa Gomesda85e5e2011-06-09 18:50:53 -0300809 return 0;
Vinicius Costa Gomesf1cb9af2011-01-26 21:42:57 -0300810
Vinicius Costa Gomes8aab4752011-09-05 14:31:31 -0300811 smp = smp_chan_create(conn);
Vinicius Costa Gomesd26a2342011-08-19 21:06:51 -0300812
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300813 skb_pull(skb, sizeof(*rp));
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300814
Vinicius Costa Gomesda85e5e2011-06-09 18:50:53 -0300815 memset(&cp, 0, sizeof(cp));
Vinicius Costa Gomes54790f72011-07-07 18:59:38 -0300816 build_pairing_cmd(conn, &cp, NULL, rp->auth_req);
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300817
Vinicius Costa Gomes1c1def02011-09-05 14:31:30 -0300818 smp->preq[0] = SMP_CMD_PAIRING_REQ;
819 memcpy(&smp->preq[1], &cp, sizeof(cp));
Anderson Brigliaf01ead32011-06-09 18:50:45 -0300820
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300821 smp_send_cmd(conn, SMP_CMD_PAIRING_REQ, sizeof(cp), &cp);
Vinicius Costa Gomesf1cb9af2011-01-26 21:42:57 -0300822
Vinicius Costa Gomesda85e5e2011-06-09 18:50:53 -0300823 return 0;
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300824}
825
Johan Hedbergad32a2f2013-05-14 18:05:12 +0300826bool smp_sufficient_security(struct hci_conn *hcon, u8 sec_level)
827{
828 if (sec_level == BT_SECURITY_LOW)
829 return true;
830
831 if (hcon->sec_level >= sec_level)
832 return true;
833
834 return false;
835}
836
Vinicius Costa Gomescc110922012-08-23 21:32:43 -0300837int smp_conn_security(struct hci_conn *hcon, __u8 sec_level)
Anderson Brigliaeb492e02011-06-09 18:50:40 -0300838{
Vinicius Costa Gomescc110922012-08-23 21:32:43 -0300839 struct l2cap_conn *conn = hcon->l2cap_data;
Vinicius Costa Gomes1c1def02011-09-05 14:31:30 -0300840 struct smp_chan *smp = conn->smp_chan;
Brian Gix2b64d152011-12-21 16:12:12 -0800841 __u8 authreq;
Anderson Brigliaeb492e02011-06-09 18:50:40 -0300842
Vinicius Costa Gomes3a0259b2011-06-09 18:50:43 -0300843 BT_DBG("conn %p hcon %p level 0x%2.2x", conn, hcon, sec_level);
844
Johan Hedberg757aee02013-04-24 13:05:32 +0300845 if (!test_bit(HCI_LE_ENABLED, &hcon->hdev->dev_flags))
Andre Guedes2e65c9d2011-06-30 19:20:56 -0300846 return 1;
847
Johan Hedbergad32a2f2013-05-14 18:05:12 +0300848 if (smp_sufficient_security(hcon, sec_level))
Vinicius Costa Gomesf1cb9af2011-01-26 21:42:57 -0300849 return 1;
850
Vinicius Costa Gomes988c5992011-08-25 20:02:28 -0300851 if (hcon->link_mode & HCI_LM_MASTER)
Johan Hedberg4dab7862012-06-07 14:58:37 +0800852 if (smp_ltk_encrypt(conn, sec_level))
Vinicius Costa Gomes02bc7452011-07-07 18:59:41 -0300853 goto done;
Vinicius Costa Gomesd26a2342011-08-19 21:06:51 -0300854
Johan Hedberg51a8efd2012-01-16 06:10:31 +0200855 if (test_and_set_bit(HCI_CONN_LE_SMP_PEND, &hcon->flags))
Vinicius Costa Gomesd26a2342011-08-19 21:06:51 -0300856 return 0;
857
Vinicius Costa Gomes8aab4752011-09-05 14:31:31 -0300858 smp = smp_chan_create(conn);
Brian Gix2b64d152011-12-21 16:12:12 -0800859 if (!smp)
860 return 1;
861
862 authreq = seclevel_to_authreq(sec_level);
Vinicius Costa Gomesd26a2342011-08-19 21:06:51 -0300863
Vinicius Costa Gomesd26a2342011-08-19 21:06:51 -0300864 if (hcon->link_mode & HCI_LM_MASTER) {
865 struct smp_cmd_pairing cp;
Anderson Brigliaf01ead32011-06-09 18:50:45 -0300866
Brian Gix2b64d152011-12-21 16:12:12 -0800867 build_pairing_cmd(conn, &cp, NULL, authreq);
Vinicius Costa Gomes1c1def02011-09-05 14:31:30 -0300868 smp->preq[0] = SMP_CMD_PAIRING_REQ;
869 memcpy(&smp->preq[1], &cp, sizeof(cp));
Anderson Brigliaf01ead32011-06-09 18:50:45 -0300870
Anderson Brigliaeb492e02011-06-09 18:50:40 -0300871 smp_send_cmd(conn, SMP_CMD_PAIRING_REQ, sizeof(cp), &cp);
872 } else {
873 struct smp_cmd_security_req cp;
Brian Gix2b64d152011-12-21 16:12:12 -0800874 cp.auth_req = authreq;
Anderson Brigliaeb492e02011-06-09 18:50:40 -0300875 smp_send_cmd(conn, SMP_CMD_SECURITY_REQ, sizeof(cp), &cp);
876 }
877
Vinicius Costa Gomes02bc7452011-07-07 18:59:41 -0300878done:
Vinicius Costa Gomesf1cb9af2011-01-26 21:42:57 -0300879 hcon->pending_sec_level = sec_level;
Vinicius Costa Gomesf1cb9af2011-01-26 21:42:57 -0300880
Anderson Brigliaeb492e02011-06-09 18:50:40 -0300881 return 0;
882}
883
Vinicius Costa Gomes7034b912011-07-07 18:59:34 -0300884static int smp_cmd_encrypt_info(struct l2cap_conn *conn, struct sk_buff *skb)
885{
Vinicius Costa Gomes16b90832011-07-07 18:59:39 -0300886 struct smp_cmd_encrypt_info *rp = (void *) skb->data;
Vinicius Costa Gomes1c1def02011-09-05 14:31:30 -0300887 struct smp_chan *smp = conn->smp_chan;
Vinicius Costa Gomes16b90832011-07-07 18:59:39 -0300888
Johan Hedbergc46b98b2014-02-18 10:19:29 +0200889 BT_DBG("conn %p", conn);
890
891 if (skb->len < sizeof(*rp))
892 return SMP_UNSPECIFIED;
893
Johan Hedberg6131ddc2014-02-18 10:19:37 +0200894 /* Ignore this PDU if it wasn't requested */
895 if (!(smp->remote_key_dist & SMP_DIST_ENC_KEY))
896 return 0;
897
Vinicius Costa Gomes16b90832011-07-07 18:59:39 -0300898 skb_pull(skb, sizeof(*rp));
899
Vinicius Costa Gomes1c1def02011-09-05 14:31:30 -0300900 memcpy(smp->tk, rp->ltk, sizeof(smp->tk));
Vinicius Costa Gomes16b90832011-07-07 18:59:39 -0300901
Vinicius Costa Gomes7034b912011-07-07 18:59:34 -0300902 return 0;
903}
904
905static int smp_cmd_master_ident(struct l2cap_conn *conn, struct sk_buff *skb)
906{
Vinicius Costa Gomes16b90832011-07-07 18:59:39 -0300907 struct smp_cmd_master_ident *rp = (void *) skb->data;
Vinicius Costa Gomes1c1def02011-09-05 14:31:30 -0300908 struct smp_chan *smp = conn->smp_chan;
Vinicius Costa Gomesc9839a12012-02-02 21:08:01 -0300909 struct hci_dev *hdev = conn->hcon->hdev;
910 struct hci_conn *hcon = conn->hcon;
911 u8 authenticated;
Vinicius Costa Gomes7034b912011-07-07 18:59:34 -0300912
Johan Hedbergc46b98b2014-02-18 10:19:29 +0200913 BT_DBG("conn %p", conn);
914
915 if (skb->len < sizeof(*rp))
916 return SMP_UNSPECIFIED;
917
Johan Hedberg6131ddc2014-02-18 10:19:37 +0200918 /* Ignore this PDU if it wasn't requested */
919 if (!(smp->remote_key_dist & SMP_DIST_ENC_KEY))
920 return 0;
921
Vinicius Costa Gomes16b90832011-07-07 18:59:39 -0300922 skb_pull(skb, sizeof(*rp));
923
Vinicius Costa Gomesc9839a12012-02-02 21:08:01 -0300924 hci_dev_lock(hdev);
Marcel Holtmannce39fb42013-10-13 02:23:39 -0700925 authenticated = (hcon->sec_level == BT_SECURITY_HIGH);
926 hci_add_ltk(hdev, &hcon->dst, hcon->dst_type, HCI_SMP_LTK, 1,
927 authenticated, smp->tk, smp->enc_key_size,
Gustavo F. Padovan04124682012-03-08 01:25:00 -0300928 rp->ediv, rp->rand);
Johan Hedbergfd349c02014-02-18 10:19:36 +0200929 if (!(smp->remote_key_dist & SMP_DIST_ID_KEY))
930 smp_distribute_keys(conn, 1);
Vinicius Costa Gomesc9839a12012-02-02 21:08:01 -0300931 hci_dev_unlock(hdev);
Vinicius Costa Gomes7034b912011-07-07 18:59:34 -0300932
933 return 0;
934}
935
Johan Hedbergfd349c02014-02-18 10:19:36 +0200936static int smp_cmd_ident_info(struct l2cap_conn *conn, struct sk_buff *skb)
937{
938 struct smp_cmd_ident_info *info = (void *) skb->data;
939 struct smp_chan *smp = conn->smp_chan;
940
941 BT_DBG("");
942
943 if (skb->len < sizeof(*info))
944 return SMP_UNSPECIFIED;
945
Johan Hedberg6131ddc2014-02-18 10:19:37 +0200946 /* Ignore this PDU if it wasn't requested */
947 if (!(smp->remote_key_dist & SMP_DIST_ID_KEY))
948 return 0;
949
Johan Hedbergfd349c02014-02-18 10:19:36 +0200950 skb_pull(skb, sizeof(*info));
951
952 memcpy(smp->irk, info->irk, 16);
953
954 return 0;
955}
956
957static int smp_cmd_ident_addr_info(struct l2cap_conn *conn,
958 struct sk_buff *skb)
959{
960 struct smp_cmd_ident_addr_info *info = (void *) skb->data;
961 struct smp_chan *smp = conn->smp_chan;
962 struct hci_conn *hcon = conn->hcon;
963 bdaddr_t rpa;
964
965 BT_DBG("");
966
967 if (skb->len < sizeof(*info))
968 return SMP_UNSPECIFIED;
969
Johan Hedberg6131ddc2014-02-18 10:19:37 +0200970 /* Ignore this PDU if it wasn't requested */
971 if (!(smp->remote_key_dist & SMP_DIST_ID_KEY))
972 return 0;
973
Johan Hedbergfd349c02014-02-18 10:19:36 +0200974 skb_pull(skb, sizeof(*info));
975
976 bacpy(&smp->id_addr, &info->bdaddr);
977 smp->id_addr_type = info->addr_type;
978
979 if (hci_bdaddr_is_rpa(&hcon->dst, hcon->dst_type))
980 bacpy(&rpa, &hcon->dst);
981 else
982 bacpy(&rpa, BDADDR_ANY);
983
984 hci_add_irk(conn->hcon->hdev, &smp->id_addr, smp->id_addr_type,
985 smp->irk, &rpa);
986
987 smp_distribute_keys(conn, 1);
988
989 return 0;
990}
991
Anderson Brigliaeb492e02011-06-09 18:50:40 -0300992int smp_sig_channel(struct l2cap_conn *conn, struct sk_buff *skb)
993{
Marcel Holtmann7b9899d2013-10-03 00:00:57 -0700994 struct hci_conn *hcon = conn->hcon;
Marcel Holtmann92381f52013-10-03 01:23:08 -0700995 __u8 code, reason;
Anderson Brigliaeb492e02011-06-09 18:50:40 -0300996 int err = 0;
997
Marcel Holtmann7b9899d2013-10-03 00:00:57 -0700998 if (hcon->type != LE_LINK) {
999 kfree_skb(skb);
Johan Hedberg34327112013-10-16 11:37:01 +03001000 return 0;
Marcel Holtmann7b9899d2013-10-03 00:00:57 -07001001 }
1002
Marcel Holtmann92381f52013-10-03 01:23:08 -07001003 if (skb->len < 1) {
1004 kfree_skb(skb);
1005 return -EILSEQ;
1006 }
1007
Marcel Holtmann06ae3312013-10-18 03:43:00 -07001008 if (!test_bit(HCI_LE_ENABLED, &hcon->hdev->dev_flags)) {
Andre Guedes2e65c9d2011-06-30 19:20:56 -03001009 err = -ENOTSUPP;
1010 reason = SMP_PAIRING_NOTSUPP;
1011 goto done;
1012 }
1013
Marcel Holtmann92381f52013-10-03 01:23:08 -07001014 code = skb->data[0];
Anderson Brigliaeb492e02011-06-09 18:50:40 -03001015 skb_pull(skb, sizeof(code));
1016
Johan Hedberg8cf9fa12013-01-29 10:44:23 -06001017 /*
1018 * The SMP context must be initialized for all other PDUs except
1019 * pairing and security requests. If we get any other PDU when
1020 * not initialized simply disconnect (done if this function
1021 * returns an error).
1022 */
1023 if (code != SMP_CMD_PAIRING_REQ && code != SMP_CMD_SECURITY_REQ &&
1024 !conn->smp_chan) {
1025 BT_ERR("Unexpected SMP command 0x%02x. Disconnecting.", code);
1026 kfree_skb(skb);
1027 return -ENOTSUPP;
1028 }
1029
Anderson Brigliaeb492e02011-06-09 18:50:40 -03001030 switch (code) {
1031 case SMP_CMD_PAIRING_REQ:
Vinicius Costa Gomesda85e5e2011-06-09 18:50:53 -03001032 reason = smp_cmd_pairing_req(conn, skb);
Anderson Brigliaeb492e02011-06-09 18:50:40 -03001033 break;
1034
1035 case SMP_CMD_PAIRING_FAIL:
Johan Hedberg84794e12013-11-06 11:24:57 +02001036 smp_failure(conn, 0);
Vinicius Costa Gomesda85e5e2011-06-09 18:50:53 -03001037 reason = 0;
1038 err = -EPERM;
Anderson Brigliaeb492e02011-06-09 18:50:40 -03001039 break;
1040
1041 case SMP_CMD_PAIRING_RSP:
Vinicius Costa Gomesda85e5e2011-06-09 18:50:53 -03001042 reason = smp_cmd_pairing_rsp(conn, skb);
Anderson Briglia88ba43b2011-06-09 18:50:42 -03001043 break;
1044
1045 case SMP_CMD_SECURITY_REQ:
Vinicius Costa Gomesda85e5e2011-06-09 18:50:53 -03001046 reason = smp_cmd_security_req(conn, skb);
Anderson Briglia88ba43b2011-06-09 18:50:42 -03001047 break;
1048
Anderson Brigliaeb492e02011-06-09 18:50:40 -03001049 case SMP_CMD_PAIRING_CONFIRM:
Vinicius Costa Gomesda85e5e2011-06-09 18:50:53 -03001050 reason = smp_cmd_pairing_confirm(conn, skb);
Anderson Briglia88ba43b2011-06-09 18:50:42 -03001051 break;
1052
Anderson Brigliaeb492e02011-06-09 18:50:40 -03001053 case SMP_CMD_PAIRING_RANDOM:
Vinicius Costa Gomesda85e5e2011-06-09 18:50:53 -03001054 reason = smp_cmd_pairing_random(conn, skb);
Anderson Briglia88ba43b2011-06-09 18:50:42 -03001055 break;
1056
Anderson Brigliaeb492e02011-06-09 18:50:40 -03001057 case SMP_CMD_ENCRYPT_INFO:
Vinicius Costa Gomes7034b912011-07-07 18:59:34 -03001058 reason = smp_cmd_encrypt_info(conn, skb);
1059 break;
1060
Anderson Brigliaeb492e02011-06-09 18:50:40 -03001061 case SMP_CMD_MASTER_IDENT:
Vinicius Costa Gomes7034b912011-07-07 18:59:34 -03001062 reason = smp_cmd_master_ident(conn, skb);
1063 break;
1064
Anderson Brigliaeb492e02011-06-09 18:50:40 -03001065 case SMP_CMD_IDENT_INFO:
Johan Hedbergfd349c02014-02-18 10:19:36 +02001066 reason = smp_cmd_ident_info(conn, skb);
1067 break;
1068
Anderson Brigliaeb492e02011-06-09 18:50:40 -03001069 case SMP_CMD_IDENT_ADDR_INFO:
Johan Hedbergfd349c02014-02-18 10:19:36 +02001070 reason = smp_cmd_ident_addr_info(conn, skb);
1071 break;
1072
Anderson Brigliaeb492e02011-06-09 18:50:40 -03001073 case SMP_CMD_SIGN_INFO:
Vinicius Costa Gomes7034b912011-07-07 18:59:34 -03001074 /* Just ignored */
1075 reason = 0;
1076 break;
1077
Anderson Brigliaeb492e02011-06-09 18:50:40 -03001078 default:
1079 BT_DBG("Unknown command code 0x%2.2x", code);
1080
1081 reason = SMP_CMD_NOTSUPP;
Vinicius Costa Gomes3a0259b2011-06-09 18:50:43 -03001082 err = -EOPNOTSUPP;
1083 goto done;
1084 }
1085
1086done:
1087 if (reason)
Johan Hedberg84794e12013-11-06 11:24:57 +02001088 smp_failure(conn, reason);
Anderson Brigliaeb492e02011-06-09 18:50:40 -03001089
1090 kfree_skb(skb);
1091 return err;
1092}
Vinicius Costa Gomes7034b912011-07-07 18:59:34 -03001093
1094int smp_distribute_keys(struct l2cap_conn *conn, __u8 force)
1095{
1096 struct smp_cmd_pairing *req, *rsp;
Vinicius Costa Gomes1c1def02011-09-05 14:31:30 -03001097 struct smp_chan *smp = conn->smp_chan;
Vinicius Costa Gomes7034b912011-07-07 18:59:34 -03001098 __u8 *keydist;
1099
1100 BT_DBG("conn %p force %d", conn, force);
1101
Johan Hedberg51a8efd2012-01-16 06:10:31 +02001102 if (!test_bit(HCI_CONN_LE_SMP_PEND, &conn->hcon->flags))
Vinicius Costa Gomesd26a2342011-08-19 21:06:51 -03001103 return 0;
1104
Vinicius Costa Gomes1c1def02011-09-05 14:31:30 -03001105 rsp = (void *) &smp->prsp[1];
Vinicius Costa Gomes7034b912011-07-07 18:59:34 -03001106
1107 /* The responder sends its keys first */
1108 if (!force && conn->hcon->out && (rsp->resp_key_dist & 0x07))
1109 return 0;
1110
Vinicius Costa Gomes1c1def02011-09-05 14:31:30 -03001111 req = (void *) &smp->preq[1];
Vinicius Costa Gomes7034b912011-07-07 18:59:34 -03001112
1113 if (conn->hcon->out) {
1114 keydist = &rsp->init_key_dist;
1115 *keydist &= req->init_key_dist;
1116 } else {
1117 keydist = &rsp->resp_key_dist;
1118 *keydist &= req->resp_key_dist;
1119 }
1120
Vinicius Costa Gomes7034b912011-07-07 18:59:34 -03001121 BT_DBG("keydist 0x%x", *keydist);
1122
1123 if (*keydist & SMP_DIST_ENC_KEY) {
1124 struct smp_cmd_encrypt_info enc;
1125 struct smp_cmd_master_ident ident;
Vinicius Costa Gomesc9839a12012-02-02 21:08:01 -03001126 struct hci_conn *hcon = conn->hcon;
1127 u8 authenticated;
Vinicius Costa Gomes7034b912011-07-07 18:59:34 -03001128 __le16 ediv;
1129
1130 get_random_bytes(enc.ltk, sizeof(enc.ltk));
1131 get_random_bytes(&ediv, sizeof(ediv));
1132 get_random_bytes(ident.rand, sizeof(ident.rand));
1133
1134 smp_send_cmd(conn, SMP_CMD_ENCRYPT_INFO, sizeof(enc), &enc);
1135
Vinicius Costa Gomesc9839a12012-02-02 21:08:01 -03001136 authenticated = hcon->sec_level == BT_SECURITY_HIGH;
Marcel Holtmannce39fb42013-10-13 02:23:39 -07001137 hci_add_ltk(hcon->hdev, &hcon->dst, hcon->dst_type,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001138 HCI_SMP_LTK_SLAVE, 1, authenticated,
1139 enc.ltk, smp->enc_key_size, ediv, ident.rand);
Vinicius Costa Gomes16b90832011-07-07 18:59:39 -03001140
Andrei Emeltchenko58115372012-03-12 12:13:06 +02001141 ident.ediv = ediv;
Vinicius Costa Gomes7034b912011-07-07 18:59:34 -03001142
1143 smp_send_cmd(conn, SMP_CMD_MASTER_IDENT, sizeof(ident), &ident);
1144
1145 *keydist &= ~SMP_DIST_ENC_KEY;
1146 }
1147
1148 if (*keydist & SMP_DIST_ID_KEY) {
1149 struct smp_cmd_ident_addr_info addrinfo;
1150 struct smp_cmd_ident_info idinfo;
1151
1152 /* Send a dummy key */
1153 get_random_bytes(idinfo.irk, sizeof(idinfo.irk));
1154
1155 smp_send_cmd(conn, SMP_CMD_IDENT_INFO, sizeof(idinfo), &idinfo);
1156
1157 /* Just public address */
1158 memset(&addrinfo, 0, sizeof(addrinfo));
Marcel Holtmann2b36a562013-10-13 05:24:00 -07001159 bacpy(&addrinfo.bdaddr, &conn->hcon->src);
Vinicius Costa Gomes7034b912011-07-07 18:59:34 -03001160
1161 smp_send_cmd(conn, SMP_CMD_IDENT_ADDR_INFO, sizeof(addrinfo),
Marcel Holtmannf1560462013-10-13 05:43:25 -07001162 &addrinfo);
Vinicius Costa Gomes7034b912011-07-07 18:59:34 -03001163
1164 *keydist &= ~SMP_DIST_ID_KEY;
1165 }
1166
1167 if (*keydist & SMP_DIST_SIGN) {
1168 struct smp_cmd_sign_info sign;
1169
1170 /* Send a dummy key */
1171 get_random_bytes(sign.csrk, sizeof(sign.csrk));
1172
1173 smp_send_cmd(conn, SMP_CMD_SIGN_INFO, sizeof(sign), &sign);
1174
1175 *keydist &= ~SMP_DIST_SIGN;
1176 }
1177
Vinicius Costa Gomesd26a2342011-08-19 21:06:51 -03001178 if (conn->hcon->out || force) {
Johan Hedberg51a8efd2012-01-16 06:10:31 +02001179 clear_bit(HCI_CONN_LE_SMP_PEND, &conn->hcon->flags);
Gustavo F. Padovan6c9d42a2011-12-20 10:57:27 -02001180 cancel_delayed_work_sync(&conn->security_timer);
Vinicius Costa Gomes8aab4752011-09-05 14:31:31 -03001181 smp_chan_destroy(conn);
Vinicius Costa Gomesd26a2342011-08-19 21:06:51 -03001182 }
1183
Vinicius Costa Gomes7034b912011-07-07 18:59:34 -03001184 return 0;
1185}