blob: 9272094bd429c5cbd66599a9ad7b13c24789ef10 [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;
56 int err, iv_len;
57 unsigned char iv[128];
58
59 if (tfm == NULL) {
60 BT_ERR("tfm %p", tfm);
61 return -EINVAL;
62 }
63
64 desc.tfm = tfm;
65 desc.flags = 0;
66
67 err = crypto_blkcipher_setkey(tfm, k, 16);
68 if (err) {
69 BT_ERR("cipher setkey failed: %d", err);
70 return err;
71 }
72
73 sg_init_one(&sg, r, 16);
74
75 iv_len = crypto_blkcipher_ivsize(tfm);
76 if (iv_len) {
77 memset(&iv, 0xff, iv_len);
78 crypto_blkcipher_set_iv(tfm, iv, iv_len);
79 }
80
81 err = crypto_blkcipher_encrypt(&desc, &sg, &sg, 16);
82 if (err)
83 BT_ERR("Encrypt data error %d", err);
84
85 return err;
86}
87
88static int smp_c1(struct crypto_blkcipher *tfm, u8 k[16], u8 r[16],
89 u8 preq[7], u8 pres[7], u8 _iat, bdaddr_t *ia,
90 u8 _rat, bdaddr_t *ra, u8 res[16])
91{
92 u8 p1[16], p2[16];
93 int err;
94
95 memset(p1, 0, 16);
96
97 /* p1 = pres || preq || _rat || _iat */
98 swap56(pres, p1);
99 swap56(preq, p1 + 7);
100 p1[14] = _rat;
101 p1[15] = _iat;
102
103 memset(p2, 0, 16);
104
105 /* p2 = padding || ia || ra */
106 baswap((bdaddr_t *) (p2 + 4), ia);
107 baswap((bdaddr_t *) (p2 + 10), ra);
108
109 /* res = r XOR p1 */
110 u128_xor((u128 *) res, (u128 *) r, (u128 *) p1);
111
112 /* res = e(k, res) */
113 err = smp_e(tfm, k, res);
114 if (err) {
115 BT_ERR("Encrypt data error");
116 return err;
117 }
118
119 /* res = res XOR p2 */
120 u128_xor((u128 *) res, (u128 *) res, (u128 *) p2);
121
122 /* res = e(k, res) */
123 err = smp_e(tfm, k, res);
124 if (err)
125 BT_ERR("Encrypt data error");
126
127 return err;
128}
129
130static int smp_s1(struct crypto_blkcipher *tfm, u8 k[16],
131 u8 r1[16], u8 r2[16], u8 _r[16])
132{
133 int err;
134
135 /* Just least significant octets from r1 and r2 are considered */
136 memcpy(_r, r1 + 8, 8);
137 memcpy(_r + 8, r2 + 8, 8);
138
139 err = smp_e(tfm, k, _r);
140 if (err)
141 BT_ERR("Encrypt data error");
142
143 return err;
144}
145
146static int smp_rand(u8 *buf)
147{
148 get_random_bytes(buf, 16);
149
150 return 0;
151}
Anderson Brigliaeb492e02011-06-09 18:50:40 -0300152
153static struct sk_buff *smp_build_cmd(struct l2cap_conn *conn, u8 code,
154 u16 dlen, void *data)
155{
156 struct sk_buff *skb;
157 struct l2cap_hdr *lh;
158 int len;
159
160 len = L2CAP_HDR_SIZE + sizeof(code) + dlen;
161
162 if (len > conn->mtu)
163 return NULL;
164
165 skb = bt_skb_alloc(len, GFP_ATOMIC);
166 if (!skb)
167 return NULL;
168
169 lh = (struct l2cap_hdr *) skb_put(skb, L2CAP_HDR_SIZE);
170 lh->len = cpu_to_le16(sizeof(code) + dlen);
Syam Sidhardhand8aece22012-10-10 22:09:28 +0530171 lh->cid = __constant_cpu_to_le16(L2CAP_CID_SMP);
Anderson Brigliaeb492e02011-06-09 18:50:40 -0300172
173 memcpy(skb_put(skb, sizeof(code)), &code, sizeof(code));
174
175 memcpy(skb_put(skb, dlen), data, dlen);
176
177 return skb;
178}
179
180static void smp_send_cmd(struct l2cap_conn *conn, u8 code, u16 len, void *data)
181{
182 struct sk_buff *skb = smp_build_cmd(conn, code, len, data);
183
184 BT_DBG("code 0x%2.2x", code);
185
186 if (!skb)
187 return;
188
Luiz Augusto von Dentz73d80de2011-11-02 15:52:01 +0200189 skb->priority = HCI_PRIO_MAX;
190 hci_send_acl(conn->hchan, skb, 0);
Vinicius Costa Gomese2dcd112011-08-19 21:06:50 -0300191
Gustavo F. Padovan6c9d42a2011-12-20 10:57:27 -0200192 cancel_delayed_work_sync(&conn->security_timer);
Marcel Holtmann17b02e62012-03-01 14:32:37 -0800193 schedule_delayed_work(&conn->security_timer, SMP_TIMEOUT);
Anderson Brigliaeb492e02011-06-09 18:50:40 -0300194}
195
Brian Gix2b64d152011-12-21 16:12:12 -0800196static __u8 authreq_to_seclevel(__u8 authreq)
197{
198 if (authreq & SMP_AUTH_MITM)
199 return BT_SECURITY_HIGH;
200 else
201 return BT_SECURITY_MEDIUM;
202}
203
204static __u8 seclevel_to_authreq(__u8 sec_level)
205{
206 switch (sec_level) {
207 case BT_SECURITY_HIGH:
208 return SMP_AUTH_MITM | SMP_AUTH_BONDING;
209 case BT_SECURITY_MEDIUM:
210 return SMP_AUTH_BONDING;
211 default:
212 return SMP_AUTH_NONE;
213 }
214}
215
Vinicius Costa Gomesb8e66ea2011-06-09 18:50:52 -0300216static void build_pairing_cmd(struct l2cap_conn *conn,
Vinicius Costa Gomes54790f72011-07-07 18:59:38 -0300217 struct smp_cmd_pairing *req,
218 struct smp_cmd_pairing *rsp,
219 __u8 authreq)
Vinicius Costa Gomesb8e66ea2011-06-09 18:50:52 -0300220{
Brian Gix2b64d152011-12-21 16:12:12 -0800221 u8 dist_keys = 0;
Vinicius Costa Gomes54790f72011-07-07 18:59:38 -0300222
Johan Hedberga8b2d5c2012-01-08 23:11:15 +0200223 if (test_bit(HCI_PAIRABLE, &conn->hcon->hdev->dev_flags)) {
Vinicius Costa Gomesca10b5e2011-08-25 20:02:37 -0300224 dist_keys = SMP_DIST_ENC_KEY;
Vinicius Costa Gomes54790f72011-07-07 18:59:38 -0300225 authreq |= SMP_AUTH_BONDING;
Brian Gix2b64d152011-12-21 16:12:12 -0800226 } else {
227 authreq &= ~SMP_AUTH_BONDING;
Vinicius Costa Gomes54790f72011-07-07 18:59:38 -0300228 }
229
230 if (rsp == NULL) {
231 req->io_capability = conn->hcon->io_capability;
232 req->oob_flag = SMP_OOB_NOT_PRESENT;
233 req->max_key_size = SMP_MAX_ENC_KEY_SIZE;
Brian Gix2b64d152011-12-21 16:12:12 -0800234 req->init_key_dist = 0;
Vinicius Costa Gomes54790f72011-07-07 18:59:38 -0300235 req->resp_key_dist = dist_keys;
Johan Hedberg065a13e2012-10-11 16:26:06 +0200236 req->auth_req = (authreq & AUTH_REQ_MASK);
Vinicius Costa Gomes54790f72011-07-07 18:59:38 -0300237 return;
238 }
239
240 rsp->io_capability = conn->hcon->io_capability;
241 rsp->oob_flag = SMP_OOB_NOT_PRESENT;
242 rsp->max_key_size = SMP_MAX_ENC_KEY_SIZE;
Brian Gix2b64d152011-12-21 16:12:12 -0800243 rsp->init_key_dist = 0;
Vinicius Costa Gomes54790f72011-07-07 18:59:38 -0300244 rsp->resp_key_dist = req->resp_key_dist & dist_keys;
Johan Hedberg065a13e2012-10-11 16:26:06 +0200245 rsp->auth_req = (authreq & AUTH_REQ_MASK);
Vinicius Costa Gomesb8e66ea2011-06-09 18:50:52 -0300246}
247
Vinicius Costa Gomes3158c502011-06-14 13:37:42 -0300248static u8 check_enc_key_size(struct l2cap_conn *conn, __u8 max_key_size)
249{
Vinicius Costa Gomes1c1def02011-09-05 14:31:30 -0300250 struct smp_chan *smp = conn->smp_chan;
251
Vinicius Costa Gomes3158c502011-06-14 13:37:42 -0300252 if ((max_key_size > SMP_MAX_ENC_KEY_SIZE) ||
253 (max_key_size < SMP_MIN_ENC_KEY_SIZE))
254 return SMP_ENC_KEY_SIZE;
255
Vinicius Costa Gomesf7aa6112012-01-30 19:29:12 -0300256 smp->enc_key_size = max_key_size;
Vinicius Costa Gomes3158c502011-06-14 13:37:42 -0300257
258 return 0;
259}
260
Brian Gix4f957a72011-11-23 08:28:36 -0800261static void smp_failure(struct l2cap_conn *conn, u8 reason, u8 send)
262{
Johan Hedbergbab73cb2012-02-09 16:07:29 +0200263 struct hci_conn *hcon = conn->hcon;
264
Brian Gix4f957a72011-11-23 08:28:36 -0800265 if (send)
266 smp_send_cmd(conn, SMP_CMD_PAIRING_FAIL, sizeof(reason),
267 &reason);
268
Johan Hedberg51a8efd2012-01-16 06:10:31 +0200269 clear_bit(HCI_CONN_ENCRYPT_PEND, &conn->hcon->flags);
Johan Hedbergbab73cb2012-02-09 16:07:29 +0200270 mgmt_auth_failed(conn->hcon->hdev, conn->dst, hcon->type,
Paulo Sérgio896ea282012-10-25 16:55:51 -0300271 hcon->dst_type, HCI_ERROR_AUTH_FAILURE);
Vinicius Costa Gomesf1c09c02012-02-01 18:27:56 -0300272
Andre Guedes61a0cfb2012-08-01 20:34:15 -0300273 cancel_delayed_work_sync(&conn->security_timer);
274
275 if (test_and_clear_bit(HCI_CONN_LE_SMP_PEND, &conn->hcon->flags))
Vinicius Costa Gomesf1c09c02012-02-01 18:27:56 -0300276 smp_chan_destroy(conn);
Brian Gix4f957a72011-11-23 08:28:36 -0800277}
278
Brian Gix2b64d152011-12-21 16:12:12 -0800279#define JUST_WORKS 0x00
280#define JUST_CFM 0x01
281#define REQ_PASSKEY 0x02
282#define CFM_PASSKEY 0x03
283#define REQ_OOB 0x04
284#define OVERLAP 0xFF
285
286static const u8 gen_method[5][5] = {
287 { JUST_WORKS, JUST_CFM, REQ_PASSKEY, JUST_WORKS, REQ_PASSKEY },
288 { JUST_WORKS, JUST_CFM, REQ_PASSKEY, JUST_WORKS, REQ_PASSKEY },
289 { CFM_PASSKEY, CFM_PASSKEY, REQ_PASSKEY, JUST_WORKS, CFM_PASSKEY },
290 { JUST_WORKS, JUST_CFM, JUST_WORKS, JUST_WORKS, JUST_CFM },
291 { CFM_PASSKEY, CFM_PASSKEY, REQ_PASSKEY, JUST_WORKS, OVERLAP },
292};
293
294static int tk_request(struct l2cap_conn *conn, u8 remote_oob, u8 auth,
295 u8 local_io, u8 remote_io)
296{
297 struct hci_conn *hcon = conn->hcon;
298 struct smp_chan *smp = conn->smp_chan;
299 u8 method;
300 u32 passkey = 0;
301 int ret = 0;
302
303 /* Initialize key for JUST WORKS */
304 memset(smp->tk, 0, sizeof(smp->tk));
305 clear_bit(SMP_FLAG_TK_VALID, &smp->smp_flags);
306
307 BT_DBG("tk_request: auth:%d lcl:%d rem:%d", auth, local_io, remote_io);
308
309 /* If neither side wants MITM, use JUST WORKS */
310 /* If either side has unknown io_caps, use JUST WORKS */
311 /* Otherwise, look up method from the table */
312 if (!(auth & SMP_AUTH_MITM) ||
313 local_io > SMP_IO_KEYBOARD_DISPLAY ||
314 remote_io > SMP_IO_KEYBOARD_DISPLAY)
315 method = JUST_WORKS;
316 else
Ido Yarivb3ff53f2012-03-05 20:07:08 +0200317 method = gen_method[remote_io][local_io];
Brian Gix2b64d152011-12-21 16:12:12 -0800318
319 /* If not bonding, don't ask user to confirm a Zero TK */
320 if (!(auth & SMP_AUTH_BONDING) && method == JUST_CFM)
321 method = JUST_WORKS;
322
323 /* If Just Works, Continue with Zero TK */
324 if (method == JUST_WORKS) {
325 set_bit(SMP_FLAG_TK_VALID, &smp->smp_flags);
326 return 0;
327 }
328
329 /* Not Just Works/Confirm results in MITM Authentication */
330 if (method != JUST_CFM)
331 set_bit(SMP_FLAG_MITM_AUTH, &smp->smp_flags);
332
333 /* If both devices have Keyoard-Display I/O, the master
334 * Confirms and the slave Enters the passkey.
335 */
336 if (method == OVERLAP) {
337 if (hcon->link_mode & HCI_LM_MASTER)
338 method = CFM_PASSKEY;
339 else
340 method = REQ_PASSKEY;
341 }
342
343 /* Generate random passkey. Not valid until confirmed. */
344 if (method == CFM_PASSKEY) {
345 u8 key[16];
346
347 memset(key, 0, sizeof(key));
348 get_random_bytes(&passkey, sizeof(passkey));
349 passkey %= 1000000;
350 put_unaligned_le32(passkey, key);
351 swap128(key, smp->tk);
352 BT_DBG("PassKey: %d", passkey);
353 }
354
355 hci_dev_lock(hcon->hdev);
356
357 if (method == REQ_PASSKEY)
Johan Hedberg272d90d2012-02-09 15:26:12 +0200358 ret = mgmt_user_passkey_request(hcon->hdev, conn->dst,
359 hcon->type, hcon->dst_type);
Brian Gix2b64d152011-12-21 16:12:12 -0800360 else
361 ret = mgmt_user_confirm_request(hcon->hdev, conn->dst,
Johan Hedberg272d90d2012-02-09 15:26:12 +0200362 hcon->type, hcon->dst_type,
Brian Gix2b64d152011-12-21 16:12:12 -0800363 cpu_to_le32(passkey), 0);
364
365 hci_dev_unlock(hcon->hdev);
366
367 return ret;
368}
369
Vinicius Costa Gomes8aab4752011-09-05 14:31:31 -0300370static void confirm_work(struct work_struct *work)
371{
372 struct smp_chan *smp = container_of(work, struct smp_chan, confirm);
373 struct l2cap_conn *conn = smp->conn;
374 struct crypto_blkcipher *tfm;
375 struct smp_cmd_pairing_confirm cp;
376 int ret;
377 u8 res[16], reason;
378
379 BT_DBG("conn %p", conn);
380
381 tfm = crypto_alloc_blkcipher("ecb(aes)", 0, CRYPTO_ALG_ASYNC);
382 if (IS_ERR(tfm)) {
383 reason = SMP_UNSPECIFIED;
384 goto error;
385 }
386
387 smp->tfm = tfm;
388
389 if (conn->hcon->out)
390 ret = smp_c1(tfm, smp->tk, smp->prnd, smp->preq, smp->prsp, 0,
Gustavo F. Padovan04124682012-03-08 01:25:00 -0300391 conn->src, conn->hcon->dst_type, conn->dst, res);
Vinicius Costa Gomes8aab4752011-09-05 14:31:31 -0300392 else
393 ret = smp_c1(tfm, smp->tk, smp->prnd, smp->preq, smp->prsp,
Gustavo F. Padovan04124682012-03-08 01:25:00 -0300394 conn->hcon->dst_type, conn->dst, 0, conn->src,
395 res);
Vinicius Costa Gomes8aab4752011-09-05 14:31:31 -0300396 if (ret) {
397 reason = SMP_UNSPECIFIED;
398 goto error;
399 }
400
Brian Gix2b64d152011-12-21 16:12:12 -0800401 clear_bit(SMP_FLAG_CFM_PENDING, &smp->smp_flags);
402
Vinicius Costa Gomes8aab4752011-09-05 14:31:31 -0300403 swap128(res, cp.confirm_val);
404 smp_send_cmd(smp->conn, SMP_CMD_PAIRING_CONFIRM, sizeof(cp), &cp);
405
406 return;
407
408error:
Brian Gix4f957a72011-11-23 08:28:36 -0800409 smp_failure(conn, reason, 1);
Vinicius Costa Gomes8aab4752011-09-05 14:31:31 -0300410}
411
412static void random_work(struct work_struct *work)
413{
414 struct smp_chan *smp = container_of(work, struct smp_chan, random);
415 struct l2cap_conn *conn = smp->conn;
416 struct hci_conn *hcon = conn->hcon;
417 struct crypto_blkcipher *tfm = smp->tfm;
418 u8 reason, confirm[16], res[16], key[16];
419 int ret;
420
421 if (IS_ERR_OR_NULL(tfm)) {
422 reason = SMP_UNSPECIFIED;
423 goto error;
424 }
425
426 BT_DBG("conn %p %s", conn, conn->hcon->out ? "master" : "slave");
427
428 if (hcon->out)
429 ret = smp_c1(tfm, smp->tk, smp->rrnd, smp->preq, smp->prsp, 0,
Gustavo F. Padovan04124682012-03-08 01:25:00 -0300430 conn->src, hcon->dst_type, conn->dst, res);
Vinicius Costa Gomes8aab4752011-09-05 14:31:31 -0300431 else
432 ret = smp_c1(tfm, smp->tk, smp->rrnd, smp->preq, smp->prsp,
Gustavo F. Padovan04124682012-03-08 01:25:00 -0300433 hcon->dst_type, conn->dst, 0, conn->src, res);
Vinicius Costa Gomes8aab4752011-09-05 14:31:31 -0300434 if (ret) {
435 reason = SMP_UNSPECIFIED;
436 goto error;
437 }
438
439 swap128(res, confirm);
440
441 if (memcmp(smp->pcnf, confirm, sizeof(smp->pcnf)) != 0) {
442 BT_ERR("Pairing failed (confirmation values mismatch)");
443 reason = SMP_CONFIRM_FAILED;
444 goto error;
445 }
446
447 if (hcon->out) {
448 u8 stk[16], rand[8];
449 __le16 ediv;
450
451 memset(rand, 0, sizeof(rand));
452 ediv = 0;
453
454 smp_s1(tfm, smp->tk, smp->rrnd, smp->prnd, key);
455 swap128(key, stk);
456
Vinicius Costa Gomesf7aa6112012-01-30 19:29:12 -0300457 memset(stk + smp->enc_key_size, 0,
Gustavo F. Padovan04124682012-03-08 01:25:00 -0300458 SMP_MAX_ENC_KEY_SIZE - smp->enc_key_size);
Vinicius Costa Gomes8aab4752011-09-05 14:31:31 -0300459
Johan Hedberg51a8efd2012-01-16 06:10:31 +0200460 if (test_and_set_bit(HCI_CONN_ENCRYPT_PEND, &hcon->flags)) {
Vinicius Costa Gomes8aab4752011-09-05 14:31:31 -0300461 reason = SMP_UNSPECIFIED;
462 goto error;
463 }
464
465 hci_le_start_enc(hcon, ediv, rand, stk);
Vinicius Costa Gomesf7aa6112012-01-30 19:29:12 -0300466 hcon->enc_key_size = smp->enc_key_size;
Vinicius Costa Gomes8aab4752011-09-05 14:31:31 -0300467 } else {
468 u8 stk[16], r[16], rand[8];
469 __le16 ediv;
470
471 memset(rand, 0, sizeof(rand));
472 ediv = 0;
473
474 swap128(smp->prnd, r);
475 smp_send_cmd(conn, SMP_CMD_PAIRING_RANDOM, sizeof(r), r);
476
477 smp_s1(tfm, smp->tk, smp->prnd, smp->rrnd, key);
478 swap128(key, stk);
479
Vinicius Costa Gomesf7aa6112012-01-30 19:29:12 -0300480 memset(stk + smp->enc_key_size, 0,
481 SMP_MAX_ENC_KEY_SIZE - smp->enc_key_size);
Vinicius Costa Gomes8aab4752011-09-05 14:31:31 -0300482
Vinicius Costa Gomesc9839a12012-02-02 21:08:01 -0300483 hci_add_ltk(hcon->hdev, conn->dst, hcon->dst_type,
Gustavo F. Padovan04124682012-03-08 01:25:00 -0300484 HCI_SMP_STK_SLAVE, 0, 0, stk, smp->enc_key_size,
485 ediv, rand);
Vinicius Costa Gomes8aab4752011-09-05 14:31:31 -0300486 }
487
488 return;
489
490error:
Brian Gix4f957a72011-11-23 08:28:36 -0800491 smp_failure(conn, reason, 1);
Vinicius Costa Gomes8aab4752011-09-05 14:31:31 -0300492}
493
494static struct smp_chan *smp_chan_create(struct l2cap_conn *conn)
495{
496 struct smp_chan *smp;
497
498 smp = kzalloc(sizeof(struct smp_chan), GFP_ATOMIC);
499 if (!smp)
500 return NULL;
501
502 INIT_WORK(&smp->confirm, confirm_work);
503 INIT_WORK(&smp->random, random_work);
504
505 smp->conn = conn;
506 conn->smp_chan = smp;
Brian Gix2b64d152011-12-21 16:12:12 -0800507 conn->hcon->smp_conn = conn;
Vinicius Costa Gomes8aab4752011-09-05 14:31:31 -0300508
509 hci_conn_hold(conn->hcon);
510
511 return smp;
512}
513
514void smp_chan_destroy(struct l2cap_conn *conn)
515{
Brian Gixc8eb9692011-11-23 08:28:35 -0800516 struct smp_chan *smp = conn->smp_chan;
517
Vinicius Costa Gomesf1c09c02012-02-01 18:27:56 -0300518 BUG_ON(!smp);
Brian Gixc8eb9692011-11-23 08:28:35 -0800519
520 if (smp->tfm)
521 crypto_free_blkcipher(smp->tfm);
522
523 kfree(smp);
524 conn->smp_chan = NULL;
Brian Gix2b64d152011-12-21 16:12:12 -0800525 conn->hcon->smp_conn = NULL;
David Herrmann76a68ba2013-04-06 20:28:37 +0200526 hci_conn_drop(conn->hcon);
Vinicius Costa Gomes8aab4752011-09-05 14:31:31 -0300527}
528
Brian Gix2b64d152011-12-21 16:12:12 -0800529int smp_user_confirm_reply(struct hci_conn *hcon, u16 mgmt_op, __le32 passkey)
530{
531 struct l2cap_conn *conn = hcon->smp_conn;
532 struct smp_chan *smp;
533 u32 value;
534 u8 key[16];
535
536 BT_DBG("");
537
538 if (!conn)
539 return -ENOTCONN;
540
541 smp = conn->smp_chan;
542
543 switch (mgmt_op) {
544 case MGMT_OP_USER_PASSKEY_REPLY:
545 value = le32_to_cpu(passkey);
546 memset(key, 0, sizeof(key));
547 BT_DBG("PassKey: %d", value);
548 put_unaligned_le32(value, key);
549 swap128(key, smp->tk);
550 /* Fall Through */
551 case MGMT_OP_USER_CONFIRM_REPLY:
552 set_bit(SMP_FLAG_TK_VALID, &smp->smp_flags);
553 break;
554 case MGMT_OP_USER_PASSKEY_NEG_REPLY:
555 case MGMT_OP_USER_CONFIRM_NEG_REPLY:
556 smp_failure(conn, SMP_PASSKEY_ENTRY_FAILED, 1);
557 return 0;
558 default:
559 smp_failure(conn, SMP_PASSKEY_ENTRY_FAILED, 1);
560 return -EOPNOTSUPP;
561 }
562
563 /* If it is our turn to send Pairing Confirm, do so now */
564 if (test_bit(SMP_FLAG_CFM_PENDING, &smp->smp_flags))
565 queue_work(hcon->hdev->workqueue, &smp->confirm);
566
567 return 0;
568}
569
Vinicius Costa Gomesda85e5e2011-06-09 18:50:53 -0300570static u8 smp_cmd_pairing_req(struct l2cap_conn *conn, struct sk_buff *skb)
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300571{
Vinicius Costa Gomes3158c502011-06-14 13:37:42 -0300572 struct smp_cmd_pairing rsp, *req = (void *) skb->data;
Vinicius Costa Gomes8aab4752011-09-05 14:31:31 -0300573 struct smp_chan *smp;
Vinicius Costa Gomes3158c502011-06-14 13:37:42 -0300574 u8 key_size;
Brian Gix2b64d152011-12-21 16:12:12 -0800575 u8 auth = SMP_AUTH_NONE;
Vinicius Costa Gomes8aab4752011-09-05 14:31:31 -0300576 int ret;
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300577
578 BT_DBG("conn %p", conn);
579
Brian Gix2b64d152011-12-21 16:12:12 -0800580 if (conn->hcon->link_mode & HCI_LM_MASTER)
581 return SMP_CMD_NOTSUPP;
582
Johan Hedberg51a8efd2012-01-16 06:10:31 +0200583 if (!test_and_set_bit(HCI_CONN_LE_SMP_PEND, &conn->hcon->flags))
Vinicius Costa Gomes8aab4752011-09-05 14:31:31 -0300584 smp = smp_chan_create(conn);
Andrei Emeltchenkod08fd0e2012-07-19 17:03:43 +0300585 else
586 smp = conn->smp_chan;
Vinicius Costa Gomes8aab4752011-09-05 14:31:31 -0300587
Andrei Emeltchenkod08fd0e2012-07-19 17:03:43 +0300588 if (!smp)
589 return SMP_UNSPECIFIED;
Vinicius Costa Gomesd26a2342011-08-19 21:06:51 -0300590
Vinicius Costa Gomes1c1def02011-09-05 14:31:30 -0300591 smp->preq[0] = SMP_CMD_PAIRING_REQ;
592 memcpy(&smp->preq[1], req, sizeof(*req));
Vinicius Costa Gomes3158c502011-06-14 13:37:42 -0300593 skb_pull(skb, sizeof(*req));
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300594
Brian Gix2b64d152011-12-21 16:12:12 -0800595 /* We didn't start the pairing, so match remote */
596 if (req->auth_req & SMP_AUTH_BONDING)
597 auth = req->auth_req;
Vinicius Costa Gomesda85e5e2011-06-09 18:50:53 -0300598
Ido Yarivfdde0a22012-03-05 20:09:38 +0200599 conn->hcon->pending_sec_level = authreq_to_seclevel(auth);
600
Brian Gix2b64d152011-12-21 16:12:12 -0800601 build_pairing_cmd(conn, req, &rsp, auth);
Vinicius Costa Gomes3158c502011-06-14 13:37:42 -0300602
603 key_size = min(req->max_key_size, rsp.max_key_size);
604 if (check_enc_key_size(conn, key_size))
605 return SMP_ENC_KEY_SIZE;
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300606
Vinicius Costa Gomes8aab4752011-09-05 14:31:31 -0300607 ret = smp_rand(smp->prnd);
608 if (ret)
609 return SMP_UNSPECIFIED;
610
Vinicius Costa Gomes1c1def02011-09-05 14:31:30 -0300611 smp->prsp[0] = SMP_CMD_PAIRING_RSP;
612 memcpy(&smp->prsp[1], &rsp, sizeof(rsp));
Anderson Brigliaf01ead32011-06-09 18:50:45 -0300613
Vinicius Costa Gomes3158c502011-06-14 13:37:42 -0300614 smp_send_cmd(conn, SMP_CMD_PAIRING_RSP, sizeof(rsp), &rsp);
Vinicius Costa Gomesda85e5e2011-06-09 18:50:53 -0300615
Brian Gix2b64d152011-12-21 16:12:12 -0800616 /* Request setup of TK */
617 ret = tk_request(conn, 0, auth, rsp.io_capability, req->io_capability);
618 if (ret)
619 return SMP_UNSPECIFIED;
620
Vinicius Costa Gomesda85e5e2011-06-09 18:50:53 -0300621 return 0;
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300622}
623
Vinicius Costa Gomesda85e5e2011-06-09 18:50:53 -0300624static u8 smp_cmd_pairing_rsp(struct l2cap_conn *conn, struct sk_buff *skb)
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300625{
Vinicius Costa Gomes3158c502011-06-14 13:37:42 -0300626 struct smp_cmd_pairing *req, *rsp = (void *) skb->data;
Vinicius Costa Gomes1c1def02011-09-05 14:31:30 -0300627 struct smp_chan *smp = conn->smp_chan;
Vinicius Costa Gomes8aab4752011-09-05 14:31:31 -0300628 struct hci_dev *hdev = conn->hcon->hdev;
Brian Gix2b64d152011-12-21 16:12:12 -0800629 u8 key_size, auth = SMP_AUTH_NONE;
Anderson Briglia7d24ddc2011-06-09 18:50:46 -0300630 int ret;
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300631
632 BT_DBG("conn %p", conn);
633
Brian Gix2b64d152011-12-21 16:12:12 -0800634 if (!(conn->hcon->link_mode & HCI_LM_MASTER))
635 return SMP_CMD_NOTSUPP;
636
Vinicius Costa Gomes3158c502011-06-14 13:37:42 -0300637 skb_pull(skb, sizeof(*rsp));
Vinicius Costa Gomesda85e5e2011-06-09 18:50:53 -0300638
Vinicius Costa Gomes1c1def02011-09-05 14:31:30 -0300639 req = (void *) &smp->preq[1];
Vinicius Costa Gomes3158c502011-06-14 13:37:42 -0300640
641 key_size = min(req->max_key_size, rsp->max_key_size);
642 if (check_enc_key_size(conn, key_size))
643 return SMP_ENC_KEY_SIZE;
644
Vinicius Costa Gomes1c1def02011-09-05 14:31:30 -0300645 ret = smp_rand(smp->prnd);
Anderson Briglia7d24ddc2011-06-09 18:50:46 -0300646 if (ret)
Vinicius Costa Gomesda85e5e2011-06-09 18:50:53 -0300647 return SMP_UNSPECIFIED;
Anderson Briglia7d24ddc2011-06-09 18:50:46 -0300648
Vinicius Costa Gomes8aab4752011-09-05 14:31:31 -0300649 smp->prsp[0] = SMP_CMD_PAIRING_RSP;
650 memcpy(&smp->prsp[1], rsp, sizeof(*rsp));
Anderson Briglia7d24ddc2011-06-09 18:50:46 -0300651
Brian Gix2b64d152011-12-21 16:12:12 -0800652 if ((req->auth_req & SMP_AUTH_BONDING) &&
653 (rsp->auth_req & SMP_AUTH_BONDING))
654 auth = SMP_AUTH_BONDING;
655
656 auth |= (req->auth_req | rsp->auth_req) & SMP_AUTH_MITM;
657
Johan Hedberg476585e2012-06-06 18:54:15 +0800658 ret = tk_request(conn, 0, auth, req->io_capability, rsp->io_capability);
Brian Gix2b64d152011-12-21 16:12:12 -0800659 if (ret)
660 return SMP_UNSPECIFIED;
661
662 set_bit(SMP_FLAG_CFM_PENDING, &smp->smp_flags);
663
664 /* Can't compose response until we have been confirmed */
665 if (!test_bit(SMP_FLAG_TK_VALID, &smp->smp_flags))
666 return 0;
667
Vinicius Costa Gomes8aab4752011-09-05 14:31:31 -0300668 queue_work(hdev->workqueue, &smp->confirm);
Vinicius Costa Gomesda85e5e2011-06-09 18:50:53 -0300669
670 return 0;
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300671}
672
Vinicius Costa Gomesda85e5e2011-06-09 18:50:53 -0300673static u8 smp_cmd_pairing_confirm(struct l2cap_conn *conn, struct sk_buff *skb)
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300674{
Vinicius Costa Gomes1c1def02011-09-05 14:31:30 -0300675 struct smp_chan *smp = conn->smp_chan;
Vinicius Costa Gomes8aab4752011-09-05 14:31:31 -0300676 struct hci_dev *hdev = conn->hcon->hdev;
Anderson Briglia7d24ddc2011-06-09 18:50:46 -0300677
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300678 BT_DBG("conn %p %s", conn, conn->hcon->out ? "master" : "slave");
679
Vinicius Costa Gomes1c1def02011-09-05 14:31:30 -0300680 memcpy(smp->pcnf, skb->data, sizeof(smp->pcnf));
681 skb_pull(skb, sizeof(smp->pcnf));
Anderson Briglia7d24ddc2011-06-09 18:50:46 -0300682
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300683 if (conn->hcon->out) {
Anderson Briglia7d24ddc2011-06-09 18:50:46 -0300684 u8 random[16];
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300685
Vinicius Costa Gomes1c1def02011-09-05 14:31:30 -0300686 swap128(smp->prnd, random);
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300687 smp_send_cmd(conn, SMP_CMD_PAIRING_RANDOM, sizeof(random),
Anderson Briglia7d24ddc2011-06-09 18:50:46 -0300688 random);
Brian Gix2b64d152011-12-21 16:12:12 -0800689 } else if (test_bit(SMP_FLAG_TK_VALID, &smp->smp_flags)) {
Vinicius Costa Gomes8aab4752011-09-05 14:31:31 -0300690 queue_work(hdev->workqueue, &smp->confirm);
Brian Gix2b64d152011-12-21 16:12:12 -0800691 } else {
692 set_bit(SMP_FLAG_CFM_PENDING, &smp->smp_flags);
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300693 }
Vinicius Costa Gomesda85e5e2011-06-09 18:50:53 -0300694
695 return 0;
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300696}
697
Vinicius Costa Gomesda85e5e2011-06-09 18:50:53 -0300698static u8 smp_cmd_pairing_random(struct l2cap_conn *conn, struct sk_buff *skb)
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300699{
Vinicius Costa Gomes1c1def02011-09-05 14:31:30 -0300700 struct smp_chan *smp = conn->smp_chan;
Vinicius Costa Gomes8aab4752011-09-05 14:31:31 -0300701 struct hci_dev *hdev = conn->hcon->hdev;
Anderson Briglia7d24ddc2011-06-09 18:50:46 -0300702
Vinicius Costa Gomes8aab4752011-09-05 14:31:31 -0300703 BT_DBG("conn %p", conn);
Anderson Briglia7d24ddc2011-06-09 18:50:46 -0300704
Vinicius Costa Gomes8aab4752011-09-05 14:31:31 -0300705 swap128(skb->data, smp->rrnd);
706 skb_pull(skb, sizeof(smp->rrnd));
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300707
Vinicius Costa Gomes8aab4752011-09-05 14:31:31 -0300708 queue_work(hdev->workqueue, &smp->random);
Vinicius Costa Gomesda85e5e2011-06-09 18:50:53 -0300709
710 return 0;
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300711}
712
Johan Hedberg4dab7862012-06-07 14:58:37 +0800713static u8 smp_ltk_encrypt(struct l2cap_conn *conn, u8 sec_level)
Vinicius Costa Gomes988c5992011-08-25 20:02:28 -0300714{
Vinicius Costa Gomesc9839a12012-02-02 21:08:01 -0300715 struct smp_ltk *key;
Vinicius Costa Gomes988c5992011-08-25 20:02:28 -0300716 struct hci_conn *hcon = conn->hcon;
717
Vinicius Costa Gomesc9839a12012-02-02 21:08:01 -0300718 key = hci_find_ltk_by_addr(hcon->hdev, conn->dst, hcon->dst_type);
Vinicius Costa Gomes988c5992011-08-25 20:02:28 -0300719 if (!key)
720 return 0;
721
Johan Hedberg4dab7862012-06-07 14:58:37 +0800722 if (sec_level > BT_SECURITY_MEDIUM && !key->authenticated)
723 return 0;
724
Johan Hedberg51a8efd2012-01-16 06:10:31 +0200725 if (test_and_set_bit(HCI_CONN_ENCRYPT_PEND, &hcon->flags))
Vinicius Costa Gomes988c5992011-08-25 20:02:28 -0300726 return 1;
727
Vinicius Costa Gomesc9839a12012-02-02 21:08:01 -0300728 hci_le_start_enc(hcon, key->ediv, key->rand, key->val);
729 hcon->enc_key_size = key->enc_size;
Vinicius Costa Gomes988c5992011-08-25 20:02:28 -0300730
731 return 1;
732
733}
Vinicius Costa Gomesda85e5e2011-06-09 18:50:53 -0300734static u8 smp_cmd_security_req(struct l2cap_conn *conn, struct sk_buff *skb)
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300735{
736 struct smp_cmd_security_req *rp = (void *) skb->data;
737 struct smp_cmd_pairing cp;
Vinicius Costa Gomesf1cb9af2011-01-26 21:42:57 -0300738 struct hci_conn *hcon = conn->hcon;
Vinicius Costa Gomes8aab4752011-09-05 14:31:31 -0300739 struct smp_chan *smp;
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300740
741 BT_DBG("conn %p", conn);
742
Brian Gix2b64d152011-12-21 16:12:12 -0800743 hcon->pending_sec_level = authreq_to_seclevel(rp->auth_req);
Vinicius Costa Gomesfeb45eb2011-08-25 20:02:35 -0300744
Johan Hedberg4dab7862012-06-07 14:58:37 +0800745 if (smp_ltk_encrypt(conn, hcon->pending_sec_level))
Vinicius Costa Gomes988c5992011-08-25 20:02:28 -0300746 return 0;
747
Johan Hedberg51a8efd2012-01-16 06:10:31 +0200748 if (test_and_set_bit(HCI_CONN_LE_SMP_PEND, &hcon->flags))
Vinicius Costa Gomesda85e5e2011-06-09 18:50:53 -0300749 return 0;
Vinicius Costa Gomesf1cb9af2011-01-26 21:42:57 -0300750
Vinicius Costa Gomes8aab4752011-09-05 14:31:31 -0300751 smp = smp_chan_create(conn);
Vinicius Costa Gomesd26a2342011-08-19 21:06:51 -0300752
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300753 skb_pull(skb, sizeof(*rp));
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300754
Vinicius Costa Gomesda85e5e2011-06-09 18:50:53 -0300755 memset(&cp, 0, sizeof(cp));
Vinicius Costa Gomes54790f72011-07-07 18:59:38 -0300756 build_pairing_cmd(conn, &cp, NULL, rp->auth_req);
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300757
Vinicius Costa Gomes1c1def02011-09-05 14:31:30 -0300758 smp->preq[0] = SMP_CMD_PAIRING_REQ;
759 memcpy(&smp->preq[1], &cp, sizeof(cp));
Anderson Brigliaf01ead32011-06-09 18:50:45 -0300760
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300761 smp_send_cmd(conn, SMP_CMD_PAIRING_REQ, sizeof(cp), &cp);
Vinicius Costa Gomesf1cb9af2011-01-26 21:42:57 -0300762
Vinicius Costa Gomesda85e5e2011-06-09 18:50:53 -0300763 return 0;
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300764}
765
Vinicius Costa Gomescc110922012-08-23 21:32:43 -0300766int smp_conn_security(struct hci_conn *hcon, __u8 sec_level)
Anderson Brigliaeb492e02011-06-09 18:50:40 -0300767{
Vinicius Costa Gomescc110922012-08-23 21:32:43 -0300768 struct l2cap_conn *conn = hcon->l2cap_data;
Vinicius Costa Gomes1c1def02011-09-05 14:31:30 -0300769 struct smp_chan *smp = conn->smp_chan;
Brian Gix2b64d152011-12-21 16:12:12 -0800770 __u8 authreq;
Anderson Brigliaeb492e02011-06-09 18:50:40 -0300771
Vinicius Costa Gomes3a0259b2011-06-09 18:50:43 -0300772 BT_DBG("conn %p hcon %p level 0x%2.2x", conn, hcon, sec_level);
773
Johan Hedberg757aee02013-04-24 13:05:32 +0300774 if (!test_bit(HCI_LE_ENABLED, &hcon->hdev->dev_flags))
Andre Guedes2e65c9d2011-06-30 19:20:56 -0300775 return 1;
776
Vinicius Costa Gomesf1cb9af2011-01-26 21:42:57 -0300777 if (sec_level == BT_SECURITY_LOW)
Anderson Brigliaeb492e02011-06-09 18:50:40 -0300778 return 1;
Vinicius Costa Gomesf1cb9af2011-01-26 21:42:57 -0300779
780 if (hcon->sec_level >= sec_level)
781 return 1;
782
Vinicius Costa Gomes988c5992011-08-25 20:02:28 -0300783 if (hcon->link_mode & HCI_LM_MASTER)
Johan Hedberg4dab7862012-06-07 14:58:37 +0800784 if (smp_ltk_encrypt(conn, sec_level))
Vinicius Costa Gomes02bc7452011-07-07 18:59:41 -0300785 goto done;
Vinicius Costa Gomesd26a2342011-08-19 21:06:51 -0300786
Johan Hedberg51a8efd2012-01-16 06:10:31 +0200787 if (test_and_set_bit(HCI_CONN_LE_SMP_PEND, &hcon->flags))
Vinicius Costa Gomesd26a2342011-08-19 21:06:51 -0300788 return 0;
789
Vinicius Costa Gomes8aab4752011-09-05 14:31:31 -0300790 smp = smp_chan_create(conn);
Brian Gix2b64d152011-12-21 16:12:12 -0800791 if (!smp)
792 return 1;
793
794 authreq = seclevel_to_authreq(sec_level);
Vinicius Costa Gomesd26a2342011-08-19 21:06:51 -0300795
Vinicius Costa Gomesd26a2342011-08-19 21:06:51 -0300796 if (hcon->link_mode & HCI_LM_MASTER) {
797 struct smp_cmd_pairing cp;
Anderson Brigliaf01ead32011-06-09 18:50:45 -0300798
Brian Gix2b64d152011-12-21 16:12:12 -0800799 build_pairing_cmd(conn, &cp, NULL, authreq);
Vinicius Costa Gomes1c1def02011-09-05 14:31:30 -0300800 smp->preq[0] = SMP_CMD_PAIRING_REQ;
801 memcpy(&smp->preq[1], &cp, sizeof(cp));
Anderson Brigliaf01ead32011-06-09 18:50:45 -0300802
Anderson Brigliaeb492e02011-06-09 18:50:40 -0300803 smp_send_cmd(conn, SMP_CMD_PAIRING_REQ, sizeof(cp), &cp);
804 } else {
805 struct smp_cmd_security_req cp;
Brian Gix2b64d152011-12-21 16:12:12 -0800806 cp.auth_req = authreq;
Anderson Brigliaeb492e02011-06-09 18:50:40 -0300807 smp_send_cmd(conn, SMP_CMD_SECURITY_REQ, sizeof(cp), &cp);
808 }
809
Vinicius Costa Gomes02bc7452011-07-07 18:59:41 -0300810done:
Vinicius Costa Gomesf1cb9af2011-01-26 21:42:57 -0300811 hcon->pending_sec_level = sec_level;
Vinicius Costa Gomesf1cb9af2011-01-26 21:42:57 -0300812
Anderson Brigliaeb492e02011-06-09 18:50:40 -0300813 return 0;
814}
815
Vinicius Costa Gomes7034b912011-07-07 18:59:34 -0300816static int smp_cmd_encrypt_info(struct l2cap_conn *conn, struct sk_buff *skb)
817{
Vinicius Costa Gomes16b90832011-07-07 18:59:39 -0300818 struct smp_cmd_encrypt_info *rp = (void *) skb->data;
Vinicius Costa Gomes1c1def02011-09-05 14:31:30 -0300819 struct smp_chan *smp = conn->smp_chan;
Vinicius Costa Gomes16b90832011-07-07 18:59:39 -0300820
821 skb_pull(skb, sizeof(*rp));
822
Vinicius Costa Gomes1c1def02011-09-05 14:31:30 -0300823 memcpy(smp->tk, rp->ltk, sizeof(smp->tk));
Vinicius Costa Gomes16b90832011-07-07 18:59:39 -0300824
Vinicius Costa Gomes7034b912011-07-07 18:59:34 -0300825 return 0;
826}
827
828static int smp_cmd_master_ident(struct l2cap_conn *conn, struct sk_buff *skb)
829{
Vinicius Costa Gomes16b90832011-07-07 18:59:39 -0300830 struct smp_cmd_master_ident *rp = (void *) skb->data;
Vinicius Costa Gomes1c1def02011-09-05 14:31:30 -0300831 struct smp_chan *smp = conn->smp_chan;
Vinicius Costa Gomesc9839a12012-02-02 21:08:01 -0300832 struct hci_dev *hdev = conn->hcon->hdev;
833 struct hci_conn *hcon = conn->hcon;
834 u8 authenticated;
Vinicius Costa Gomes7034b912011-07-07 18:59:34 -0300835
Vinicius Costa Gomes16b90832011-07-07 18:59:39 -0300836 skb_pull(skb, sizeof(*rp));
837
Vinicius Costa Gomesc9839a12012-02-02 21:08:01 -0300838 hci_dev_lock(hdev);
839 authenticated = (conn->hcon->sec_level == BT_SECURITY_HIGH);
840 hci_add_ltk(conn->hcon->hdev, conn->dst, hcon->dst_type,
Gustavo F. Padovan04124682012-03-08 01:25:00 -0300841 HCI_SMP_LTK, 1, authenticated, smp->tk, smp->enc_key_size,
842 rp->ediv, rp->rand);
Vinicius Costa Gomes7034b912011-07-07 18:59:34 -0300843 smp_distribute_keys(conn, 1);
Vinicius Costa Gomesc9839a12012-02-02 21:08:01 -0300844 hci_dev_unlock(hdev);
Vinicius Costa Gomes7034b912011-07-07 18:59:34 -0300845
846 return 0;
847}
848
Anderson Brigliaeb492e02011-06-09 18:50:40 -0300849int smp_sig_channel(struct l2cap_conn *conn, struct sk_buff *skb)
850{
Marcel Holtmann7b9899d2013-10-03 00:00:57 -0700851 struct hci_conn *hcon = conn->hcon;
Marcel Holtmann92381f52013-10-03 01:23:08 -0700852 __u8 code, reason;
Anderson Brigliaeb492e02011-06-09 18:50:40 -0300853 int err = 0;
854
Marcel Holtmann7b9899d2013-10-03 00:00:57 -0700855 if (hcon->type != LE_LINK) {
856 kfree_skb(skb);
857 return -ENOTSUPP;
858 }
859
Marcel Holtmann92381f52013-10-03 01:23:08 -0700860 if (skb->len < 1) {
861 kfree_skb(skb);
862 return -EILSEQ;
863 }
864
Johan Hedberg757aee02013-04-24 13:05:32 +0300865 if (!test_bit(HCI_LE_ENABLED, &conn->hcon->hdev->dev_flags)) {
Andre Guedes2e65c9d2011-06-30 19:20:56 -0300866 err = -ENOTSUPP;
867 reason = SMP_PAIRING_NOTSUPP;
868 goto done;
869 }
870
Marcel Holtmann92381f52013-10-03 01:23:08 -0700871 code = skb->data[0];
Anderson Brigliaeb492e02011-06-09 18:50:40 -0300872 skb_pull(skb, sizeof(code));
873
Johan Hedberg8cf9fa12013-01-29 10:44:23 -0600874 /*
875 * The SMP context must be initialized for all other PDUs except
876 * pairing and security requests. If we get any other PDU when
877 * not initialized simply disconnect (done if this function
878 * returns an error).
879 */
880 if (code != SMP_CMD_PAIRING_REQ && code != SMP_CMD_SECURITY_REQ &&
881 !conn->smp_chan) {
882 BT_ERR("Unexpected SMP command 0x%02x. Disconnecting.", code);
883 kfree_skb(skb);
884 return -ENOTSUPP;
885 }
886
Anderson Brigliaeb492e02011-06-09 18:50:40 -0300887 switch (code) {
888 case SMP_CMD_PAIRING_REQ:
Vinicius Costa Gomesda85e5e2011-06-09 18:50:53 -0300889 reason = smp_cmd_pairing_req(conn, skb);
Anderson Brigliaeb492e02011-06-09 18:50:40 -0300890 break;
891
892 case SMP_CMD_PAIRING_FAIL:
Brian Gix4f957a72011-11-23 08:28:36 -0800893 smp_failure(conn, skb->data[0], 0);
Vinicius Costa Gomesda85e5e2011-06-09 18:50:53 -0300894 reason = 0;
895 err = -EPERM;
Anderson Brigliaeb492e02011-06-09 18:50:40 -0300896 break;
897
898 case SMP_CMD_PAIRING_RSP:
Vinicius Costa Gomesda85e5e2011-06-09 18:50:53 -0300899 reason = smp_cmd_pairing_rsp(conn, skb);
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300900 break;
901
902 case SMP_CMD_SECURITY_REQ:
Vinicius Costa Gomesda85e5e2011-06-09 18:50:53 -0300903 reason = smp_cmd_security_req(conn, skb);
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300904 break;
905
Anderson Brigliaeb492e02011-06-09 18:50:40 -0300906 case SMP_CMD_PAIRING_CONFIRM:
Vinicius Costa Gomesda85e5e2011-06-09 18:50:53 -0300907 reason = smp_cmd_pairing_confirm(conn, skb);
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300908 break;
909
Anderson Brigliaeb492e02011-06-09 18:50:40 -0300910 case SMP_CMD_PAIRING_RANDOM:
Vinicius Costa Gomesda85e5e2011-06-09 18:50:53 -0300911 reason = smp_cmd_pairing_random(conn, skb);
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300912 break;
913
Anderson Brigliaeb492e02011-06-09 18:50:40 -0300914 case SMP_CMD_ENCRYPT_INFO:
Vinicius Costa Gomes7034b912011-07-07 18:59:34 -0300915 reason = smp_cmd_encrypt_info(conn, skb);
916 break;
917
Anderson Brigliaeb492e02011-06-09 18:50:40 -0300918 case SMP_CMD_MASTER_IDENT:
Vinicius Costa Gomes7034b912011-07-07 18:59:34 -0300919 reason = smp_cmd_master_ident(conn, skb);
920 break;
921
Anderson Brigliaeb492e02011-06-09 18:50:40 -0300922 case SMP_CMD_IDENT_INFO:
923 case SMP_CMD_IDENT_ADDR_INFO:
924 case SMP_CMD_SIGN_INFO:
Vinicius Costa Gomes7034b912011-07-07 18:59:34 -0300925 /* Just ignored */
926 reason = 0;
927 break;
928
Anderson Brigliaeb492e02011-06-09 18:50:40 -0300929 default:
930 BT_DBG("Unknown command code 0x%2.2x", code);
931
932 reason = SMP_CMD_NOTSUPP;
Vinicius Costa Gomes3a0259b2011-06-09 18:50:43 -0300933 err = -EOPNOTSUPP;
934 goto done;
935 }
936
937done:
938 if (reason)
Brian Gix4f957a72011-11-23 08:28:36 -0800939 smp_failure(conn, reason, 1);
Anderson Brigliaeb492e02011-06-09 18:50:40 -0300940
941 kfree_skb(skb);
942 return err;
943}
Vinicius Costa Gomes7034b912011-07-07 18:59:34 -0300944
945int smp_distribute_keys(struct l2cap_conn *conn, __u8 force)
946{
947 struct smp_cmd_pairing *req, *rsp;
Vinicius Costa Gomes1c1def02011-09-05 14:31:30 -0300948 struct smp_chan *smp = conn->smp_chan;
Vinicius Costa Gomes7034b912011-07-07 18:59:34 -0300949 __u8 *keydist;
950
951 BT_DBG("conn %p force %d", conn, force);
952
Johan Hedberg51a8efd2012-01-16 06:10:31 +0200953 if (!test_bit(HCI_CONN_LE_SMP_PEND, &conn->hcon->flags))
Vinicius Costa Gomesd26a2342011-08-19 21:06:51 -0300954 return 0;
955
Vinicius Costa Gomes1c1def02011-09-05 14:31:30 -0300956 rsp = (void *) &smp->prsp[1];
Vinicius Costa Gomes7034b912011-07-07 18:59:34 -0300957
958 /* The responder sends its keys first */
959 if (!force && conn->hcon->out && (rsp->resp_key_dist & 0x07))
960 return 0;
961
Vinicius Costa Gomes1c1def02011-09-05 14:31:30 -0300962 req = (void *) &smp->preq[1];
Vinicius Costa Gomes7034b912011-07-07 18:59:34 -0300963
964 if (conn->hcon->out) {
965 keydist = &rsp->init_key_dist;
966 *keydist &= req->init_key_dist;
967 } else {
968 keydist = &rsp->resp_key_dist;
969 *keydist &= req->resp_key_dist;
970 }
971
972
973 BT_DBG("keydist 0x%x", *keydist);
974
975 if (*keydist & SMP_DIST_ENC_KEY) {
976 struct smp_cmd_encrypt_info enc;
977 struct smp_cmd_master_ident ident;
Vinicius Costa Gomesc9839a12012-02-02 21:08:01 -0300978 struct hci_conn *hcon = conn->hcon;
979 u8 authenticated;
Vinicius Costa Gomes7034b912011-07-07 18:59:34 -0300980 __le16 ediv;
981
982 get_random_bytes(enc.ltk, sizeof(enc.ltk));
983 get_random_bytes(&ediv, sizeof(ediv));
984 get_random_bytes(ident.rand, sizeof(ident.rand));
985
986 smp_send_cmd(conn, SMP_CMD_ENCRYPT_INFO, sizeof(enc), &enc);
987
Vinicius Costa Gomesc9839a12012-02-02 21:08:01 -0300988 authenticated = hcon->sec_level == BT_SECURITY_HIGH;
989 hci_add_ltk(conn->hcon->hdev, conn->dst, hcon->dst_type,
Gustavo F. Padovan04124682012-03-08 01:25:00 -0300990 HCI_SMP_LTK_SLAVE, 1, authenticated,
991 enc.ltk, smp->enc_key_size, ediv, ident.rand);
Vinicius Costa Gomes16b90832011-07-07 18:59:39 -0300992
Andrei Emeltchenko58115372012-03-12 12:13:06 +0200993 ident.ediv = ediv;
Vinicius Costa Gomes7034b912011-07-07 18:59:34 -0300994
995 smp_send_cmd(conn, SMP_CMD_MASTER_IDENT, sizeof(ident), &ident);
996
997 *keydist &= ~SMP_DIST_ENC_KEY;
998 }
999
1000 if (*keydist & SMP_DIST_ID_KEY) {
1001 struct smp_cmd_ident_addr_info addrinfo;
1002 struct smp_cmd_ident_info idinfo;
1003
1004 /* Send a dummy key */
1005 get_random_bytes(idinfo.irk, sizeof(idinfo.irk));
1006
1007 smp_send_cmd(conn, SMP_CMD_IDENT_INFO, sizeof(idinfo), &idinfo);
1008
1009 /* Just public address */
1010 memset(&addrinfo, 0, sizeof(addrinfo));
1011 bacpy(&addrinfo.bdaddr, conn->src);
1012
1013 smp_send_cmd(conn, SMP_CMD_IDENT_ADDR_INFO, sizeof(addrinfo),
1014 &addrinfo);
1015
1016 *keydist &= ~SMP_DIST_ID_KEY;
1017 }
1018
1019 if (*keydist & SMP_DIST_SIGN) {
1020 struct smp_cmd_sign_info sign;
1021
1022 /* Send a dummy key */
1023 get_random_bytes(sign.csrk, sizeof(sign.csrk));
1024
1025 smp_send_cmd(conn, SMP_CMD_SIGN_INFO, sizeof(sign), &sign);
1026
1027 *keydist &= ~SMP_DIST_SIGN;
1028 }
1029
Vinicius Costa Gomesd26a2342011-08-19 21:06:51 -03001030 if (conn->hcon->out || force) {
Johan Hedberg51a8efd2012-01-16 06:10:31 +02001031 clear_bit(HCI_CONN_LE_SMP_PEND, &conn->hcon->flags);
Gustavo F. Padovan6c9d42a2011-12-20 10:57:27 -02001032 cancel_delayed_work_sync(&conn->security_timer);
Vinicius Costa Gomes8aab4752011-09-05 14:31:31 -03001033 smp_chan_destroy(conn);
Vinicius Costa Gomesd26a2342011-08-19 21:06:51 -03001034 }
1035
Vinicius Costa Gomes7034b912011-07-07 18:59:34 -03001036 return 0;
1037}