blob: ccad6c1e3ec320659a6b1e512d90cbd66ad04c49 [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>
Anderson Brigliaeb492e02011-06-09 18:50:40 -030031#include <net/bluetooth/smp.h>
Anderson Brigliad22ef0b2011-06-09 18:50:44 -030032
Marcel Holtmann17b02e62012-03-01 14:32:37 -080033#define SMP_TIMEOUT msecs_to_jiffies(30000)
Vinicius Costa Gomes5d3de7d2011-06-14 13:37:41 -030034
Johan Hedberg065a13e2012-10-11 16:26:06 +020035#define AUTH_REQ_MASK 0x07
36
Anderson Brigliad22ef0b2011-06-09 18:50:44 -030037static inline void swap128(u8 src[16], u8 dst[16])
38{
39 int i;
40 for (i = 0; i < 16; i++)
41 dst[15 - i] = src[i];
42}
43
44static inline void swap56(u8 src[7], u8 dst[7])
45{
46 int i;
47 for (i = 0; i < 7; i++)
48 dst[6 - i] = src[i];
49}
50
51static int smp_e(struct crypto_blkcipher *tfm, const u8 *k, u8 *r)
52{
53 struct blkcipher_desc desc;
54 struct scatterlist sg;
55 int err, iv_len;
56 unsigned char iv[128];
57
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
74 iv_len = crypto_blkcipher_ivsize(tfm);
75 if (iv_len) {
76 memset(&iv, 0xff, iv_len);
77 crypto_blkcipher_set_iv(tfm, iv, iv_len);
78 }
79
80 err = crypto_blkcipher_encrypt(&desc, &sg, &sg, 16);
81 if (err)
82 BT_ERR("Encrypt data error %d", err);
83
84 return err;
85}
86
87static int smp_c1(struct crypto_blkcipher *tfm, u8 k[16], u8 r[16],
88 u8 preq[7], u8 pres[7], u8 _iat, bdaddr_t *ia,
89 u8 _rat, bdaddr_t *ra, u8 res[16])
90{
91 u8 p1[16], p2[16];
92 int err;
93
94 memset(p1, 0, 16);
95
96 /* p1 = pres || preq || _rat || _iat */
97 swap56(pres, p1);
98 swap56(preq, p1 + 7);
99 p1[14] = _rat;
100 p1[15] = _iat;
101
102 memset(p2, 0, 16);
103
104 /* p2 = padding || ia || ra */
105 baswap((bdaddr_t *) (p2 + 4), ia);
106 baswap((bdaddr_t *) (p2 + 10), ra);
107
108 /* res = r XOR p1 */
109 u128_xor((u128 *) res, (u128 *) r, (u128 *) p1);
110
111 /* res = e(k, res) */
112 err = smp_e(tfm, k, res);
113 if (err) {
114 BT_ERR("Encrypt data error");
115 return err;
116 }
117
118 /* res = res XOR p2 */
119 u128_xor((u128 *) res, (u128 *) res, (u128 *) p2);
120
121 /* res = e(k, res) */
122 err = smp_e(tfm, k, res);
123 if (err)
124 BT_ERR("Encrypt data error");
125
126 return err;
127}
128
129static int smp_s1(struct crypto_blkcipher *tfm, u8 k[16],
130 u8 r1[16], u8 r2[16], u8 _r[16])
131{
132 int err;
133
134 /* Just least significant octets from r1 and r2 are considered */
135 memcpy(_r, r1 + 8, 8);
136 memcpy(_r + 8, r2 + 8, 8);
137
138 err = smp_e(tfm, k, _r);
139 if (err)
140 BT_ERR("Encrypt data error");
141
142 return err;
143}
144
145static int smp_rand(u8 *buf)
146{
147 get_random_bytes(buf, 16);
148
149 return 0;
150}
Anderson Brigliaeb492e02011-06-09 18:50:40 -0300151
152static struct sk_buff *smp_build_cmd(struct l2cap_conn *conn, u8 code,
153 u16 dlen, void *data)
154{
155 struct sk_buff *skb;
156 struct l2cap_hdr *lh;
157 int len;
158
159 len = L2CAP_HDR_SIZE + sizeof(code) + dlen;
160
161 if (len > conn->mtu)
162 return NULL;
163
164 skb = bt_skb_alloc(len, GFP_ATOMIC);
165 if (!skb)
166 return NULL;
167
168 lh = (struct l2cap_hdr *) skb_put(skb, L2CAP_HDR_SIZE);
169 lh->len = cpu_to_le16(sizeof(code) + dlen);
Syam Sidhardhand8aece22012-10-10 22:09:28 +0530170 lh->cid = __constant_cpu_to_le16(L2CAP_CID_SMP);
Anderson Brigliaeb492e02011-06-09 18:50:40 -0300171
172 memcpy(skb_put(skb, sizeof(code)), &code, sizeof(code));
173
174 memcpy(skb_put(skb, dlen), data, dlen);
175
176 return skb;
177}
178
179static void smp_send_cmd(struct l2cap_conn *conn, u8 code, u16 len, void *data)
180{
181 struct sk_buff *skb = smp_build_cmd(conn, code, len, data);
182
183 BT_DBG("code 0x%2.2x", code);
184
185 if (!skb)
186 return;
187
Luiz Augusto von Dentz73d80de2011-11-02 15:52:01 +0200188 skb->priority = HCI_PRIO_MAX;
189 hci_send_acl(conn->hchan, skb, 0);
Vinicius Costa Gomese2dcd112011-08-19 21:06:50 -0300190
Gustavo F. Padovan6c9d42a2011-12-20 10:57:27 -0200191 cancel_delayed_work_sync(&conn->security_timer);
Marcel Holtmann17b02e62012-03-01 14:32:37 -0800192 schedule_delayed_work(&conn->security_timer, SMP_TIMEOUT);
Anderson Brigliaeb492e02011-06-09 18:50:40 -0300193}
194
Brian Gix2b64d152011-12-21 16:12:12 -0800195static __u8 authreq_to_seclevel(__u8 authreq)
196{
197 if (authreq & SMP_AUTH_MITM)
198 return BT_SECURITY_HIGH;
199 else
200 return BT_SECURITY_MEDIUM;
201}
202
203static __u8 seclevel_to_authreq(__u8 sec_level)
204{
205 switch (sec_level) {
206 case BT_SECURITY_HIGH:
207 return SMP_AUTH_MITM | SMP_AUTH_BONDING;
208 case BT_SECURITY_MEDIUM:
209 return SMP_AUTH_BONDING;
210 default:
211 return SMP_AUTH_NONE;
212 }
213}
214
Vinicius Costa Gomesb8e66ea2011-06-09 18:50:52 -0300215static void build_pairing_cmd(struct l2cap_conn *conn,
Vinicius Costa Gomes54790f72011-07-07 18:59:38 -0300216 struct smp_cmd_pairing *req,
217 struct smp_cmd_pairing *rsp,
218 __u8 authreq)
Vinicius Costa Gomesb8e66ea2011-06-09 18:50:52 -0300219{
Brian Gix2b64d152011-12-21 16:12:12 -0800220 u8 dist_keys = 0;
Vinicius Costa Gomes54790f72011-07-07 18:59:38 -0300221
Johan Hedberga8b2d5c2012-01-08 23:11:15 +0200222 if (test_bit(HCI_PAIRABLE, &conn->hcon->hdev->dev_flags)) {
Vinicius Costa Gomesca10b5e2011-08-25 20:02:37 -0300223 dist_keys = SMP_DIST_ENC_KEY;
Vinicius Costa Gomes54790f72011-07-07 18:59:38 -0300224 authreq |= SMP_AUTH_BONDING;
Brian Gix2b64d152011-12-21 16:12:12 -0800225 } else {
226 authreq &= ~SMP_AUTH_BONDING;
Vinicius Costa Gomes54790f72011-07-07 18:59:38 -0300227 }
228
229 if (rsp == NULL) {
230 req->io_capability = conn->hcon->io_capability;
231 req->oob_flag = SMP_OOB_NOT_PRESENT;
232 req->max_key_size = SMP_MAX_ENC_KEY_SIZE;
Brian Gix2b64d152011-12-21 16:12:12 -0800233 req->init_key_dist = 0;
Vinicius Costa Gomes54790f72011-07-07 18:59:38 -0300234 req->resp_key_dist = dist_keys;
Johan Hedberg065a13e2012-10-11 16:26:06 +0200235 req->auth_req = (authreq & AUTH_REQ_MASK);
Vinicius Costa Gomes54790f72011-07-07 18:59:38 -0300236 return;
237 }
238
239 rsp->io_capability = conn->hcon->io_capability;
240 rsp->oob_flag = SMP_OOB_NOT_PRESENT;
241 rsp->max_key_size = SMP_MAX_ENC_KEY_SIZE;
Brian Gix2b64d152011-12-21 16:12:12 -0800242 rsp->init_key_dist = 0;
Vinicius Costa Gomes54790f72011-07-07 18:59:38 -0300243 rsp->resp_key_dist = req->resp_key_dist & dist_keys;
Johan Hedberg065a13e2012-10-11 16:26:06 +0200244 rsp->auth_req = (authreq & AUTH_REQ_MASK);
Vinicius Costa Gomesb8e66ea2011-06-09 18:50:52 -0300245}
246
Vinicius Costa Gomes3158c502011-06-14 13:37:42 -0300247static u8 check_enc_key_size(struct l2cap_conn *conn, __u8 max_key_size)
248{
Vinicius Costa Gomes1c1def02011-09-05 14:31:30 -0300249 struct smp_chan *smp = conn->smp_chan;
250
Vinicius Costa Gomes3158c502011-06-14 13:37:42 -0300251 if ((max_key_size > SMP_MAX_ENC_KEY_SIZE) ||
252 (max_key_size < SMP_MIN_ENC_KEY_SIZE))
253 return SMP_ENC_KEY_SIZE;
254
Vinicius Costa Gomesf7aa6112012-01-30 19:29:12 -0300255 smp->enc_key_size = max_key_size;
Vinicius Costa Gomes3158c502011-06-14 13:37:42 -0300256
257 return 0;
258}
259
Brian Gix4f957a72011-11-23 08:28:36 -0800260static void smp_failure(struct l2cap_conn *conn, u8 reason, u8 send)
261{
Johan Hedbergbab73cb2012-02-09 16:07:29 +0200262 struct hci_conn *hcon = conn->hcon;
263
Brian Gix4f957a72011-11-23 08:28:36 -0800264 if (send)
265 smp_send_cmd(conn, SMP_CMD_PAIRING_FAIL, sizeof(reason),
266 &reason);
267
Johan Hedberg51a8efd2012-01-16 06:10:31 +0200268 clear_bit(HCI_CONN_ENCRYPT_PEND, &conn->hcon->flags);
Johan Hedbergbab73cb2012-02-09 16:07:29 +0200269 mgmt_auth_failed(conn->hcon->hdev, conn->dst, hcon->type,
Paulo Sérgio896ea282012-10-25 16:55:51 -0300270 hcon->dst_type, HCI_ERROR_AUTH_FAILURE);
Vinicius Costa Gomesf1c09c02012-02-01 18:27:56 -0300271
Andre Guedes61a0cfb2012-08-01 20:34:15 -0300272 cancel_delayed_work_sync(&conn->security_timer);
273
274 if (test_and_clear_bit(HCI_CONN_LE_SMP_PEND, &conn->hcon->flags))
Vinicius Costa Gomesf1c09c02012-02-01 18:27:56 -0300275 smp_chan_destroy(conn);
Brian Gix4f957a72011-11-23 08:28:36 -0800276}
277
Brian Gix2b64d152011-12-21 16:12:12 -0800278#define JUST_WORKS 0x00
279#define JUST_CFM 0x01
280#define REQ_PASSKEY 0x02
281#define CFM_PASSKEY 0x03
282#define REQ_OOB 0x04
283#define OVERLAP 0xFF
284
285static const u8 gen_method[5][5] = {
286 { JUST_WORKS, JUST_CFM, REQ_PASSKEY, JUST_WORKS, REQ_PASSKEY },
287 { JUST_WORKS, JUST_CFM, REQ_PASSKEY, JUST_WORKS, REQ_PASSKEY },
288 { CFM_PASSKEY, CFM_PASSKEY, REQ_PASSKEY, JUST_WORKS, CFM_PASSKEY },
289 { JUST_WORKS, JUST_CFM, JUST_WORKS, JUST_WORKS, JUST_CFM },
290 { CFM_PASSKEY, CFM_PASSKEY, REQ_PASSKEY, JUST_WORKS, OVERLAP },
291};
292
293static int tk_request(struct l2cap_conn *conn, u8 remote_oob, u8 auth,
294 u8 local_io, u8 remote_io)
295{
296 struct hci_conn *hcon = conn->hcon;
297 struct smp_chan *smp = conn->smp_chan;
298 u8 method;
299 u32 passkey = 0;
300 int ret = 0;
301
302 /* Initialize key for JUST WORKS */
303 memset(smp->tk, 0, sizeof(smp->tk));
304 clear_bit(SMP_FLAG_TK_VALID, &smp->smp_flags);
305
306 BT_DBG("tk_request: auth:%d lcl:%d rem:%d", auth, local_io, remote_io);
307
308 /* If neither side wants MITM, use JUST WORKS */
309 /* If either side has unknown io_caps, use JUST WORKS */
310 /* Otherwise, look up method from the table */
311 if (!(auth & SMP_AUTH_MITM) ||
312 local_io > SMP_IO_KEYBOARD_DISPLAY ||
313 remote_io > SMP_IO_KEYBOARD_DISPLAY)
314 method = JUST_WORKS;
315 else
Ido Yarivb3ff53f2012-03-05 20:07:08 +0200316 method = gen_method[remote_io][local_io];
Brian Gix2b64d152011-12-21 16:12:12 -0800317
318 /* If not bonding, don't ask user to confirm a Zero TK */
319 if (!(auth & SMP_AUTH_BONDING) && method == JUST_CFM)
320 method = JUST_WORKS;
321
322 /* If Just Works, Continue with Zero TK */
323 if (method == JUST_WORKS) {
324 set_bit(SMP_FLAG_TK_VALID, &smp->smp_flags);
325 return 0;
326 }
327
328 /* Not Just Works/Confirm results in MITM Authentication */
329 if (method != JUST_CFM)
330 set_bit(SMP_FLAG_MITM_AUTH, &smp->smp_flags);
331
332 /* If both devices have Keyoard-Display I/O, the master
333 * Confirms and the slave Enters the passkey.
334 */
335 if (method == OVERLAP) {
336 if (hcon->link_mode & HCI_LM_MASTER)
337 method = CFM_PASSKEY;
338 else
339 method = REQ_PASSKEY;
340 }
341
342 /* Generate random passkey. Not valid until confirmed. */
343 if (method == CFM_PASSKEY) {
344 u8 key[16];
345
346 memset(key, 0, sizeof(key));
347 get_random_bytes(&passkey, sizeof(passkey));
348 passkey %= 1000000;
349 put_unaligned_le32(passkey, key);
350 swap128(key, smp->tk);
351 BT_DBG("PassKey: %d", passkey);
352 }
353
354 hci_dev_lock(hcon->hdev);
355
356 if (method == REQ_PASSKEY)
Johan Hedberg272d90d2012-02-09 15:26:12 +0200357 ret = mgmt_user_passkey_request(hcon->hdev, conn->dst,
358 hcon->type, hcon->dst_type);
Brian Gix2b64d152011-12-21 16:12:12 -0800359 else
360 ret = mgmt_user_confirm_request(hcon->hdev, conn->dst,
Johan Hedberg272d90d2012-02-09 15:26:12 +0200361 hcon->type, hcon->dst_type,
Brian Gix2b64d152011-12-21 16:12:12 -0800362 cpu_to_le32(passkey), 0);
363
364 hci_dev_unlock(hcon->hdev);
365
366 return ret;
367}
368
Vinicius Costa Gomes8aab4752011-09-05 14:31:31 -0300369static void confirm_work(struct work_struct *work)
370{
371 struct smp_chan *smp = container_of(work, struct smp_chan, confirm);
372 struct l2cap_conn *conn = smp->conn;
373 struct crypto_blkcipher *tfm;
374 struct smp_cmd_pairing_confirm cp;
375 int ret;
376 u8 res[16], reason;
377
378 BT_DBG("conn %p", conn);
379
380 tfm = crypto_alloc_blkcipher("ecb(aes)", 0, CRYPTO_ALG_ASYNC);
381 if (IS_ERR(tfm)) {
382 reason = SMP_UNSPECIFIED;
383 goto error;
384 }
385
386 smp->tfm = tfm;
387
388 if (conn->hcon->out)
389 ret = smp_c1(tfm, smp->tk, smp->prnd, smp->preq, smp->prsp, 0,
Gustavo F. Padovan04124682012-03-08 01:25:00 -0300390 conn->src, conn->hcon->dst_type, conn->dst, res);
Vinicius Costa Gomes8aab4752011-09-05 14:31:31 -0300391 else
392 ret = smp_c1(tfm, smp->tk, smp->prnd, smp->preq, smp->prsp,
Gustavo F. Padovan04124682012-03-08 01:25:00 -0300393 conn->hcon->dst_type, conn->dst, 0, conn->src,
394 res);
Vinicius Costa Gomes8aab4752011-09-05 14:31:31 -0300395 if (ret) {
396 reason = SMP_UNSPECIFIED;
397 goto error;
398 }
399
Brian Gix2b64d152011-12-21 16:12:12 -0800400 clear_bit(SMP_FLAG_CFM_PENDING, &smp->smp_flags);
401
Vinicius Costa Gomes8aab4752011-09-05 14:31:31 -0300402 swap128(res, cp.confirm_val);
403 smp_send_cmd(smp->conn, SMP_CMD_PAIRING_CONFIRM, sizeof(cp), &cp);
404
405 return;
406
407error:
Brian Gix4f957a72011-11-23 08:28:36 -0800408 smp_failure(conn, reason, 1);
Vinicius Costa Gomes8aab4752011-09-05 14:31:31 -0300409}
410
411static void random_work(struct work_struct *work)
412{
413 struct smp_chan *smp = container_of(work, struct smp_chan, random);
414 struct l2cap_conn *conn = smp->conn;
415 struct hci_conn *hcon = conn->hcon;
416 struct crypto_blkcipher *tfm = smp->tfm;
417 u8 reason, confirm[16], res[16], key[16];
418 int ret;
419
420 if (IS_ERR_OR_NULL(tfm)) {
421 reason = SMP_UNSPECIFIED;
422 goto error;
423 }
424
425 BT_DBG("conn %p %s", conn, conn->hcon->out ? "master" : "slave");
426
427 if (hcon->out)
428 ret = smp_c1(tfm, smp->tk, smp->rrnd, smp->preq, smp->prsp, 0,
Gustavo F. Padovan04124682012-03-08 01:25:00 -0300429 conn->src, hcon->dst_type, conn->dst, res);
Vinicius Costa Gomes8aab4752011-09-05 14:31:31 -0300430 else
431 ret = smp_c1(tfm, smp->tk, smp->rrnd, smp->preq, smp->prsp,
Gustavo F. Padovan04124682012-03-08 01:25:00 -0300432 hcon->dst_type, conn->dst, 0, conn->src, res);
Vinicius Costa Gomes8aab4752011-09-05 14:31:31 -0300433 if (ret) {
434 reason = SMP_UNSPECIFIED;
435 goto error;
436 }
437
438 swap128(res, confirm);
439
440 if (memcmp(smp->pcnf, confirm, sizeof(smp->pcnf)) != 0) {
441 BT_ERR("Pairing failed (confirmation values mismatch)");
442 reason = SMP_CONFIRM_FAILED;
443 goto error;
444 }
445
446 if (hcon->out) {
447 u8 stk[16], rand[8];
448 __le16 ediv;
449
450 memset(rand, 0, sizeof(rand));
451 ediv = 0;
452
453 smp_s1(tfm, smp->tk, smp->rrnd, smp->prnd, key);
454 swap128(key, stk);
455
Vinicius Costa Gomesf7aa6112012-01-30 19:29:12 -0300456 memset(stk + smp->enc_key_size, 0,
Gustavo F. Padovan04124682012-03-08 01:25:00 -0300457 SMP_MAX_ENC_KEY_SIZE - smp->enc_key_size);
Vinicius Costa Gomes8aab4752011-09-05 14:31:31 -0300458
Johan Hedberg51a8efd2012-01-16 06:10:31 +0200459 if (test_and_set_bit(HCI_CONN_ENCRYPT_PEND, &hcon->flags)) {
Vinicius Costa Gomes8aab4752011-09-05 14:31:31 -0300460 reason = SMP_UNSPECIFIED;
461 goto error;
462 }
463
464 hci_le_start_enc(hcon, ediv, rand, stk);
Vinicius Costa Gomesf7aa6112012-01-30 19:29:12 -0300465 hcon->enc_key_size = smp->enc_key_size;
Vinicius Costa Gomes8aab4752011-09-05 14:31:31 -0300466 } else {
467 u8 stk[16], r[16], rand[8];
468 __le16 ediv;
469
470 memset(rand, 0, sizeof(rand));
471 ediv = 0;
472
473 swap128(smp->prnd, r);
474 smp_send_cmd(conn, SMP_CMD_PAIRING_RANDOM, sizeof(r), r);
475
476 smp_s1(tfm, smp->tk, smp->prnd, smp->rrnd, key);
477 swap128(key, stk);
478
Vinicius Costa Gomesf7aa6112012-01-30 19:29:12 -0300479 memset(stk + smp->enc_key_size, 0,
480 SMP_MAX_ENC_KEY_SIZE - smp->enc_key_size);
Vinicius Costa Gomes8aab4752011-09-05 14:31:31 -0300481
Vinicius Costa Gomesc9839a12012-02-02 21:08:01 -0300482 hci_add_ltk(hcon->hdev, conn->dst, hcon->dst_type,
Gustavo F. Padovan04124682012-03-08 01:25:00 -0300483 HCI_SMP_STK_SLAVE, 0, 0, stk, smp->enc_key_size,
484 ediv, rand);
Vinicius Costa Gomes8aab4752011-09-05 14:31:31 -0300485 }
486
487 return;
488
489error:
Brian Gix4f957a72011-11-23 08:28:36 -0800490 smp_failure(conn, reason, 1);
Vinicius Costa Gomes8aab4752011-09-05 14:31:31 -0300491}
492
493static struct smp_chan *smp_chan_create(struct l2cap_conn *conn)
494{
495 struct smp_chan *smp;
496
497 smp = kzalloc(sizeof(struct smp_chan), GFP_ATOMIC);
498 if (!smp)
499 return NULL;
500
501 INIT_WORK(&smp->confirm, confirm_work);
502 INIT_WORK(&smp->random, random_work);
503
504 smp->conn = conn;
505 conn->smp_chan = smp;
Brian Gix2b64d152011-12-21 16:12:12 -0800506 conn->hcon->smp_conn = conn;
Vinicius Costa Gomes8aab4752011-09-05 14:31:31 -0300507
508 hci_conn_hold(conn->hcon);
509
510 return smp;
511}
512
513void smp_chan_destroy(struct l2cap_conn *conn)
514{
Brian Gixc8eb9692011-11-23 08:28:35 -0800515 struct smp_chan *smp = conn->smp_chan;
516
Vinicius Costa Gomesf1c09c02012-02-01 18:27:56 -0300517 BUG_ON(!smp);
Brian Gixc8eb9692011-11-23 08:28:35 -0800518
519 if (smp->tfm)
520 crypto_free_blkcipher(smp->tfm);
521
522 kfree(smp);
523 conn->smp_chan = NULL;
Brian Gix2b64d152011-12-21 16:12:12 -0800524 conn->hcon->smp_conn = NULL;
David Herrmann76a68ba2013-04-06 20:28:37 +0200525 hci_conn_drop(conn->hcon);
Vinicius Costa Gomes8aab4752011-09-05 14:31:31 -0300526}
527
Brian Gix2b64d152011-12-21 16:12:12 -0800528int smp_user_confirm_reply(struct hci_conn *hcon, u16 mgmt_op, __le32 passkey)
529{
530 struct l2cap_conn *conn = hcon->smp_conn;
531 struct smp_chan *smp;
532 u32 value;
533 u8 key[16];
534
535 BT_DBG("");
536
537 if (!conn)
538 return -ENOTCONN;
539
540 smp = conn->smp_chan;
541
542 switch (mgmt_op) {
543 case MGMT_OP_USER_PASSKEY_REPLY:
544 value = le32_to_cpu(passkey);
545 memset(key, 0, sizeof(key));
546 BT_DBG("PassKey: %d", value);
547 put_unaligned_le32(value, key);
548 swap128(key, smp->tk);
549 /* Fall Through */
550 case MGMT_OP_USER_CONFIRM_REPLY:
551 set_bit(SMP_FLAG_TK_VALID, &smp->smp_flags);
552 break;
553 case MGMT_OP_USER_PASSKEY_NEG_REPLY:
554 case MGMT_OP_USER_CONFIRM_NEG_REPLY:
555 smp_failure(conn, SMP_PASSKEY_ENTRY_FAILED, 1);
556 return 0;
557 default:
558 smp_failure(conn, SMP_PASSKEY_ENTRY_FAILED, 1);
559 return -EOPNOTSUPP;
560 }
561
562 /* If it is our turn to send Pairing Confirm, do so now */
563 if (test_bit(SMP_FLAG_CFM_PENDING, &smp->smp_flags))
564 queue_work(hcon->hdev->workqueue, &smp->confirm);
565
566 return 0;
567}
568
Vinicius Costa Gomesda85e5e2011-06-09 18:50:53 -0300569static u8 smp_cmd_pairing_req(struct l2cap_conn *conn, struct sk_buff *skb)
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300570{
Vinicius Costa Gomes3158c502011-06-14 13:37:42 -0300571 struct smp_cmd_pairing rsp, *req = (void *) skb->data;
Vinicius Costa Gomes8aab4752011-09-05 14:31:31 -0300572 struct smp_chan *smp;
Vinicius Costa Gomes3158c502011-06-14 13:37:42 -0300573 u8 key_size;
Brian Gix2b64d152011-12-21 16:12:12 -0800574 u8 auth = SMP_AUTH_NONE;
Vinicius Costa Gomes8aab4752011-09-05 14:31:31 -0300575 int ret;
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300576
577 BT_DBG("conn %p", conn);
578
Brian Gix2b64d152011-12-21 16:12:12 -0800579 if (conn->hcon->link_mode & HCI_LM_MASTER)
580 return SMP_CMD_NOTSUPP;
581
Johan Hedberg51a8efd2012-01-16 06:10:31 +0200582 if (!test_and_set_bit(HCI_CONN_LE_SMP_PEND, &conn->hcon->flags))
Vinicius Costa Gomes8aab4752011-09-05 14:31:31 -0300583 smp = smp_chan_create(conn);
Andrei Emeltchenkod08fd0e2012-07-19 17:03:43 +0300584 else
585 smp = conn->smp_chan;
Vinicius Costa Gomes8aab4752011-09-05 14:31:31 -0300586
Andrei Emeltchenkod08fd0e2012-07-19 17:03:43 +0300587 if (!smp)
588 return SMP_UNSPECIFIED;
Vinicius Costa Gomesd26a2342011-08-19 21:06:51 -0300589
Vinicius Costa Gomes1c1def02011-09-05 14:31:30 -0300590 smp->preq[0] = SMP_CMD_PAIRING_REQ;
591 memcpy(&smp->preq[1], req, sizeof(*req));
Vinicius Costa Gomes3158c502011-06-14 13:37:42 -0300592 skb_pull(skb, sizeof(*req));
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300593
Brian Gix2b64d152011-12-21 16:12:12 -0800594 /* We didn't start the pairing, so match remote */
595 if (req->auth_req & SMP_AUTH_BONDING)
596 auth = req->auth_req;
Vinicius Costa Gomesda85e5e2011-06-09 18:50:53 -0300597
Ido Yarivfdde0a22012-03-05 20:09:38 +0200598 conn->hcon->pending_sec_level = authreq_to_seclevel(auth);
599
Brian Gix2b64d152011-12-21 16:12:12 -0800600 build_pairing_cmd(conn, req, &rsp, auth);
Vinicius Costa Gomes3158c502011-06-14 13:37:42 -0300601
602 key_size = min(req->max_key_size, rsp.max_key_size);
603 if (check_enc_key_size(conn, key_size))
604 return SMP_ENC_KEY_SIZE;
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300605
Vinicius Costa Gomes8aab4752011-09-05 14:31:31 -0300606 ret = smp_rand(smp->prnd);
607 if (ret)
608 return SMP_UNSPECIFIED;
609
Vinicius Costa Gomes1c1def02011-09-05 14:31:30 -0300610 smp->prsp[0] = SMP_CMD_PAIRING_RSP;
611 memcpy(&smp->prsp[1], &rsp, sizeof(rsp));
Anderson Brigliaf01ead32011-06-09 18:50:45 -0300612
Vinicius Costa Gomes3158c502011-06-14 13:37:42 -0300613 smp_send_cmd(conn, SMP_CMD_PAIRING_RSP, sizeof(rsp), &rsp);
Vinicius Costa Gomesda85e5e2011-06-09 18:50:53 -0300614
Brian Gix2b64d152011-12-21 16:12:12 -0800615 /* Request setup of TK */
616 ret = tk_request(conn, 0, auth, rsp.io_capability, req->io_capability);
617 if (ret)
618 return SMP_UNSPECIFIED;
619
Vinicius Costa Gomesda85e5e2011-06-09 18:50:53 -0300620 return 0;
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300621}
622
Vinicius Costa Gomesda85e5e2011-06-09 18:50:53 -0300623static u8 smp_cmd_pairing_rsp(struct l2cap_conn *conn, struct sk_buff *skb)
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300624{
Vinicius Costa Gomes3158c502011-06-14 13:37:42 -0300625 struct smp_cmd_pairing *req, *rsp = (void *) skb->data;
Vinicius Costa Gomes1c1def02011-09-05 14:31:30 -0300626 struct smp_chan *smp = conn->smp_chan;
Vinicius Costa Gomes8aab4752011-09-05 14:31:31 -0300627 struct hci_dev *hdev = conn->hcon->hdev;
Brian Gix2b64d152011-12-21 16:12:12 -0800628 u8 key_size, auth = SMP_AUTH_NONE;
Anderson Briglia7d24ddc2011-06-09 18:50:46 -0300629 int ret;
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300630
631 BT_DBG("conn %p", conn);
632
Brian Gix2b64d152011-12-21 16:12:12 -0800633 if (!(conn->hcon->link_mode & HCI_LM_MASTER))
634 return SMP_CMD_NOTSUPP;
635
Vinicius Costa Gomes3158c502011-06-14 13:37:42 -0300636 skb_pull(skb, sizeof(*rsp));
Vinicius Costa Gomesda85e5e2011-06-09 18:50:53 -0300637
Vinicius Costa Gomes1c1def02011-09-05 14:31:30 -0300638 req = (void *) &smp->preq[1];
Vinicius Costa Gomes3158c502011-06-14 13:37:42 -0300639
640 key_size = min(req->max_key_size, rsp->max_key_size);
641 if (check_enc_key_size(conn, key_size))
642 return SMP_ENC_KEY_SIZE;
643
Vinicius Costa Gomes1c1def02011-09-05 14:31:30 -0300644 ret = smp_rand(smp->prnd);
Anderson Briglia7d24ddc2011-06-09 18:50:46 -0300645 if (ret)
Vinicius Costa Gomesda85e5e2011-06-09 18:50:53 -0300646 return SMP_UNSPECIFIED;
Anderson Briglia7d24ddc2011-06-09 18:50:46 -0300647
Vinicius Costa Gomes8aab4752011-09-05 14:31:31 -0300648 smp->prsp[0] = SMP_CMD_PAIRING_RSP;
649 memcpy(&smp->prsp[1], rsp, sizeof(*rsp));
Anderson Briglia7d24ddc2011-06-09 18:50:46 -0300650
Brian Gix2b64d152011-12-21 16:12:12 -0800651 if ((req->auth_req & SMP_AUTH_BONDING) &&
652 (rsp->auth_req & SMP_AUTH_BONDING))
653 auth = SMP_AUTH_BONDING;
654
655 auth |= (req->auth_req | rsp->auth_req) & SMP_AUTH_MITM;
656
Johan Hedberg476585e2012-06-06 18:54:15 +0800657 ret = tk_request(conn, 0, auth, req->io_capability, rsp->io_capability);
Brian Gix2b64d152011-12-21 16:12:12 -0800658 if (ret)
659 return SMP_UNSPECIFIED;
660
661 set_bit(SMP_FLAG_CFM_PENDING, &smp->smp_flags);
662
663 /* Can't compose response until we have been confirmed */
664 if (!test_bit(SMP_FLAG_TK_VALID, &smp->smp_flags))
665 return 0;
666
Vinicius Costa Gomes8aab4752011-09-05 14:31:31 -0300667 queue_work(hdev->workqueue, &smp->confirm);
Vinicius Costa Gomesda85e5e2011-06-09 18:50:53 -0300668
669 return 0;
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300670}
671
Vinicius Costa Gomesda85e5e2011-06-09 18:50:53 -0300672static u8 smp_cmd_pairing_confirm(struct l2cap_conn *conn, struct sk_buff *skb)
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300673{
Vinicius Costa Gomes1c1def02011-09-05 14:31:30 -0300674 struct smp_chan *smp = conn->smp_chan;
Vinicius Costa Gomes8aab4752011-09-05 14:31:31 -0300675 struct hci_dev *hdev = conn->hcon->hdev;
Anderson Briglia7d24ddc2011-06-09 18:50:46 -0300676
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300677 BT_DBG("conn %p %s", conn, conn->hcon->out ? "master" : "slave");
678
Vinicius Costa Gomes1c1def02011-09-05 14:31:30 -0300679 memcpy(smp->pcnf, skb->data, sizeof(smp->pcnf));
680 skb_pull(skb, sizeof(smp->pcnf));
Anderson Briglia7d24ddc2011-06-09 18:50:46 -0300681
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300682 if (conn->hcon->out) {
Anderson Briglia7d24ddc2011-06-09 18:50:46 -0300683 u8 random[16];
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300684
Vinicius Costa Gomes1c1def02011-09-05 14:31:30 -0300685 swap128(smp->prnd, random);
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300686 smp_send_cmd(conn, SMP_CMD_PAIRING_RANDOM, sizeof(random),
Anderson Briglia7d24ddc2011-06-09 18:50:46 -0300687 random);
Brian Gix2b64d152011-12-21 16:12:12 -0800688 } else if (test_bit(SMP_FLAG_TK_VALID, &smp->smp_flags)) {
Vinicius Costa Gomes8aab4752011-09-05 14:31:31 -0300689 queue_work(hdev->workqueue, &smp->confirm);
Brian Gix2b64d152011-12-21 16:12:12 -0800690 } else {
691 set_bit(SMP_FLAG_CFM_PENDING, &smp->smp_flags);
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300692 }
Vinicius Costa Gomesda85e5e2011-06-09 18:50:53 -0300693
694 return 0;
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300695}
696
Vinicius Costa Gomesda85e5e2011-06-09 18:50:53 -0300697static u8 smp_cmd_pairing_random(struct l2cap_conn *conn, struct sk_buff *skb)
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300698{
Vinicius Costa Gomes1c1def02011-09-05 14:31:30 -0300699 struct smp_chan *smp = conn->smp_chan;
Vinicius Costa Gomes8aab4752011-09-05 14:31:31 -0300700 struct hci_dev *hdev = conn->hcon->hdev;
Anderson Briglia7d24ddc2011-06-09 18:50:46 -0300701
Vinicius Costa Gomes8aab4752011-09-05 14:31:31 -0300702 BT_DBG("conn %p", conn);
Anderson Briglia7d24ddc2011-06-09 18:50:46 -0300703
Vinicius Costa Gomes8aab4752011-09-05 14:31:31 -0300704 swap128(skb->data, smp->rrnd);
705 skb_pull(skb, sizeof(smp->rrnd));
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300706
Vinicius Costa Gomes8aab4752011-09-05 14:31:31 -0300707 queue_work(hdev->workqueue, &smp->random);
Vinicius Costa Gomesda85e5e2011-06-09 18:50:53 -0300708
709 return 0;
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300710}
711
Johan Hedberg4dab7862012-06-07 14:58:37 +0800712static u8 smp_ltk_encrypt(struct l2cap_conn *conn, u8 sec_level)
Vinicius Costa Gomes988c5992011-08-25 20:02:28 -0300713{
Vinicius Costa Gomesc9839a12012-02-02 21:08:01 -0300714 struct smp_ltk *key;
Vinicius Costa Gomes988c5992011-08-25 20:02:28 -0300715 struct hci_conn *hcon = conn->hcon;
716
Vinicius Costa Gomesc9839a12012-02-02 21:08:01 -0300717 key = hci_find_ltk_by_addr(hcon->hdev, conn->dst, hcon->dst_type);
Vinicius Costa Gomes988c5992011-08-25 20:02:28 -0300718 if (!key)
719 return 0;
720
Johan Hedberg4dab7862012-06-07 14:58:37 +0800721 if (sec_level > BT_SECURITY_MEDIUM && !key->authenticated)
722 return 0;
723
Johan Hedberg51a8efd2012-01-16 06:10:31 +0200724 if (test_and_set_bit(HCI_CONN_ENCRYPT_PEND, &hcon->flags))
Vinicius Costa Gomes988c5992011-08-25 20:02:28 -0300725 return 1;
726
Vinicius Costa Gomesc9839a12012-02-02 21:08:01 -0300727 hci_le_start_enc(hcon, key->ediv, key->rand, key->val);
728 hcon->enc_key_size = key->enc_size;
Vinicius Costa Gomes988c5992011-08-25 20:02:28 -0300729
730 return 1;
731
732}
Vinicius Costa Gomesda85e5e2011-06-09 18:50:53 -0300733static u8 smp_cmd_security_req(struct l2cap_conn *conn, struct sk_buff *skb)
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300734{
735 struct smp_cmd_security_req *rp = (void *) skb->data;
736 struct smp_cmd_pairing cp;
Vinicius Costa Gomesf1cb9af2011-01-26 21:42:57 -0300737 struct hci_conn *hcon = conn->hcon;
Vinicius Costa Gomes8aab4752011-09-05 14:31:31 -0300738 struct smp_chan *smp;
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300739
740 BT_DBG("conn %p", conn);
741
Johan Hedberg86ca9ea2013-11-05 11:30:39 +0200742 if (!(conn->hcon->link_mode & HCI_LM_MASTER))
743 return SMP_CMD_NOTSUPP;
744
Brian Gix2b64d152011-12-21 16:12:12 -0800745 hcon->pending_sec_level = authreq_to_seclevel(rp->auth_req);
Vinicius Costa Gomesfeb45eb2011-08-25 20:02:35 -0300746
Johan Hedberg4dab7862012-06-07 14:58:37 +0800747 if (smp_ltk_encrypt(conn, hcon->pending_sec_level))
Vinicius Costa Gomes988c5992011-08-25 20:02:28 -0300748 return 0;
749
Johan Hedberg51a8efd2012-01-16 06:10:31 +0200750 if (test_and_set_bit(HCI_CONN_LE_SMP_PEND, &hcon->flags))
Vinicius Costa Gomesda85e5e2011-06-09 18:50:53 -0300751 return 0;
Vinicius Costa Gomesf1cb9af2011-01-26 21:42:57 -0300752
Vinicius Costa Gomes8aab4752011-09-05 14:31:31 -0300753 smp = smp_chan_create(conn);
Vinicius Costa Gomesd26a2342011-08-19 21:06:51 -0300754
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300755 skb_pull(skb, sizeof(*rp));
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300756
Vinicius Costa Gomesda85e5e2011-06-09 18:50:53 -0300757 memset(&cp, 0, sizeof(cp));
Vinicius Costa Gomes54790f72011-07-07 18:59:38 -0300758 build_pairing_cmd(conn, &cp, NULL, rp->auth_req);
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300759
Vinicius Costa Gomes1c1def02011-09-05 14:31:30 -0300760 smp->preq[0] = SMP_CMD_PAIRING_REQ;
761 memcpy(&smp->preq[1], &cp, sizeof(cp));
Anderson Brigliaf01ead32011-06-09 18:50:45 -0300762
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300763 smp_send_cmd(conn, SMP_CMD_PAIRING_REQ, sizeof(cp), &cp);
Vinicius Costa Gomesf1cb9af2011-01-26 21:42:57 -0300764
Vinicius Costa Gomesda85e5e2011-06-09 18:50:53 -0300765 return 0;
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300766}
767
Vinicius Costa Gomescc110922012-08-23 21:32:43 -0300768int smp_conn_security(struct hci_conn *hcon, __u8 sec_level)
Anderson Brigliaeb492e02011-06-09 18:50:40 -0300769{
Vinicius Costa Gomescc110922012-08-23 21:32:43 -0300770 struct l2cap_conn *conn = hcon->l2cap_data;
Vinicius Costa Gomes1c1def02011-09-05 14:31:30 -0300771 struct smp_chan *smp = conn->smp_chan;
Brian Gix2b64d152011-12-21 16:12:12 -0800772 __u8 authreq;
Anderson Brigliaeb492e02011-06-09 18:50:40 -0300773
Vinicius Costa Gomes3a0259b2011-06-09 18:50:43 -0300774 BT_DBG("conn %p hcon %p level 0x%2.2x", conn, hcon, sec_level);
775
Johan Hedberg757aee02013-04-24 13:05:32 +0300776 if (!test_bit(HCI_LE_ENABLED, &hcon->hdev->dev_flags))
Andre Guedes2e65c9d2011-06-30 19:20:56 -0300777 return 1;
778
Vinicius Costa Gomesf1cb9af2011-01-26 21:42:57 -0300779 if (sec_level == BT_SECURITY_LOW)
Anderson Brigliaeb492e02011-06-09 18:50:40 -0300780 return 1;
Vinicius Costa Gomesf1cb9af2011-01-26 21:42:57 -0300781
782 if (hcon->sec_level >= sec_level)
783 return 1;
784
Vinicius Costa Gomes988c5992011-08-25 20:02:28 -0300785 if (hcon->link_mode & HCI_LM_MASTER)
Johan Hedberg4dab7862012-06-07 14:58:37 +0800786 if (smp_ltk_encrypt(conn, sec_level))
Vinicius Costa Gomes02bc7452011-07-07 18:59:41 -0300787 goto done;
Vinicius Costa Gomesd26a2342011-08-19 21:06:51 -0300788
Johan Hedberg51a8efd2012-01-16 06:10:31 +0200789 if (test_and_set_bit(HCI_CONN_LE_SMP_PEND, &hcon->flags))
Vinicius Costa Gomesd26a2342011-08-19 21:06:51 -0300790 return 0;
791
Vinicius Costa Gomes8aab4752011-09-05 14:31:31 -0300792 smp = smp_chan_create(conn);
Brian Gix2b64d152011-12-21 16:12:12 -0800793 if (!smp)
794 return 1;
795
796 authreq = seclevel_to_authreq(sec_level);
Vinicius Costa Gomesd26a2342011-08-19 21:06:51 -0300797
Vinicius Costa Gomesd26a2342011-08-19 21:06:51 -0300798 if (hcon->link_mode & HCI_LM_MASTER) {
799 struct smp_cmd_pairing cp;
Anderson Brigliaf01ead32011-06-09 18:50:45 -0300800
Brian Gix2b64d152011-12-21 16:12:12 -0800801 build_pairing_cmd(conn, &cp, NULL, authreq);
Vinicius Costa Gomes1c1def02011-09-05 14:31:30 -0300802 smp->preq[0] = SMP_CMD_PAIRING_REQ;
803 memcpy(&smp->preq[1], &cp, sizeof(cp));
Anderson Brigliaf01ead32011-06-09 18:50:45 -0300804
Anderson Brigliaeb492e02011-06-09 18:50:40 -0300805 smp_send_cmd(conn, SMP_CMD_PAIRING_REQ, sizeof(cp), &cp);
806 } else {
807 struct smp_cmd_security_req cp;
Brian Gix2b64d152011-12-21 16:12:12 -0800808 cp.auth_req = authreq;
Anderson Brigliaeb492e02011-06-09 18:50:40 -0300809 smp_send_cmd(conn, SMP_CMD_SECURITY_REQ, sizeof(cp), &cp);
810 }
811
Vinicius Costa Gomes02bc7452011-07-07 18:59:41 -0300812done:
Vinicius Costa Gomesf1cb9af2011-01-26 21:42:57 -0300813 hcon->pending_sec_level = sec_level;
Vinicius Costa Gomesf1cb9af2011-01-26 21:42:57 -0300814
Anderson Brigliaeb492e02011-06-09 18:50:40 -0300815 return 0;
816}
817
Vinicius Costa Gomes7034b912011-07-07 18:59:34 -0300818static int smp_cmd_encrypt_info(struct l2cap_conn *conn, struct sk_buff *skb)
819{
Vinicius Costa Gomes16b90832011-07-07 18:59:39 -0300820 struct smp_cmd_encrypt_info *rp = (void *) skb->data;
Vinicius Costa Gomes1c1def02011-09-05 14:31:30 -0300821 struct smp_chan *smp = conn->smp_chan;
Vinicius Costa Gomes16b90832011-07-07 18:59:39 -0300822
823 skb_pull(skb, sizeof(*rp));
824
Vinicius Costa Gomes1c1def02011-09-05 14:31:30 -0300825 memcpy(smp->tk, rp->ltk, sizeof(smp->tk));
Vinicius Costa Gomes16b90832011-07-07 18:59:39 -0300826
Vinicius Costa Gomes7034b912011-07-07 18:59:34 -0300827 return 0;
828}
829
830static int smp_cmd_master_ident(struct l2cap_conn *conn, struct sk_buff *skb)
831{
Vinicius Costa Gomes16b90832011-07-07 18:59:39 -0300832 struct smp_cmd_master_ident *rp = (void *) skb->data;
Vinicius Costa Gomes1c1def02011-09-05 14:31:30 -0300833 struct smp_chan *smp = conn->smp_chan;
Vinicius Costa Gomesc9839a12012-02-02 21:08:01 -0300834 struct hci_dev *hdev = conn->hcon->hdev;
835 struct hci_conn *hcon = conn->hcon;
836 u8 authenticated;
Vinicius Costa Gomes7034b912011-07-07 18:59:34 -0300837
Vinicius Costa Gomes16b90832011-07-07 18:59:39 -0300838 skb_pull(skb, sizeof(*rp));
839
Vinicius Costa Gomesc9839a12012-02-02 21:08:01 -0300840 hci_dev_lock(hdev);
841 authenticated = (conn->hcon->sec_level == BT_SECURITY_HIGH);
842 hci_add_ltk(conn->hcon->hdev, conn->dst, hcon->dst_type,
Gustavo F. Padovan04124682012-03-08 01:25:00 -0300843 HCI_SMP_LTK, 1, authenticated, smp->tk, smp->enc_key_size,
844 rp->ediv, rp->rand);
Vinicius Costa Gomes7034b912011-07-07 18:59:34 -0300845 smp_distribute_keys(conn, 1);
Vinicius Costa Gomesc9839a12012-02-02 21:08:01 -0300846 hci_dev_unlock(hdev);
Vinicius Costa Gomes7034b912011-07-07 18:59:34 -0300847
848 return 0;
849}
850
Anderson Brigliaeb492e02011-06-09 18:50:40 -0300851int smp_sig_channel(struct l2cap_conn *conn, struct sk_buff *skb)
852{
853 __u8 code = skb->data[0];
854 __u8 reason;
855 int err = 0;
856
Johan Hedberg757aee02013-04-24 13:05:32 +0300857 if (!test_bit(HCI_LE_ENABLED, &conn->hcon->hdev->dev_flags)) {
Andre Guedes2e65c9d2011-06-30 19:20:56 -0300858 err = -ENOTSUPP;
859 reason = SMP_PAIRING_NOTSUPP;
860 goto done;
861 }
862
Anderson Brigliaeb492e02011-06-09 18:50:40 -0300863 skb_pull(skb, sizeof(code));
864
Johan Hedberg8cf9fa12013-01-29 10:44:23 -0600865 /*
866 * The SMP context must be initialized for all other PDUs except
867 * pairing and security requests. If we get any other PDU when
868 * not initialized simply disconnect (done if this function
869 * returns an error).
870 */
871 if (code != SMP_CMD_PAIRING_REQ && code != SMP_CMD_SECURITY_REQ &&
872 !conn->smp_chan) {
873 BT_ERR("Unexpected SMP command 0x%02x. Disconnecting.", code);
874 kfree_skb(skb);
875 return -ENOTSUPP;
876 }
877
Anderson Brigliaeb492e02011-06-09 18:50:40 -0300878 switch (code) {
879 case SMP_CMD_PAIRING_REQ:
Vinicius Costa Gomesda85e5e2011-06-09 18:50:53 -0300880 reason = smp_cmd_pairing_req(conn, skb);
Anderson Brigliaeb492e02011-06-09 18:50:40 -0300881 break;
882
883 case SMP_CMD_PAIRING_FAIL:
Brian Gix4f957a72011-11-23 08:28:36 -0800884 smp_failure(conn, skb->data[0], 0);
Vinicius Costa Gomesda85e5e2011-06-09 18:50:53 -0300885 reason = 0;
886 err = -EPERM;
Anderson Brigliaeb492e02011-06-09 18:50:40 -0300887 break;
888
889 case SMP_CMD_PAIRING_RSP:
Vinicius Costa Gomesda85e5e2011-06-09 18:50:53 -0300890 reason = smp_cmd_pairing_rsp(conn, skb);
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300891 break;
892
893 case SMP_CMD_SECURITY_REQ:
Vinicius Costa Gomesda85e5e2011-06-09 18:50:53 -0300894 reason = smp_cmd_security_req(conn, skb);
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300895 break;
896
Anderson Brigliaeb492e02011-06-09 18:50:40 -0300897 case SMP_CMD_PAIRING_CONFIRM:
Vinicius Costa Gomesda85e5e2011-06-09 18:50:53 -0300898 reason = smp_cmd_pairing_confirm(conn, skb);
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300899 break;
900
Anderson Brigliaeb492e02011-06-09 18:50:40 -0300901 case SMP_CMD_PAIRING_RANDOM:
Vinicius Costa Gomesda85e5e2011-06-09 18:50:53 -0300902 reason = smp_cmd_pairing_random(conn, skb);
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300903 break;
904
Anderson Brigliaeb492e02011-06-09 18:50:40 -0300905 case SMP_CMD_ENCRYPT_INFO:
Vinicius Costa Gomes7034b912011-07-07 18:59:34 -0300906 reason = smp_cmd_encrypt_info(conn, skb);
907 break;
908
Anderson Brigliaeb492e02011-06-09 18:50:40 -0300909 case SMP_CMD_MASTER_IDENT:
Vinicius Costa Gomes7034b912011-07-07 18:59:34 -0300910 reason = smp_cmd_master_ident(conn, skb);
911 break;
912
Anderson Brigliaeb492e02011-06-09 18:50:40 -0300913 case SMP_CMD_IDENT_INFO:
914 case SMP_CMD_IDENT_ADDR_INFO:
915 case SMP_CMD_SIGN_INFO:
Vinicius Costa Gomes7034b912011-07-07 18:59:34 -0300916 /* Just ignored */
917 reason = 0;
918 break;
919
Anderson Brigliaeb492e02011-06-09 18:50:40 -0300920 default:
921 BT_DBG("Unknown command code 0x%2.2x", code);
922
923 reason = SMP_CMD_NOTSUPP;
Vinicius Costa Gomes3a0259b2011-06-09 18:50:43 -0300924 err = -EOPNOTSUPP;
925 goto done;
926 }
927
928done:
929 if (reason)
Brian Gix4f957a72011-11-23 08:28:36 -0800930 smp_failure(conn, reason, 1);
Anderson Brigliaeb492e02011-06-09 18:50:40 -0300931
932 kfree_skb(skb);
933 return err;
934}
Vinicius Costa Gomes7034b912011-07-07 18:59:34 -0300935
936int smp_distribute_keys(struct l2cap_conn *conn, __u8 force)
937{
938 struct smp_cmd_pairing *req, *rsp;
Vinicius Costa Gomes1c1def02011-09-05 14:31:30 -0300939 struct smp_chan *smp = conn->smp_chan;
Vinicius Costa Gomes7034b912011-07-07 18:59:34 -0300940 __u8 *keydist;
941
942 BT_DBG("conn %p force %d", conn, force);
943
Johan Hedberg51a8efd2012-01-16 06:10:31 +0200944 if (!test_bit(HCI_CONN_LE_SMP_PEND, &conn->hcon->flags))
Vinicius Costa Gomesd26a2342011-08-19 21:06:51 -0300945 return 0;
946
Vinicius Costa Gomes1c1def02011-09-05 14:31:30 -0300947 rsp = (void *) &smp->prsp[1];
Vinicius Costa Gomes7034b912011-07-07 18:59:34 -0300948
949 /* The responder sends its keys first */
950 if (!force && conn->hcon->out && (rsp->resp_key_dist & 0x07))
951 return 0;
952
Vinicius Costa Gomes1c1def02011-09-05 14:31:30 -0300953 req = (void *) &smp->preq[1];
Vinicius Costa Gomes7034b912011-07-07 18:59:34 -0300954
955 if (conn->hcon->out) {
956 keydist = &rsp->init_key_dist;
957 *keydist &= req->init_key_dist;
958 } else {
959 keydist = &rsp->resp_key_dist;
960 *keydist &= req->resp_key_dist;
961 }
962
963
964 BT_DBG("keydist 0x%x", *keydist);
965
966 if (*keydist & SMP_DIST_ENC_KEY) {
967 struct smp_cmd_encrypt_info enc;
968 struct smp_cmd_master_ident ident;
Vinicius Costa Gomesc9839a12012-02-02 21:08:01 -0300969 struct hci_conn *hcon = conn->hcon;
970 u8 authenticated;
Vinicius Costa Gomes7034b912011-07-07 18:59:34 -0300971 __le16 ediv;
972
973 get_random_bytes(enc.ltk, sizeof(enc.ltk));
974 get_random_bytes(&ediv, sizeof(ediv));
975 get_random_bytes(ident.rand, sizeof(ident.rand));
976
977 smp_send_cmd(conn, SMP_CMD_ENCRYPT_INFO, sizeof(enc), &enc);
978
Vinicius Costa Gomesc9839a12012-02-02 21:08:01 -0300979 authenticated = hcon->sec_level == BT_SECURITY_HIGH;
980 hci_add_ltk(conn->hcon->hdev, conn->dst, hcon->dst_type,
Gustavo F. Padovan04124682012-03-08 01:25:00 -0300981 HCI_SMP_LTK_SLAVE, 1, authenticated,
982 enc.ltk, smp->enc_key_size, ediv, ident.rand);
Vinicius Costa Gomes16b90832011-07-07 18:59:39 -0300983
Andrei Emeltchenko58115372012-03-12 12:13:06 +0200984 ident.ediv = ediv;
Vinicius Costa Gomes7034b912011-07-07 18:59:34 -0300985
986 smp_send_cmd(conn, SMP_CMD_MASTER_IDENT, sizeof(ident), &ident);
987
988 *keydist &= ~SMP_DIST_ENC_KEY;
989 }
990
991 if (*keydist & SMP_DIST_ID_KEY) {
992 struct smp_cmd_ident_addr_info addrinfo;
993 struct smp_cmd_ident_info idinfo;
994
995 /* Send a dummy key */
996 get_random_bytes(idinfo.irk, sizeof(idinfo.irk));
997
998 smp_send_cmd(conn, SMP_CMD_IDENT_INFO, sizeof(idinfo), &idinfo);
999
1000 /* Just public address */
1001 memset(&addrinfo, 0, sizeof(addrinfo));
1002 bacpy(&addrinfo.bdaddr, conn->src);
1003
1004 smp_send_cmd(conn, SMP_CMD_IDENT_ADDR_INFO, sizeof(addrinfo),
1005 &addrinfo);
1006
1007 *keydist &= ~SMP_DIST_ID_KEY;
1008 }
1009
1010 if (*keydist & SMP_DIST_SIGN) {
1011 struct smp_cmd_sign_info sign;
1012
1013 /* Send a dummy key */
1014 get_random_bytes(sign.csrk, sizeof(sign.csrk));
1015
1016 smp_send_cmd(conn, SMP_CMD_SIGN_INFO, sizeof(sign), &sign);
1017
1018 *keydist &= ~SMP_DIST_SIGN;
1019 }
1020
Vinicius Costa Gomesd26a2342011-08-19 21:06:51 -03001021 if (conn->hcon->out || force) {
Johan Hedberg51a8efd2012-01-16 06:10:31 +02001022 clear_bit(HCI_CONN_LE_SMP_PEND, &conn->hcon->flags);
Gustavo F. Padovan6c9d42a2011-12-20 10:57:27 -02001023 cancel_delayed_work_sync(&conn->security_timer);
Vinicius Costa Gomes8aab4752011-09-05 14:31:31 -03001024 smp_chan_destroy(conn);
Vinicius Costa Gomesd26a2342011-08-19 21:06:51 -03001025 }
1026
Vinicius Costa Gomes7034b912011-07-07 18:59:34 -03001027 return 0;
1028}