blob: 1730bb2b625941bda49bd5b76734ef01aed8a0b8 [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
81static int smp_c1(struct crypto_blkcipher *tfm, u8 k[16], u8 r[16],
Marcel Holtmannf1560462013-10-13 05:43:25 -070082 u8 preq[7], u8 pres[7], u8 _iat, bdaddr_t *ia,
83 u8 _rat, bdaddr_t *ra, u8 res[16])
Anderson Brigliad22ef0b2011-06-09 18:50:44 -030084{
85 u8 p1[16], p2[16];
86 int err;
87
88 memset(p1, 0, 16);
89
90 /* p1 = pres || preq || _rat || _iat */
91 swap56(pres, p1);
92 swap56(preq, p1 + 7);
93 p1[14] = _rat;
94 p1[15] = _iat;
95
96 memset(p2, 0, 16);
97
98 /* p2 = padding || ia || ra */
99 baswap((bdaddr_t *) (p2 + 4), ia);
100 baswap((bdaddr_t *) (p2 + 10), ra);
101
102 /* res = r XOR p1 */
103 u128_xor((u128 *) res, (u128 *) r, (u128 *) p1);
104
105 /* res = e(k, res) */
106 err = smp_e(tfm, k, res);
107 if (err) {
108 BT_ERR("Encrypt data error");
109 return err;
110 }
111
112 /* res = res XOR p2 */
113 u128_xor((u128 *) res, (u128 *) res, (u128 *) p2);
114
115 /* res = e(k, res) */
116 err = smp_e(tfm, k, res);
117 if (err)
118 BT_ERR("Encrypt data error");
119
120 return err;
121}
122
Marcel Holtmannf1560462013-10-13 05:43:25 -0700123static int smp_s1(struct crypto_blkcipher *tfm, u8 k[16], u8 r1[16],
124 u8 r2[16], u8 _r[16])
Anderson Brigliad22ef0b2011-06-09 18:50:44 -0300125{
126 int err;
127
128 /* Just least significant octets from r1 and r2 are considered */
129 memcpy(_r, r1 + 8, 8);
130 memcpy(_r + 8, r2 + 8, 8);
131
132 err = smp_e(tfm, k, _r);
133 if (err)
134 BT_ERR("Encrypt data error");
135
136 return err;
137}
138
Anderson Brigliaeb492e02011-06-09 18:50:40 -0300139static struct sk_buff *smp_build_cmd(struct l2cap_conn *conn, u8 code,
Marcel Holtmannf1560462013-10-13 05:43:25 -0700140 u16 dlen, void *data)
Anderson Brigliaeb492e02011-06-09 18:50:40 -0300141{
142 struct sk_buff *skb;
143 struct l2cap_hdr *lh;
144 int len;
145
146 len = L2CAP_HDR_SIZE + sizeof(code) + dlen;
147
148 if (len > conn->mtu)
149 return NULL;
150
151 skb = bt_skb_alloc(len, GFP_ATOMIC);
152 if (!skb)
153 return NULL;
154
155 lh = (struct l2cap_hdr *) skb_put(skb, L2CAP_HDR_SIZE);
156 lh->len = cpu_to_le16(sizeof(code) + dlen);
Syam Sidhardhand8aece22012-10-10 22:09:28 +0530157 lh->cid = __constant_cpu_to_le16(L2CAP_CID_SMP);
Anderson Brigliaeb492e02011-06-09 18:50:40 -0300158
159 memcpy(skb_put(skb, sizeof(code)), &code, sizeof(code));
160
161 memcpy(skb_put(skb, dlen), data, dlen);
162
163 return skb;
164}
165
166static void smp_send_cmd(struct l2cap_conn *conn, u8 code, u16 len, void *data)
167{
168 struct sk_buff *skb = smp_build_cmd(conn, code, len, data);
169
170 BT_DBG("code 0x%2.2x", code);
171
172 if (!skb)
173 return;
174
Luiz Augusto von Dentz73d80de2011-11-02 15:52:01 +0200175 skb->priority = HCI_PRIO_MAX;
176 hci_send_acl(conn->hchan, skb, 0);
Vinicius Costa Gomese2dcd112011-08-19 21:06:50 -0300177
Gustavo F. Padovan6c9d42a2011-12-20 10:57:27 -0200178 cancel_delayed_work_sync(&conn->security_timer);
Marcel Holtmann17b02e62012-03-01 14:32:37 -0800179 schedule_delayed_work(&conn->security_timer, SMP_TIMEOUT);
Anderson Brigliaeb492e02011-06-09 18:50:40 -0300180}
181
Brian Gix2b64d152011-12-21 16:12:12 -0800182static __u8 authreq_to_seclevel(__u8 authreq)
183{
184 if (authreq & SMP_AUTH_MITM)
185 return BT_SECURITY_HIGH;
186 else
187 return BT_SECURITY_MEDIUM;
188}
189
190static __u8 seclevel_to_authreq(__u8 sec_level)
191{
192 switch (sec_level) {
193 case BT_SECURITY_HIGH:
194 return SMP_AUTH_MITM | SMP_AUTH_BONDING;
195 case BT_SECURITY_MEDIUM:
196 return SMP_AUTH_BONDING;
197 default:
198 return SMP_AUTH_NONE;
199 }
200}
201
Vinicius Costa Gomesb8e66ea2011-06-09 18:50:52 -0300202static void build_pairing_cmd(struct l2cap_conn *conn,
Marcel Holtmannf1560462013-10-13 05:43:25 -0700203 struct smp_cmd_pairing *req,
204 struct smp_cmd_pairing *rsp, __u8 authreq)
Vinicius Costa Gomesb8e66ea2011-06-09 18:50:52 -0300205{
Brian Gix2b64d152011-12-21 16:12:12 -0800206 u8 dist_keys = 0;
Vinicius Costa Gomes54790f72011-07-07 18:59:38 -0300207
Johan Hedberga8b2d5c2012-01-08 23:11:15 +0200208 if (test_bit(HCI_PAIRABLE, &conn->hcon->hdev->dev_flags)) {
Vinicius Costa Gomesca10b5e2011-08-25 20:02:37 -0300209 dist_keys = SMP_DIST_ENC_KEY;
Vinicius Costa Gomes54790f72011-07-07 18:59:38 -0300210 authreq |= SMP_AUTH_BONDING;
Brian Gix2b64d152011-12-21 16:12:12 -0800211 } else {
212 authreq &= ~SMP_AUTH_BONDING;
Vinicius Costa Gomes54790f72011-07-07 18:59:38 -0300213 }
214
215 if (rsp == NULL) {
216 req->io_capability = conn->hcon->io_capability;
217 req->oob_flag = SMP_OOB_NOT_PRESENT;
218 req->max_key_size = SMP_MAX_ENC_KEY_SIZE;
Johan Hedberg0cf73b92014-01-29 13:55:59 -0800219 req->init_key_dist = dist_keys;
Vinicius Costa Gomes54790f72011-07-07 18:59:38 -0300220 req->resp_key_dist = dist_keys;
Johan Hedberg065a13e2012-10-11 16:26:06 +0200221 req->auth_req = (authreq & AUTH_REQ_MASK);
Vinicius Costa Gomes54790f72011-07-07 18:59:38 -0300222 return;
223 }
224
225 rsp->io_capability = conn->hcon->io_capability;
226 rsp->oob_flag = SMP_OOB_NOT_PRESENT;
227 rsp->max_key_size = SMP_MAX_ENC_KEY_SIZE;
Johan Hedberg0cf73b92014-01-29 13:55:59 -0800228 rsp->init_key_dist = req->init_key_dist & dist_keys;
Vinicius Costa Gomes54790f72011-07-07 18:59:38 -0300229 rsp->resp_key_dist = req->resp_key_dist & dist_keys;
Johan Hedberg065a13e2012-10-11 16:26:06 +0200230 rsp->auth_req = (authreq & AUTH_REQ_MASK);
Vinicius Costa Gomesb8e66ea2011-06-09 18:50:52 -0300231}
232
Vinicius Costa Gomes3158c502011-06-14 13:37:42 -0300233static u8 check_enc_key_size(struct l2cap_conn *conn, __u8 max_key_size)
234{
Vinicius Costa Gomes1c1def02011-09-05 14:31:30 -0300235 struct smp_chan *smp = conn->smp_chan;
236
Vinicius Costa Gomes3158c502011-06-14 13:37:42 -0300237 if ((max_key_size > SMP_MAX_ENC_KEY_SIZE) ||
Marcel Holtmannf1560462013-10-13 05:43:25 -0700238 (max_key_size < SMP_MIN_ENC_KEY_SIZE))
Vinicius Costa Gomes3158c502011-06-14 13:37:42 -0300239 return SMP_ENC_KEY_SIZE;
240
Vinicius Costa Gomesf7aa6112012-01-30 19:29:12 -0300241 smp->enc_key_size = max_key_size;
Vinicius Costa Gomes3158c502011-06-14 13:37:42 -0300242
243 return 0;
244}
245
Johan Hedberg84794e12013-11-06 11:24:57 +0200246static void smp_failure(struct l2cap_conn *conn, u8 reason)
Brian Gix4f957a72011-11-23 08:28:36 -0800247{
Johan Hedbergbab73cb2012-02-09 16:07:29 +0200248 struct hci_conn *hcon = conn->hcon;
249
Johan Hedberg84794e12013-11-06 11:24:57 +0200250 if (reason)
Brian Gix4f957a72011-11-23 08:28:36 -0800251 smp_send_cmd(conn, SMP_CMD_PAIRING_FAIL, sizeof(reason),
Marcel Holtmannf1560462013-10-13 05:43:25 -0700252 &reason);
Brian Gix4f957a72011-11-23 08:28:36 -0800253
Marcel Holtmannce39fb42013-10-13 02:23:39 -0700254 clear_bit(HCI_CONN_ENCRYPT_PEND, &hcon->flags);
255 mgmt_auth_failed(hcon->hdev, &hcon->dst, hcon->type, hcon->dst_type,
256 HCI_ERROR_AUTH_FAILURE);
Vinicius Costa Gomesf1c09c02012-02-01 18:27:56 -0300257
Andre Guedes61a0cfb2012-08-01 20:34:15 -0300258 cancel_delayed_work_sync(&conn->security_timer);
259
Marcel Holtmannce39fb42013-10-13 02:23:39 -0700260 if (test_and_clear_bit(HCI_CONN_LE_SMP_PEND, &hcon->flags))
Vinicius Costa Gomesf1c09c02012-02-01 18:27:56 -0300261 smp_chan_destroy(conn);
Brian Gix4f957a72011-11-23 08:28:36 -0800262}
263
Brian Gix2b64d152011-12-21 16:12:12 -0800264#define JUST_WORKS 0x00
265#define JUST_CFM 0x01
266#define REQ_PASSKEY 0x02
267#define CFM_PASSKEY 0x03
268#define REQ_OOB 0x04
269#define OVERLAP 0xFF
270
271static const u8 gen_method[5][5] = {
272 { JUST_WORKS, JUST_CFM, REQ_PASSKEY, JUST_WORKS, REQ_PASSKEY },
273 { JUST_WORKS, JUST_CFM, REQ_PASSKEY, JUST_WORKS, REQ_PASSKEY },
274 { CFM_PASSKEY, CFM_PASSKEY, REQ_PASSKEY, JUST_WORKS, CFM_PASSKEY },
275 { JUST_WORKS, JUST_CFM, JUST_WORKS, JUST_WORKS, JUST_CFM },
276 { CFM_PASSKEY, CFM_PASSKEY, REQ_PASSKEY, JUST_WORKS, OVERLAP },
277};
278
279static int tk_request(struct l2cap_conn *conn, u8 remote_oob, u8 auth,
280 u8 local_io, u8 remote_io)
281{
282 struct hci_conn *hcon = conn->hcon;
283 struct smp_chan *smp = conn->smp_chan;
284 u8 method;
285 u32 passkey = 0;
286 int ret = 0;
287
288 /* Initialize key for JUST WORKS */
289 memset(smp->tk, 0, sizeof(smp->tk));
290 clear_bit(SMP_FLAG_TK_VALID, &smp->smp_flags);
291
292 BT_DBG("tk_request: auth:%d lcl:%d rem:%d", auth, local_io, remote_io);
293
294 /* If neither side wants MITM, use JUST WORKS */
295 /* If either side has unknown io_caps, use JUST WORKS */
296 /* Otherwise, look up method from the table */
297 if (!(auth & SMP_AUTH_MITM) ||
Marcel Holtmannf1560462013-10-13 05:43:25 -0700298 local_io > SMP_IO_KEYBOARD_DISPLAY ||
299 remote_io > SMP_IO_KEYBOARD_DISPLAY)
Brian Gix2b64d152011-12-21 16:12:12 -0800300 method = JUST_WORKS;
301 else
Ido Yarivb3ff53f2012-03-05 20:07:08 +0200302 method = gen_method[remote_io][local_io];
Brian Gix2b64d152011-12-21 16:12:12 -0800303
304 /* If not bonding, don't ask user to confirm a Zero TK */
305 if (!(auth & SMP_AUTH_BONDING) && method == JUST_CFM)
306 method = JUST_WORKS;
307
308 /* If Just Works, Continue with Zero TK */
309 if (method == JUST_WORKS) {
310 set_bit(SMP_FLAG_TK_VALID, &smp->smp_flags);
311 return 0;
312 }
313
314 /* Not Just Works/Confirm results in MITM Authentication */
315 if (method != JUST_CFM)
316 set_bit(SMP_FLAG_MITM_AUTH, &smp->smp_flags);
317
318 /* If both devices have Keyoard-Display I/O, the master
319 * Confirms and the slave Enters the passkey.
320 */
321 if (method == OVERLAP) {
322 if (hcon->link_mode & HCI_LM_MASTER)
323 method = CFM_PASSKEY;
324 else
325 method = REQ_PASSKEY;
326 }
327
328 /* Generate random passkey. Not valid until confirmed. */
329 if (method == CFM_PASSKEY) {
330 u8 key[16];
331
332 memset(key, 0, sizeof(key));
333 get_random_bytes(&passkey, sizeof(passkey));
334 passkey %= 1000000;
335 put_unaligned_le32(passkey, key);
336 swap128(key, smp->tk);
337 BT_DBG("PassKey: %d", passkey);
338 }
339
340 hci_dev_lock(hcon->hdev);
341
342 if (method == REQ_PASSKEY)
Marcel Holtmannce39fb42013-10-13 02:23:39 -0700343 ret = mgmt_user_passkey_request(hcon->hdev, &hcon->dst,
Johan Hedberg272d90d2012-02-09 15:26:12 +0200344 hcon->type, hcon->dst_type);
Brian Gix2b64d152011-12-21 16:12:12 -0800345 else
Marcel Holtmannce39fb42013-10-13 02:23:39 -0700346 ret = mgmt_user_confirm_request(hcon->hdev, &hcon->dst,
Johan Hedberg272d90d2012-02-09 15:26:12 +0200347 hcon->type, hcon->dst_type,
Brian Gix2b64d152011-12-21 16:12:12 -0800348 cpu_to_le32(passkey), 0);
349
350 hci_dev_unlock(hcon->hdev);
351
352 return ret;
353}
354
Vinicius Costa Gomes8aab4752011-09-05 14:31:31 -0300355static void confirm_work(struct work_struct *work)
356{
357 struct smp_chan *smp = container_of(work, struct smp_chan, confirm);
358 struct l2cap_conn *conn = smp->conn;
359 struct crypto_blkcipher *tfm;
360 struct smp_cmd_pairing_confirm cp;
361 int ret;
362 u8 res[16], reason;
363
364 BT_DBG("conn %p", conn);
365
366 tfm = crypto_alloc_blkcipher("ecb(aes)", 0, CRYPTO_ALG_ASYNC);
367 if (IS_ERR(tfm)) {
368 reason = SMP_UNSPECIFIED;
369 goto error;
370 }
371
372 smp->tfm = tfm;
373
374 if (conn->hcon->out)
Marcel Holtmannc8462ca2013-10-13 05:24:02 -0700375 ret = smp_c1(tfm, smp->tk, smp->prnd, smp->preq, smp->prsp,
376 conn->hcon->src_type, &conn->hcon->src,
377 conn->hcon->dst_type, &conn->hcon->dst, res);
Vinicius Costa Gomes8aab4752011-09-05 14:31:31 -0300378 else
379 ret = smp_c1(tfm, smp->tk, smp->prnd, smp->preq, smp->prsp,
Marcel Holtmannc8462ca2013-10-13 05:24:02 -0700380 conn->hcon->dst_type, &conn->hcon->dst,
381 conn->hcon->src_type, &conn->hcon->src, res);
Vinicius Costa Gomes8aab4752011-09-05 14:31:31 -0300382 if (ret) {
383 reason = SMP_UNSPECIFIED;
384 goto error;
385 }
386
Brian Gix2b64d152011-12-21 16:12:12 -0800387 clear_bit(SMP_FLAG_CFM_PENDING, &smp->smp_flags);
388
Vinicius Costa Gomes8aab4752011-09-05 14:31:31 -0300389 swap128(res, cp.confirm_val);
390 smp_send_cmd(smp->conn, SMP_CMD_PAIRING_CONFIRM, sizeof(cp), &cp);
391
392 return;
393
394error:
Johan Hedberg84794e12013-11-06 11:24:57 +0200395 smp_failure(conn, reason);
Vinicius Costa Gomes8aab4752011-09-05 14:31:31 -0300396}
397
398static void random_work(struct work_struct *work)
399{
400 struct smp_chan *smp = container_of(work, struct smp_chan, random);
401 struct l2cap_conn *conn = smp->conn;
402 struct hci_conn *hcon = conn->hcon;
403 struct crypto_blkcipher *tfm = smp->tfm;
404 u8 reason, confirm[16], res[16], key[16];
405 int ret;
406
407 if (IS_ERR_OR_NULL(tfm)) {
408 reason = SMP_UNSPECIFIED;
409 goto error;
410 }
411
412 BT_DBG("conn %p %s", conn, conn->hcon->out ? "master" : "slave");
413
414 if (hcon->out)
Marcel Holtmannc8462ca2013-10-13 05:24:02 -0700415 ret = smp_c1(tfm, smp->tk, smp->rrnd, smp->preq, smp->prsp,
416 hcon->src_type, &hcon->src,
417 hcon->dst_type, &hcon->dst, res);
Vinicius Costa Gomes8aab4752011-09-05 14:31:31 -0300418 else
419 ret = smp_c1(tfm, smp->tk, smp->rrnd, smp->preq, smp->prsp,
Marcel Holtmannc8462ca2013-10-13 05:24:02 -0700420 hcon->dst_type, &hcon->dst,
421 hcon->src_type, &hcon->src, res);
Vinicius Costa Gomes8aab4752011-09-05 14:31:31 -0300422 if (ret) {
423 reason = SMP_UNSPECIFIED;
424 goto error;
425 }
426
427 swap128(res, confirm);
428
429 if (memcmp(smp->pcnf, confirm, sizeof(smp->pcnf)) != 0) {
430 BT_ERR("Pairing failed (confirmation values mismatch)");
431 reason = SMP_CONFIRM_FAILED;
432 goto error;
433 }
434
435 if (hcon->out) {
436 u8 stk[16], rand[8];
437 __le16 ediv;
438
439 memset(rand, 0, sizeof(rand));
440 ediv = 0;
441
442 smp_s1(tfm, smp->tk, smp->rrnd, smp->prnd, key);
443 swap128(key, stk);
444
Vinicius Costa Gomesf7aa6112012-01-30 19:29:12 -0300445 memset(stk + smp->enc_key_size, 0,
Gustavo F. Padovan04124682012-03-08 01:25:00 -0300446 SMP_MAX_ENC_KEY_SIZE - smp->enc_key_size);
Vinicius Costa Gomes8aab4752011-09-05 14:31:31 -0300447
Johan Hedberg51a8efd2012-01-16 06:10:31 +0200448 if (test_and_set_bit(HCI_CONN_ENCRYPT_PEND, &hcon->flags)) {
Vinicius Costa Gomes8aab4752011-09-05 14:31:31 -0300449 reason = SMP_UNSPECIFIED;
450 goto error;
451 }
452
453 hci_le_start_enc(hcon, ediv, rand, stk);
Vinicius Costa Gomesf7aa6112012-01-30 19:29:12 -0300454 hcon->enc_key_size = smp->enc_key_size;
Vinicius Costa Gomes8aab4752011-09-05 14:31:31 -0300455 } else {
456 u8 stk[16], r[16], rand[8];
457 __le16 ediv;
458
459 memset(rand, 0, sizeof(rand));
460 ediv = 0;
461
462 swap128(smp->prnd, r);
463 smp_send_cmd(conn, SMP_CMD_PAIRING_RANDOM, sizeof(r), r);
464
465 smp_s1(tfm, smp->tk, smp->prnd, smp->rrnd, key);
466 swap128(key, stk);
467
Vinicius Costa Gomesf7aa6112012-01-30 19:29:12 -0300468 memset(stk + smp->enc_key_size, 0,
Marcel Holtmannf1560462013-10-13 05:43:25 -0700469 SMP_MAX_ENC_KEY_SIZE - smp->enc_key_size);
Vinicius Costa Gomes8aab4752011-09-05 14:31:31 -0300470
Marcel Holtmannce39fb42013-10-13 02:23:39 -0700471 hci_add_ltk(hcon->hdev, &hcon->dst, hcon->dst_type,
Gustavo F. Padovan04124682012-03-08 01:25:00 -0300472 HCI_SMP_STK_SLAVE, 0, 0, stk, smp->enc_key_size,
473 ediv, rand);
Vinicius Costa Gomes8aab4752011-09-05 14:31:31 -0300474 }
475
476 return;
477
478error:
Johan Hedberg84794e12013-11-06 11:24:57 +0200479 smp_failure(conn, reason);
Vinicius Costa Gomes8aab4752011-09-05 14:31:31 -0300480}
481
482static struct smp_chan *smp_chan_create(struct l2cap_conn *conn)
483{
484 struct smp_chan *smp;
485
Marcel Holtmannf1560462013-10-13 05:43:25 -0700486 smp = kzalloc(sizeof(*smp), GFP_ATOMIC);
Vinicius Costa Gomes8aab4752011-09-05 14:31:31 -0300487 if (!smp)
488 return NULL;
489
490 INIT_WORK(&smp->confirm, confirm_work);
491 INIT_WORK(&smp->random, random_work);
492
493 smp->conn = conn;
494 conn->smp_chan = smp;
Brian Gix2b64d152011-12-21 16:12:12 -0800495 conn->hcon->smp_conn = conn;
Vinicius Costa Gomes8aab4752011-09-05 14:31:31 -0300496
497 hci_conn_hold(conn->hcon);
498
499 return smp;
500}
501
502void smp_chan_destroy(struct l2cap_conn *conn)
503{
Brian Gixc8eb9692011-11-23 08:28:35 -0800504 struct smp_chan *smp = conn->smp_chan;
505
Vinicius Costa Gomesf1c09c02012-02-01 18:27:56 -0300506 BUG_ON(!smp);
Brian Gixc8eb9692011-11-23 08:28:35 -0800507
508 if (smp->tfm)
509 crypto_free_blkcipher(smp->tfm);
510
511 kfree(smp);
512 conn->smp_chan = NULL;
Brian Gix2b64d152011-12-21 16:12:12 -0800513 conn->hcon->smp_conn = NULL;
David Herrmann76a68ba2013-04-06 20:28:37 +0200514 hci_conn_drop(conn->hcon);
Vinicius Costa Gomes8aab4752011-09-05 14:31:31 -0300515}
516
Brian Gix2b64d152011-12-21 16:12:12 -0800517int smp_user_confirm_reply(struct hci_conn *hcon, u16 mgmt_op, __le32 passkey)
518{
519 struct l2cap_conn *conn = hcon->smp_conn;
520 struct smp_chan *smp;
521 u32 value;
522 u8 key[16];
523
524 BT_DBG("");
525
526 if (!conn)
527 return -ENOTCONN;
528
529 smp = conn->smp_chan;
530
531 switch (mgmt_op) {
532 case MGMT_OP_USER_PASSKEY_REPLY:
533 value = le32_to_cpu(passkey);
534 memset(key, 0, sizeof(key));
535 BT_DBG("PassKey: %d", value);
536 put_unaligned_le32(value, key);
537 swap128(key, smp->tk);
538 /* Fall Through */
539 case MGMT_OP_USER_CONFIRM_REPLY:
540 set_bit(SMP_FLAG_TK_VALID, &smp->smp_flags);
541 break;
542 case MGMT_OP_USER_PASSKEY_NEG_REPLY:
543 case MGMT_OP_USER_CONFIRM_NEG_REPLY:
Johan Hedberg84794e12013-11-06 11:24:57 +0200544 smp_failure(conn, SMP_PASSKEY_ENTRY_FAILED);
Brian Gix2b64d152011-12-21 16:12:12 -0800545 return 0;
546 default:
Johan Hedberg84794e12013-11-06 11:24:57 +0200547 smp_failure(conn, SMP_PASSKEY_ENTRY_FAILED);
Brian Gix2b64d152011-12-21 16:12:12 -0800548 return -EOPNOTSUPP;
549 }
550
551 /* If it is our turn to send Pairing Confirm, do so now */
552 if (test_bit(SMP_FLAG_CFM_PENDING, &smp->smp_flags))
553 queue_work(hcon->hdev->workqueue, &smp->confirm);
554
555 return 0;
556}
557
Vinicius Costa Gomesda85e5e2011-06-09 18:50:53 -0300558static u8 smp_cmd_pairing_req(struct l2cap_conn *conn, struct sk_buff *skb)
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300559{
Vinicius Costa Gomes3158c502011-06-14 13:37:42 -0300560 struct smp_cmd_pairing rsp, *req = (void *) skb->data;
Vinicius Costa Gomes8aab4752011-09-05 14:31:31 -0300561 struct smp_chan *smp;
Vinicius Costa Gomes3158c502011-06-14 13:37:42 -0300562 u8 key_size;
Brian Gix2b64d152011-12-21 16:12:12 -0800563 u8 auth = SMP_AUTH_NONE;
Vinicius Costa Gomes8aab4752011-09-05 14:31:31 -0300564 int ret;
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300565
566 BT_DBG("conn %p", conn);
567
Johan Hedbergc46b98b2014-02-18 10:19:29 +0200568 if (skb->len < sizeof(*req))
569 return SMP_UNSPECIFIED;
570
Brian Gix2b64d152011-12-21 16:12:12 -0800571 if (conn->hcon->link_mode & HCI_LM_MASTER)
572 return SMP_CMD_NOTSUPP;
573
Johan Hedberg51a8efd2012-01-16 06:10:31 +0200574 if (!test_and_set_bit(HCI_CONN_LE_SMP_PEND, &conn->hcon->flags))
Vinicius Costa Gomes8aab4752011-09-05 14:31:31 -0300575 smp = smp_chan_create(conn);
Andrei Emeltchenkod08fd0e2012-07-19 17:03:43 +0300576 else
577 smp = conn->smp_chan;
Vinicius Costa Gomes8aab4752011-09-05 14:31:31 -0300578
Andrei Emeltchenkod08fd0e2012-07-19 17:03:43 +0300579 if (!smp)
580 return SMP_UNSPECIFIED;
Vinicius Costa Gomesd26a2342011-08-19 21:06:51 -0300581
Vinicius Costa Gomes1c1def02011-09-05 14:31:30 -0300582 smp->preq[0] = SMP_CMD_PAIRING_REQ;
583 memcpy(&smp->preq[1], req, sizeof(*req));
Vinicius Costa Gomes3158c502011-06-14 13:37:42 -0300584 skb_pull(skb, sizeof(*req));
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300585
Brian Gix2b64d152011-12-21 16:12:12 -0800586 /* We didn't start the pairing, so match remote */
587 if (req->auth_req & SMP_AUTH_BONDING)
588 auth = req->auth_req;
Vinicius Costa Gomesda85e5e2011-06-09 18:50:53 -0300589
Ido Yarivfdde0a22012-03-05 20:09:38 +0200590 conn->hcon->pending_sec_level = authreq_to_seclevel(auth);
591
Brian Gix2b64d152011-12-21 16:12:12 -0800592 build_pairing_cmd(conn, req, &rsp, auth);
Vinicius Costa Gomes3158c502011-06-14 13:37:42 -0300593
594 key_size = min(req->max_key_size, rsp.max_key_size);
595 if (check_enc_key_size(conn, key_size))
596 return SMP_ENC_KEY_SIZE;
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300597
Johan Hedberge84a6b12013-12-02 10:49:03 +0200598 get_random_bytes(smp->prnd, sizeof(smp->prnd));
Vinicius Costa Gomes8aab4752011-09-05 14:31:31 -0300599
Vinicius Costa Gomes1c1def02011-09-05 14:31:30 -0300600 smp->prsp[0] = SMP_CMD_PAIRING_RSP;
601 memcpy(&smp->prsp[1], &rsp, sizeof(rsp));
Anderson Brigliaf01ead32011-06-09 18:50:45 -0300602
Vinicius Costa Gomes3158c502011-06-14 13:37:42 -0300603 smp_send_cmd(conn, SMP_CMD_PAIRING_RSP, sizeof(rsp), &rsp);
Vinicius Costa Gomesda85e5e2011-06-09 18:50:53 -0300604
Brian Gix2b64d152011-12-21 16:12:12 -0800605 /* Request setup of TK */
606 ret = tk_request(conn, 0, auth, rsp.io_capability, req->io_capability);
607 if (ret)
608 return SMP_UNSPECIFIED;
609
Vinicius Costa Gomesda85e5e2011-06-09 18:50:53 -0300610 return 0;
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300611}
612
Vinicius Costa Gomesda85e5e2011-06-09 18:50:53 -0300613static u8 smp_cmd_pairing_rsp(struct l2cap_conn *conn, struct sk_buff *skb)
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300614{
Vinicius Costa Gomes3158c502011-06-14 13:37:42 -0300615 struct smp_cmd_pairing *req, *rsp = (void *) skb->data;
Vinicius Costa Gomes1c1def02011-09-05 14:31:30 -0300616 struct smp_chan *smp = conn->smp_chan;
Vinicius Costa Gomes8aab4752011-09-05 14:31:31 -0300617 struct hci_dev *hdev = conn->hcon->hdev;
Brian Gix2b64d152011-12-21 16:12:12 -0800618 u8 key_size, auth = SMP_AUTH_NONE;
Anderson Briglia7d24ddc2011-06-09 18:50:46 -0300619 int ret;
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300620
621 BT_DBG("conn %p", conn);
622
Johan Hedbergc46b98b2014-02-18 10:19:29 +0200623 if (skb->len < sizeof(*rsp))
624 return SMP_UNSPECIFIED;
625
Brian Gix2b64d152011-12-21 16:12:12 -0800626 if (!(conn->hcon->link_mode & HCI_LM_MASTER))
627 return SMP_CMD_NOTSUPP;
628
Vinicius Costa Gomes3158c502011-06-14 13:37:42 -0300629 skb_pull(skb, sizeof(*rsp));
Vinicius Costa Gomesda85e5e2011-06-09 18:50:53 -0300630
Vinicius Costa Gomes1c1def02011-09-05 14:31:30 -0300631 req = (void *) &smp->preq[1];
Vinicius Costa Gomes3158c502011-06-14 13:37:42 -0300632
633 key_size = min(req->max_key_size, rsp->max_key_size);
634 if (check_enc_key_size(conn, key_size))
635 return SMP_ENC_KEY_SIZE;
636
Johan Hedberge84a6b12013-12-02 10:49:03 +0200637 get_random_bytes(smp->prnd, sizeof(smp->prnd));
Anderson Briglia7d24ddc2011-06-09 18:50:46 -0300638
Vinicius Costa Gomes8aab4752011-09-05 14:31:31 -0300639 smp->prsp[0] = SMP_CMD_PAIRING_RSP;
640 memcpy(&smp->prsp[1], rsp, sizeof(*rsp));
Anderson Briglia7d24ddc2011-06-09 18:50:46 -0300641
Brian Gix2b64d152011-12-21 16:12:12 -0800642 if ((req->auth_req & SMP_AUTH_BONDING) &&
Marcel Holtmannf1560462013-10-13 05:43:25 -0700643 (rsp->auth_req & SMP_AUTH_BONDING))
Brian Gix2b64d152011-12-21 16:12:12 -0800644 auth = SMP_AUTH_BONDING;
645
646 auth |= (req->auth_req | rsp->auth_req) & SMP_AUTH_MITM;
647
Johan Hedberg476585e2012-06-06 18:54:15 +0800648 ret = tk_request(conn, 0, auth, req->io_capability, rsp->io_capability);
Brian Gix2b64d152011-12-21 16:12:12 -0800649 if (ret)
650 return SMP_UNSPECIFIED;
651
652 set_bit(SMP_FLAG_CFM_PENDING, &smp->smp_flags);
653
654 /* Can't compose response until we have been confirmed */
655 if (!test_bit(SMP_FLAG_TK_VALID, &smp->smp_flags))
656 return 0;
657
Vinicius Costa Gomes8aab4752011-09-05 14:31:31 -0300658 queue_work(hdev->workqueue, &smp->confirm);
Vinicius Costa Gomesda85e5e2011-06-09 18:50:53 -0300659
660 return 0;
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300661}
662
Vinicius Costa Gomesda85e5e2011-06-09 18:50:53 -0300663static u8 smp_cmd_pairing_confirm(struct l2cap_conn *conn, struct sk_buff *skb)
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300664{
Vinicius Costa Gomes1c1def02011-09-05 14:31:30 -0300665 struct smp_chan *smp = conn->smp_chan;
Vinicius Costa Gomes8aab4752011-09-05 14:31:31 -0300666 struct hci_dev *hdev = conn->hcon->hdev;
Anderson Briglia7d24ddc2011-06-09 18:50:46 -0300667
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300668 BT_DBG("conn %p %s", conn, conn->hcon->out ? "master" : "slave");
669
Johan Hedbergc46b98b2014-02-18 10:19:29 +0200670 if (skb->len < sizeof(smp->pcnf))
671 return SMP_UNSPECIFIED;
672
Vinicius Costa Gomes1c1def02011-09-05 14:31:30 -0300673 memcpy(smp->pcnf, skb->data, sizeof(smp->pcnf));
674 skb_pull(skb, sizeof(smp->pcnf));
Anderson Briglia7d24ddc2011-06-09 18:50:46 -0300675
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300676 if (conn->hcon->out) {
Anderson Briglia7d24ddc2011-06-09 18:50:46 -0300677 u8 random[16];
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300678
Vinicius Costa Gomes1c1def02011-09-05 14:31:30 -0300679 swap128(smp->prnd, random);
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300680 smp_send_cmd(conn, SMP_CMD_PAIRING_RANDOM, sizeof(random),
Marcel Holtmannf1560462013-10-13 05:43:25 -0700681 random);
Brian Gix2b64d152011-12-21 16:12:12 -0800682 } else if (test_bit(SMP_FLAG_TK_VALID, &smp->smp_flags)) {
Vinicius Costa Gomes8aab4752011-09-05 14:31:31 -0300683 queue_work(hdev->workqueue, &smp->confirm);
Brian Gix2b64d152011-12-21 16:12:12 -0800684 } else {
685 set_bit(SMP_FLAG_CFM_PENDING, &smp->smp_flags);
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300686 }
Vinicius Costa Gomesda85e5e2011-06-09 18:50:53 -0300687
688 return 0;
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300689}
690
Vinicius Costa Gomesda85e5e2011-06-09 18:50:53 -0300691static u8 smp_cmd_pairing_random(struct l2cap_conn *conn, struct sk_buff *skb)
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300692{
Vinicius Costa Gomes1c1def02011-09-05 14:31:30 -0300693 struct smp_chan *smp = conn->smp_chan;
Vinicius Costa Gomes8aab4752011-09-05 14:31:31 -0300694 struct hci_dev *hdev = conn->hcon->hdev;
Anderson Briglia7d24ddc2011-06-09 18:50:46 -0300695
Vinicius Costa Gomes8aab4752011-09-05 14:31:31 -0300696 BT_DBG("conn %p", conn);
Anderson Briglia7d24ddc2011-06-09 18:50:46 -0300697
Johan Hedbergc46b98b2014-02-18 10:19:29 +0200698 if (skb->len < sizeof(smp->rrnd))
699 return SMP_UNSPECIFIED;
700
Vinicius Costa Gomes8aab4752011-09-05 14:31:31 -0300701 swap128(skb->data, smp->rrnd);
702 skb_pull(skb, sizeof(smp->rrnd));
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300703
Vinicius Costa Gomes8aab4752011-09-05 14:31:31 -0300704 queue_work(hdev->workqueue, &smp->random);
Vinicius Costa Gomesda85e5e2011-06-09 18:50:53 -0300705
706 return 0;
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300707}
708
Johan Hedberg4dab7862012-06-07 14:58:37 +0800709static u8 smp_ltk_encrypt(struct l2cap_conn *conn, u8 sec_level)
Vinicius Costa Gomes988c5992011-08-25 20:02:28 -0300710{
Vinicius Costa Gomesc9839a12012-02-02 21:08:01 -0300711 struct smp_ltk *key;
Vinicius Costa Gomes988c5992011-08-25 20:02:28 -0300712 struct hci_conn *hcon = conn->hcon;
713
Johan Hedberg98a0b842014-01-30 19:40:00 -0800714 key = hci_find_ltk_by_addr(hcon->hdev, &hcon->dst, hcon->dst_type,
715 hcon->out);
Vinicius Costa Gomes988c5992011-08-25 20:02:28 -0300716 if (!key)
717 return 0;
718
Johan Hedberg4dab7862012-06-07 14:58:37 +0800719 if (sec_level > BT_SECURITY_MEDIUM && !key->authenticated)
720 return 0;
721
Johan Hedberg51a8efd2012-01-16 06:10:31 +0200722 if (test_and_set_bit(HCI_CONN_ENCRYPT_PEND, &hcon->flags))
Vinicius Costa Gomes988c5992011-08-25 20:02:28 -0300723 return 1;
724
Vinicius Costa Gomesc9839a12012-02-02 21:08:01 -0300725 hci_le_start_enc(hcon, key->ediv, key->rand, key->val);
726 hcon->enc_key_size = key->enc_size;
Vinicius Costa Gomes988c5992011-08-25 20:02:28 -0300727
728 return 1;
Vinicius Costa Gomes988c5992011-08-25 20:02:28 -0300729}
Marcel Holtmannf1560462013-10-13 05:43:25 -0700730
Vinicius Costa Gomesda85e5e2011-06-09 18:50:53 -0300731static u8 smp_cmd_security_req(struct l2cap_conn *conn, struct sk_buff *skb)
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300732{
733 struct smp_cmd_security_req *rp = (void *) skb->data;
734 struct smp_cmd_pairing cp;
Vinicius Costa Gomesf1cb9af2011-01-26 21:42:57 -0300735 struct hci_conn *hcon = conn->hcon;
Vinicius Costa Gomes8aab4752011-09-05 14:31:31 -0300736 struct smp_chan *smp;
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300737
738 BT_DBG("conn %p", conn);
739
Johan Hedbergc46b98b2014-02-18 10:19:29 +0200740 if (skb->len < sizeof(*rp))
741 return SMP_UNSPECIFIED;
742
Johan Hedberg86ca9ea2013-11-05 11:30:39 +0200743 if (!(conn->hcon->link_mode & HCI_LM_MASTER))
744 return SMP_CMD_NOTSUPP;
745
Brian Gix2b64d152011-12-21 16:12:12 -0800746 hcon->pending_sec_level = authreq_to_seclevel(rp->auth_req);
Vinicius Costa Gomesfeb45eb2011-08-25 20:02:35 -0300747
Johan Hedberg4dab7862012-06-07 14:58:37 +0800748 if (smp_ltk_encrypt(conn, hcon->pending_sec_level))
Vinicius Costa Gomes988c5992011-08-25 20:02:28 -0300749 return 0;
750
Johan Hedberg51a8efd2012-01-16 06:10:31 +0200751 if (test_and_set_bit(HCI_CONN_LE_SMP_PEND, &hcon->flags))
Vinicius Costa Gomesda85e5e2011-06-09 18:50:53 -0300752 return 0;
Vinicius Costa Gomesf1cb9af2011-01-26 21:42:57 -0300753
Vinicius Costa Gomes8aab4752011-09-05 14:31:31 -0300754 smp = smp_chan_create(conn);
Vinicius Costa Gomesd26a2342011-08-19 21:06:51 -0300755
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300756 skb_pull(skb, sizeof(*rp));
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300757
Vinicius Costa Gomesda85e5e2011-06-09 18:50:53 -0300758 memset(&cp, 0, sizeof(cp));
Vinicius Costa Gomes54790f72011-07-07 18:59:38 -0300759 build_pairing_cmd(conn, &cp, NULL, rp->auth_req);
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300760
Vinicius Costa Gomes1c1def02011-09-05 14:31:30 -0300761 smp->preq[0] = SMP_CMD_PAIRING_REQ;
762 memcpy(&smp->preq[1], &cp, sizeof(cp));
Anderson Brigliaf01ead32011-06-09 18:50:45 -0300763
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300764 smp_send_cmd(conn, SMP_CMD_PAIRING_REQ, sizeof(cp), &cp);
Vinicius Costa Gomesf1cb9af2011-01-26 21:42:57 -0300765
Vinicius Costa Gomesda85e5e2011-06-09 18:50:53 -0300766 return 0;
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300767}
768
Johan Hedbergad32a2f2013-05-14 18:05:12 +0300769bool smp_sufficient_security(struct hci_conn *hcon, u8 sec_level)
770{
771 if (sec_level == BT_SECURITY_LOW)
772 return true;
773
774 if (hcon->sec_level >= sec_level)
775 return true;
776
777 return false;
778}
779
Vinicius Costa Gomescc110922012-08-23 21:32:43 -0300780int smp_conn_security(struct hci_conn *hcon, __u8 sec_level)
Anderson Brigliaeb492e02011-06-09 18:50:40 -0300781{
Vinicius Costa Gomescc110922012-08-23 21:32:43 -0300782 struct l2cap_conn *conn = hcon->l2cap_data;
Vinicius Costa Gomes1c1def02011-09-05 14:31:30 -0300783 struct smp_chan *smp = conn->smp_chan;
Brian Gix2b64d152011-12-21 16:12:12 -0800784 __u8 authreq;
Anderson Brigliaeb492e02011-06-09 18:50:40 -0300785
Vinicius Costa Gomes3a0259b2011-06-09 18:50:43 -0300786 BT_DBG("conn %p hcon %p level 0x%2.2x", conn, hcon, sec_level);
787
Johan Hedberg757aee02013-04-24 13:05:32 +0300788 if (!test_bit(HCI_LE_ENABLED, &hcon->hdev->dev_flags))
Andre Guedes2e65c9d2011-06-30 19:20:56 -0300789 return 1;
790
Johan Hedbergad32a2f2013-05-14 18:05:12 +0300791 if (smp_sufficient_security(hcon, sec_level))
Vinicius Costa Gomesf1cb9af2011-01-26 21:42:57 -0300792 return 1;
793
Vinicius Costa Gomes988c5992011-08-25 20:02:28 -0300794 if (hcon->link_mode & HCI_LM_MASTER)
Johan Hedberg4dab7862012-06-07 14:58:37 +0800795 if (smp_ltk_encrypt(conn, sec_level))
Vinicius Costa Gomes02bc7452011-07-07 18:59:41 -0300796 goto done;
Vinicius Costa Gomesd26a2342011-08-19 21:06:51 -0300797
Johan Hedberg51a8efd2012-01-16 06:10:31 +0200798 if (test_and_set_bit(HCI_CONN_LE_SMP_PEND, &hcon->flags))
Vinicius Costa Gomesd26a2342011-08-19 21:06:51 -0300799 return 0;
800
Vinicius Costa Gomes8aab4752011-09-05 14:31:31 -0300801 smp = smp_chan_create(conn);
Brian Gix2b64d152011-12-21 16:12:12 -0800802 if (!smp)
803 return 1;
804
805 authreq = seclevel_to_authreq(sec_level);
Vinicius Costa Gomesd26a2342011-08-19 21:06:51 -0300806
Vinicius Costa Gomesd26a2342011-08-19 21:06:51 -0300807 if (hcon->link_mode & HCI_LM_MASTER) {
808 struct smp_cmd_pairing cp;
Anderson Brigliaf01ead32011-06-09 18:50:45 -0300809
Brian Gix2b64d152011-12-21 16:12:12 -0800810 build_pairing_cmd(conn, &cp, NULL, authreq);
Vinicius Costa Gomes1c1def02011-09-05 14:31:30 -0300811 smp->preq[0] = SMP_CMD_PAIRING_REQ;
812 memcpy(&smp->preq[1], &cp, sizeof(cp));
Anderson Brigliaf01ead32011-06-09 18:50:45 -0300813
Anderson Brigliaeb492e02011-06-09 18:50:40 -0300814 smp_send_cmd(conn, SMP_CMD_PAIRING_REQ, sizeof(cp), &cp);
815 } else {
816 struct smp_cmd_security_req cp;
Brian Gix2b64d152011-12-21 16:12:12 -0800817 cp.auth_req = authreq;
Anderson Brigliaeb492e02011-06-09 18:50:40 -0300818 smp_send_cmd(conn, SMP_CMD_SECURITY_REQ, sizeof(cp), &cp);
819 }
820
Vinicius Costa Gomes02bc7452011-07-07 18:59:41 -0300821done:
Vinicius Costa Gomesf1cb9af2011-01-26 21:42:57 -0300822 hcon->pending_sec_level = sec_level;
Vinicius Costa Gomesf1cb9af2011-01-26 21:42:57 -0300823
Anderson Brigliaeb492e02011-06-09 18:50:40 -0300824 return 0;
825}
826
Vinicius Costa Gomes7034b912011-07-07 18:59:34 -0300827static int smp_cmd_encrypt_info(struct l2cap_conn *conn, struct sk_buff *skb)
828{
Vinicius Costa Gomes16b90832011-07-07 18:59:39 -0300829 struct smp_cmd_encrypt_info *rp = (void *) skb->data;
Vinicius Costa Gomes1c1def02011-09-05 14:31:30 -0300830 struct smp_chan *smp = conn->smp_chan;
Vinicius Costa Gomes16b90832011-07-07 18:59:39 -0300831
Johan Hedbergc46b98b2014-02-18 10:19:29 +0200832 BT_DBG("conn %p", conn);
833
834 if (skb->len < sizeof(*rp))
835 return SMP_UNSPECIFIED;
836
Vinicius Costa Gomes16b90832011-07-07 18:59:39 -0300837 skb_pull(skb, sizeof(*rp));
838
Vinicius Costa Gomes1c1def02011-09-05 14:31:30 -0300839 memcpy(smp->tk, rp->ltk, sizeof(smp->tk));
Vinicius Costa Gomes16b90832011-07-07 18:59:39 -0300840
Vinicius Costa Gomes7034b912011-07-07 18:59:34 -0300841 return 0;
842}
843
844static int smp_cmd_master_ident(struct l2cap_conn *conn, struct sk_buff *skb)
845{
Vinicius Costa Gomes16b90832011-07-07 18:59:39 -0300846 struct smp_cmd_master_ident *rp = (void *) skb->data;
Vinicius Costa Gomes1c1def02011-09-05 14:31:30 -0300847 struct smp_chan *smp = conn->smp_chan;
Vinicius Costa Gomesc9839a12012-02-02 21:08:01 -0300848 struct hci_dev *hdev = conn->hcon->hdev;
849 struct hci_conn *hcon = conn->hcon;
850 u8 authenticated;
Vinicius Costa Gomes7034b912011-07-07 18:59:34 -0300851
Johan Hedbergc46b98b2014-02-18 10:19:29 +0200852 BT_DBG("conn %p", conn);
853
854 if (skb->len < sizeof(*rp))
855 return SMP_UNSPECIFIED;
856
Vinicius Costa Gomes16b90832011-07-07 18:59:39 -0300857 skb_pull(skb, sizeof(*rp));
858
Vinicius Costa Gomesc9839a12012-02-02 21:08:01 -0300859 hci_dev_lock(hdev);
Marcel Holtmannce39fb42013-10-13 02:23:39 -0700860 authenticated = (hcon->sec_level == BT_SECURITY_HIGH);
861 hci_add_ltk(hdev, &hcon->dst, hcon->dst_type, HCI_SMP_LTK, 1,
862 authenticated, smp->tk, smp->enc_key_size,
Gustavo F. Padovan04124682012-03-08 01:25:00 -0300863 rp->ediv, rp->rand);
Vinicius Costa Gomes7034b912011-07-07 18:59:34 -0300864 smp_distribute_keys(conn, 1);
Vinicius Costa Gomesc9839a12012-02-02 21:08:01 -0300865 hci_dev_unlock(hdev);
Vinicius Costa Gomes7034b912011-07-07 18:59:34 -0300866
867 return 0;
868}
869
Anderson Brigliaeb492e02011-06-09 18:50:40 -0300870int smp_sig_channel(struct l2cap_conn *conn, struct sk_buff *skb)
871{
Marcel Holtmann7b9899d2013-10-03 00:00:57 -0700872 struct hci_conn *hcon = conn->hcon;
Marcel Holtmann92381f52013-10-03 01:23:08 -0700873 __u8 code, reason;
Anderson Brigliaeb492e02011-06-09 18:50:40 -0300874 int err = 0;
875
Marcel Holtmann7b9899d2013-10-03 00:00:57 -0700876 if (hcon->type != LE_LINK) {
877 kfree_skb(skb);
Johan Hedberg34327112013-10-16 11:37:01 +0300878 return 0;
Marcel Holtmann7b9899d2013-10-03 00:00:57 -0700879 }
880
Marcel Holtmann92381f52013-10-03 01:23:08 -0700881 if (skb->len < 1) {
882 kfree_skb(skb);
883 return -EILSEQ;
884 }
885
Marcel Holtmann06ae3312013-10-18 03:43:00 -0700886 if (!test_bit(HCI_LE_ENABLED, &hcon->hdev->dev_flags)) {
Andre Guedes2e65c9d2011-06-30 19:20:56 -0300887 err = -ENOTSUPP;
888 reason = SMP_PAIRING_NOTSUPP;
889 goto done;
890 }
891
Marcel Holtmann92381f52013-10-03 01:23:08 -0700892 code = skb->data[0];
Anderson Brigliaeb492e02011-06-09 18:50:40 -0300893 skb_pull(skb, sizeof(code));
894
Johan Hedberg8cf9fa12013-01-29 10:44:23 -0600895 /*
896 * The SMP context must be initialized for all other PDUs except
897 * pairing and security requests. If we get any other PDU when
898 * not initialized simply disconnect (done if this function
899 * returns an error).
900 */
901 if (code != SMP_CMD_PAIRING_REQ && code != SMP_CMD_SECURITY_REQ &&
902 !conn->smp_chan) {
903 BT_ERR("Unexpected SMP command 0x%02x. Disconnecting.", code);
904 kfree_skb(skb);
905 return -ENOTSUPP;
906 }
907
Anderson Brigliaeb492e02011-06-09 18:50:40 -0300908 switch (code) {
909 case SMP_CMD_PAIRING_REQ:
Vinicius Costa Gomesda85e5e2011-06-09 18:50:53 -0300910 reason = smp_cmd_pairing_req(conn, skb);
Anderson Brigliaeb492e02011-06-09 18:50:40 -0300911 break;
912
913 case SMP_CMD_PAIRING_FAIL:
Johan Hedberg84794e12013-11-06 11:24:57 +0200914 smp_failure(conn, 0);
Vinicius Costa Gomesda85e5e2011-06-09 18:50:53 -0300915 reason = 0;
916 err = -EPERM;
Anderson Brigliaeb492e02011-06-09 18:50:40 -0300917 break;
918
919 case SMP_CMD_PAIRING_RSP:
Vinicius Costa Gomesda85e5e2011-06-09 18:50:53 -0300920 reason = smp_cmd_pairing_rsp(conn, skb);
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300921 break;
922
923 case SMP_CMD_SECURITY_REQ:
Vinicius Costa Gomesda85e5e2011-06-09 18:50:53 -0300924 reason = smp_cmd_security_req(conn, skb);
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300925 break;
926
Anderson Brigliaeb492e02011-06-09 18:50:40 -0300927 case SMP_CMD_PAIRING_CONFIRM:
Vinicius Costa Gomesda85e5e2011-06-09 18:50:53 -0300928 reason = smp_cmd_pairing_confirm(conn, skb);
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300929 break;
930
Anderson Brigliaeb492e02011-06-09 18:50:40 -0300931 case SMP_CMD_PAIRING_RANDOM:
Vinicius Costa Gomesda85e5e2011-06-09 18:50:53 -0300932 reason = smp_cmd_pairing_random(conn, skb);
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300933 break;
934
Anderson Brigliaeb492e02011-06-09 18:50:40 -0300935 case SMP_CMD_ENCRYPT_INFO:
Vinicius Costa Gomes7034b912011-07-07 18:59:34 -0300936 reason = smp_cmd_encrypt_info(conn, skb);
937 break;
938
Anderson Brigliaeb492e02011-06-09 18:50:40 -0300939 case SMP_CMD_MASTER_IDENT:
Vinicius Costa Gomes7034b912011-07-07 18:59:34 -0300940 reason = smp_cmd_master_ident(conn, skb);
941 break;
942
Anderson Brigliaeb492e02011-06-09 18:50:40 -0300943 case SMP_CMD_IDENT_INFO:
944 case SMP_CMD_IDENT_ADDR_INFO:
945 case SMP_CMD_SIGN_INFO:
Vinicius Costa Gomes7034b912011-07-07 18:59:34 -0300946 /* Just ignored */
947 reason = 0;
948 break;
949
Anderson Brigliaeb492e02011-06-09 18:50:40 -0300950 default:
951 BT_DBG("Unknown command code 0x%2.2x", code);
952
953 reason = SMP_CMD_NOTSUPP;
Vinicius Costa Gomes3a0259b2011-06-09 18:50:43 -0300954 err = -EOPNOTSUPP;
955 goto done;
956 }
957
958done:
959 if (reason)
Johan Hedberg84794e12013-11-06 11:24:57 +0200960 smp_failure(conn, reason);
Anderson Brigliaeb492e02011-06-09 18:50:40 -0300961
962 kfree_skb(skb);
963 return err;
964}
Vinicius Costa Gomes7034b912011-07-07 18:59:34 -0300965
966int smp_distribute_keys(struct l2cap_conn *conn, __u8 force)
967{
968 struct smp_cmd_pairing *req, *rsp;
Vinicius Costa Gomes1c1def02011-09-05 14:31:30 -0300969 struct smp_chan *smp = conn->smp_chan;
Vinicius Costa Gomes7034b912011-07-07 18:59:34 -0300970 __u8 *keydist;
971
972 BT_DBG("conn %p force %d", conn, force);
973
Johan Hedberg51a8efd2012-01-16 06:10:31 +0200974 if (!test_bit(HCI_CONN_LE_SMP_PEND, &conn->hcon->flags))
Vinicius Costa Gomesd26a2342011-08-19 21:06:51 -0300975 return 0;
976
Vinicius Costa Gomes1c1def02011-09-05 14:31:30 -0300977 rsp = (void *) &smp->prsp[1];
Vinicius Costa Gomes7034b912011-07-07 18:59:34 -0300978
979 /* The responder sends its keys first */
980 if (!force && conn->hcon->out && (rsp->resp_key_dist & 0x07))
981 return 0;
982
Vinicius Costa Gomes1c1def02011-09-05 14:31:30 -0300983 req = (void *) &smp->preq[1];
Vinicius Costa Gomes7034b912011-07-07 18:59:34 -0300984
985 if (conn->hcon->out) {
986 keydist = &rsp->init_key_dist;
987 *keydist &= req->init_key_dist;
988 } else {
989 keydist = &rsp->resp_key_dist;
990 *keydist &= req->resp_key_dist;
991 }
992
993
994 BT_DBG("keydist 0x%x", *keydist);
995
996 if (*keydist & SMP_DIST_ENC_KEY) {
997 struct smp_cmd_encrypt_info enc;
998 struct smp_cmd_master_ident ident;
Vinicius Costa Gomesc9839a12012-02-02 21:08:01 -0300999 struct hci_conn *hcon = conn->hcon;
1000 u8 authenticated;
Vinicius Costa Gomes7034b912011-07-07 18:59:34 -03001001 __le16 ediv;
1002
1003 get_random_bytes(enc.ltk, sizeof(enc.ltk));
1004 get_random_bytes(&ediv, sizeof(ediv));
1005 get_random_bytes(ident.rand, sizeof(ident.rand));
1006
1007 smp_send_cmd(conn, SMP_CMD_ENCRYPT_INFO, sizeof(enc), &enc);
1008
Vinicius Costa Gomesc9839a12012-02-02 21:08:01 -03001009 authenticated = hcon->sec_level == BT_SECURITY_HIGH;
Marcel Holtmannce39fb42013-10-13 02:23:39 -07001010 hci_add_ltk(hcon->hdev, &hcon->dst, hcon->dst_type,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001011 HCI_SMP_LTK_SLAVE, 1, authenticated,
1012 enc.ltk, smp->enc_key_size, ediv, ident.rand);
Vinicius Costa Gomes16b90832011-07-07 18:59:39 -03001013
Andrei Emeltchenko58115372012-03-12 12:13:06 +02001014 ident.ediv = ediv;
Vinicius Costa Gomes7034b912011-07-07 18:59:34 -03001015
1016 smp_send_cmd(conn, SMP_CMD_MASTER_IDENT, sizeof(ident), &ident);
1017
1018 *keydist &= ~SMP_DIST_ENC_KEY;
1019 }
1020
1021 if (*keydist & SMP_DIST_ID_KEY) {
1022 struct smp_cmd_ident_addr_info addrinfo;
1023 struct smp_cmd_ident_info idinfo;
1024
1025 /* Send a dummy key */
1026 get_random_bytes(idinfo.irk, sizeof(idinfo.irk));
1027
1028 smp_send_cmd(conn, SMP_CMD_IDENT_INFO, sizeof(idinfo), &idinfo);
1029
1030 /* Just public address */
1031 memset(&addrinfo, 0, sizeof(addrinfo));
Marcel Holtmann2b36a562013-10-13 05:24:00 -07001032 bacpy(&addrinfo.bdaddr, &conn->hcon->src);
Vinicius Costa Gomes7034b912011-07-07 18:59:34 -03001033
1034 smp_send_cmd(conn, SMP_CMD_IDENT_ADDR_INFO, sizeof(addrinfo),
Marcel Holtmannf1560462013-10-13 05:43:25 -07001035 &addrinfo);
Vinicius Costa Gomes7034b912011-07-07 18:59:34 -03001036
1037 *keydist &= ~SMP_DIST_ID_KEY;
1038 }
1039
1040 if (*keydist & SMP_DIST_SIGN) {
1041 struct smp_cmd_sign_info sign;
1042
1043 /* Send a dummy key */
1044 get_random_bytes(sign.csrk, sizeof(sign.csrk));
1045
1046 smp_send_cmd(conn, SMP_CMD_SIGN_INFO, sizeof(sign), &sign);
1047
1048 *keydist &= ~SMP_DIST_SIGN;
1049 }
1050
Vinicius Costa Gomesd26a2342011-08-19 21:06:51 -03001051 if (conn->hcon->out || force) {
Johan Hedberg51a8efd2012-01-16 06:10:31 +02001052 clear_bit(HCI_CONN_LE_SMP_PEND, &conn->hcon->flags);
Gustavo F. Padovan6c9d42a2011-12-20 10:57:27 -02001053 cancel_delayed_work_sync(&conn->security_timer);
Vinicius Costa Gomes8aab4752011-09-05 14:31:31 -03001054 smp_chan_destroy(conn);
Vinicius Costa Gomesd26a2342011-08-19 21:06:51 -03001055 }
1056
Vinicius Costa Gomes7034b912011-07-07 18:59:34 -03001057 return 0;
1058}