blob: 03489e5815ef55bf72d7214f4d461c9a85024996 [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
23#include <net/bluetooth/bluetooth.h>
24#include <net/bluetooth/hci_core.h>
25#include <net/bluetooth/l2cap.h>
26#include <net/bluetooth/smp.h>
Anderson Brigliad22ef0b2011-06-09 18:50:44 -030027#include <linux/crypto.h>
Stephen Rothwellf70490e2011-06-23 12:58:55 +100028#include <linux/scatterlist.h>
Anderson Brigliad22ef0b2011-06-09 18:50:44 -030029#include <crypto/b128ops.h>
30
Vinicius Costa Gomes5d3de7d2011-06-14 13:37:41 -030031#define SMP_TIMEOUT 30000 /* 30 seconds */
32
Anderson Brigliad22ef0b2011-06-09 18:50:44 -030033static inline void swap128(u8 src[16], u8 dst[16])
34{
35 int i;
36 for (i = 0; i < 16; i++)
37 dst[15 - i] = src[i];
38}
39
40static inline void swap56(u8 src[7], u8 dst[7])
41{
42 int i;
43 for (i = 0; i < 7; i++)
44 dst[6 - i] = src[i];
45}
46
47static int smp_e(struct crypto_blkcipher *tfm, const u8 *k, u8 *r)
48{
49 struct blkcipher_desc desc;
50 struct scatterlist sg;
51 int err, iv_len;
52 unsigned char iv[128];
53
54 if (tfm == NULL) {
55 BT_ERR("tfm %p", tfm);
56 return -EINVAL;
57 }
58
59 desc.tfm = tfm;
60 desc.flags = 0;
61
62 err = crypto_blkcipher_setkey(tfm, k, 16);
63 if (err) {
64 BT_ERR("cipher setkey failed: %d", err);
65 return err;
66 }
67
68 sg_init_one(&sg, r, 16);
69
70 iv_len = crypto_blkcipher_ivsize(tfm);
71 if (iv_len) {
72 memset(&iv, 0xff, iv_len);
73 crypto_blkcipher_set_iv(tfm, iv, iv_len);
74 }
75
76 err = crypto_blkcipher_encrypt(&desc, &sg, &sg, 16);
77 if (err)
78 BT_ERR("Encrypt data error %d", err);
79
80 return err;
81}
82
83static int smp_c1(struct crypto_blkcipher *tfm, u8 k[16], u8 r[16],
84 u8 preq[7], u8 pres[7], u8 _iat, bdaddr_t *ia,
85 u8 _rat, bdaddr_t *ra, u8 res[16])
86{
87 u8 p1[16], p2[16];
88 int err;
89
90 memset(p1, 0, 16);
91
92 /* p1 = pres || preq || _rat || _iat */
93 swap56(pres, p1);
94 swap56(preq, p1 + 7);
95 p1[14] = _rat;
96 p1[15] = _iat;
97
98 memset(p2, 0, 16);
99
100 /* p2 = padding || ia || ra */
101 baswap((bdaddr_t *) (p2 + 4), ia);
102 baswap((bdaddr_t *) (p2 + 10), ra);
103
104 /* res = r XOR p1 */
105 u128_xor((u128 *) res, (u128 *) r, (u128 *) p1);
106
107 /* res = e(k, res) */
108 err = smp_e(tfm, k, res);
109 if (err) {
110 BT_ERR("Encrypt data error");
111 return err;
112 }
113
114 /* res = res XOR p2 */
115 u128_xor((u128 *) res, (u128 *) res, (u128 *) p2);
116
117 /* res = e(k, res) */
118 err = smp_e(tfm, k, res);
119 if (err)
120 BT_ERR("Encrypt data error");
121
122 return err;
123}
124
125static int smp_s1(struct crypto_blkcipher *tfm, u8 k[16],
126 u8 r1[16], u8 r2[16], u8 _r[16])
127{
128 int err;
129
130 /* Just least significant octets from r1 and r2 are considered */
131 memcpy(_r, r1 + 8, 8);
132 memcpy(_r + 8, r2 + 8, 8);
133
134 err = smp_e(tfm, k, _r);
135 if (err)
136 BT_ERR("Encrypt data error");
137
138 return err;
139}
140
141static int smp_rand(u8 *buf)
142{
143 get_random_bytes(buf, 16);
144
145 return 0;
146}
Anderson Brigliaeb492e02011-06-09 18:50:40 -0300147
148static struct sk_buff *smp_build_cmd(struct l2cap_conn *conn, u8 code,
149 u16 dlen, void *data)
150{
151 struct sk_buff *skb;
152 struct l2cap_hdr *lh;
153 int len;
154
155 len = L2CAP_HDR_SIZE + sizeof(code) + dlen;
156
157 if (len > conn->mtu)
158 return NULL;
159
160 skb = bt_skb_alloc(len, GFP_ATOMIC);
161 if (!skb)
162 return NULL;
163
164 lh = (struct l2cap_hdr *) skb_put(skb, L2CAP_HDR_SIZE);
165 lh->len = cpu_to_le16(sizeof(code) + dlen);
166 lh->cid = cpu_to_le16(L2CAP_CID_SMP);
167
168 memcpy(skb_put(skb, sizeof(code)), &code, sizeof(code));
169
170 memcpy(skb_put(skb, dlen), data, dlen);
171
172 return skb;
173}
174
175static void smp_send_cmd(struct l2cap_conn *conn, u8 code, u16 len, void *data)
176{
177 struct sk_buff *skb = smp_build_cmd(conn, code, len, data);
178
179 BT_DBG("code 0x%2.2x", code);
180
181 if (!skb)
182 return;
183
184 hci_send_acl(conn->hcon, skb, 0);
Vinicius Costa Gomese2dcd112011-08-19 21:06:50 -0300185
186 mod_timer(&conn->security_timer, jiffies +
187 msecs_to_jiffies(SMP_TIMEOUT));
Anderson Brigliaeb492e02011-06-09 18:50:40 -0300188}
189
Vinicius Costa Gomesda85e5e2011-06-09 18:50:53 -0300190static __u8 seclevel_to_authreq(__u8 level)
191{
192 switch (level) {
193 case BT_SECURITY_HIGH:
194 /* Right now we don't support bonding */
195 return SMP_AUTH_MITM;
196
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,
Vinicius Costa Gomes54790f72011-07-07 18:59:38 -0300203 struct smp_cmd_pairing *req,
204 struct smp_cmd_pairing *rsp,
205 __u8 authreq)
Vinicius Costa Gomesb8e66ea2011-06-09 18:50:52 -0300206{
Vinicius Costa Gomes54790f72011-07-07 18:59:38 -0300207 u8 dist_keys;
208
209 dist_keys = 0;
210 if (test_bit(HCI_PAIRABLE, &conn->hcon->hdev->flags)) {
211 dist_keys = SMP_DIST_ENC_KEY | SMP_DIST_ID_KEY | SMP_DIST_SIGN;
212 authreq |= SMP_AUTH_BONDING;
213 }
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;
219 req->init_key_dist = dist_keys;
220 req->resp_key_dist = dist_keys;
221 req->auth_req = authreq;
222 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;
228 rsp->init_key_dist = req->init_key_dist & dist_keys;
229 rsp->resp_key_dist = req->resp_key_dist & dist_keys;
230 rsp->auth_req = authreq;
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) ||
238 (max_key_size < SMP_MIN_ENC_KEY_SIZE))
239 return SMP_ENC_KEY_SIZE;
240
Vinicius Costa Gomes1c1def02011-09-05 14:31:30 -0300241 smp->smp_key_size = max_key_size;
Vinicius Costa Gomes3158c502011-06-14 13:37:42 -0300242
243 return 0;
244}
245
Vinicius Costa Gomes8aab4752011-09-05 14:31:31 -0300246static void confirm_work(struct work_struct *work)
247{
248 struct smp_chan *smp = container_of(work, struct smp_chan, confirm);
249 struct l2cap_conn *conn = smp->conn;
250 struct crypto_blkcipher *tfm;
251 struct smp_cmd_pairing_confirm cp;
252 int ret;
253 u8 res[16], reason;
254
255 BT_DBG("conn %p", conn);
256
257 tfm = crypto_alloc_blkcipher("ecb(aes)", 0, CRYPTO_ALG_ASYNC);
258 if (IS_ERR(tfm)) {
259 reason = SMP_UNSPECIFIED;
260 goto error;
261 }
262
263 smp->tfm = tfm;
264
265 if (conn->hcon->out)
266 ret = smp_c1(tfm, smp->tk, smp->prnd, smp->preq, smp->prsp, 0,
267 conn->src, conn->hcon->dst_type, conn->dst,
268 res);
269 else
270 ret = smp_c1(tfm, smp->tk, smp->prnd, smp->preq, smp->prsp,
271 conn->hcon->dst_type, conn->dst, 0, conn->src,
272 res);
273 if (ret) {
274 reason = SMP_UNSPECIFIED;
275 goto error;
276 }
277
278 swap128(res, cp.confirm_val);
279 smp_send_cmd(smp->conn, SMP_CMD_PAIRING_CONFIRM, sizeof(cp), &cp);
280
281 return;
282
283error:
284 smp_send_cmd(conn, SMP_CMD_PAIRING_FAIL, sizeof(reason), &reason);
285 smp_chan_destroy(conn);
286}
287
288static void random_work(struct work_struct *work)
289{
290 struct smp_chan *smp = container_of(work, struct smp_chan, random);
291 struct l2cap_conn *conn = smp->conn;
292 struct hci_conn *hcon = conn->hcon;
293 struct crypto_blkcipher *tfm = smp->tfm;
294 u8 reason, confirm[16], res[16], key[16];
295 int ret;
296
297 if (IS_ERR_OR_NULL(tfm)) {
298 reason = SMP_UNSPECIFIED;
299 goto error;
300 }
301
302 BT_DBG("conn %p %s", conn, conn->hcon->out ? "master" : "slave");
303
304 if (hcon->out)
305 ret = smp_c1(tfm, smp->tk, smp->rrnd, smp->preq, smp->prsp, 0,
306 conn->src, hcon->dst_type, conn->dst,
307 res);
308 else
309 ret = smp_c1(tfm, smp->tk, smp->rrnd, smp->preq, smp->prsp,
310 hcon->dst_type, conn->dst, 0, conn->src,
311 res);
312 if (ret) {
313 reason = SMP_UNSPECIFIED;
314 goto error;
315 }
316
317 swap128(res, confirm);
318
319 if (memcmp(smp->pcnf, confirm, sizeof(smp->pcnf)) != 0) {
320 BT_ERR("Pairing failed (confirmation values mismatch)");
321 reason = SMP_CONFIRM_FAILED;
322 goto error;
323 }
324
325 if (hcon->out) {
326 u8 stk[16], rand[8];
327 __le16 ediv;
328
329 memset(rand, 0, sizeof(rand));
330 ediv = 0;
331
332 smp_s1(tfm, smp->tk, smp->rrnd, smp->prnd, key);
333 swap128(key, stk);
334
335 memset(stk + smp->smp_key_size, 0,
336 SMP_MAX_ENC_KEY_SIZE - smp->smp_key_size);
337
338 if (test_and_set_bit(HCI_CONN_ENCRYPT_PEND, &hcon->pend)) {
339 reason = SMP_UNSPECIFIED;
340 goto error;
341 }
342
343 hci_le_start_enc(hcon, ediv, rand, stk);
344 hcon->enc_key_size = smp->smp_key_size;
345 } else {
346 u8 stk[16], r[16], rand[8];
347 __le16 ediv;
348
349 memset(rand, 0, sizeof(rand));
350 ediv = 0;
351
352 swap128(smp->prnd, r);
353 smp_send_cmd(conn, SMP_CMD_PAIRING_RANDOM, sizeof(r), r);
354
355 smp_s1(tfm, smp->tk, smp->prnd, smp->rrnd, key);
356 swap128(key, stk);
357
358 memset(stk + smp->smp_key_size, 0,
359 SMP_MAX_ENC_KEY_SIZE - smp->smp_key_size);
360
361 hci_add_ltk(hcon->hdev, 0, conn->dst, smp->smp_key_size,
362 ediv, rand, stk);
363 }
364
365 return;
366
367error:
368 smp_send_cmd(conn, SMP_CMD_PAIRING_FAIL, sizeof(reason), &reason);
369 smp_chan_destroy(conn);
370}
371
372static struct smp_chan *smp_chan_create(struct l2cap_conn *conn)
373{
374 struct smp_chan *smp;
375
376 smp = kzalloc(sizeof(struct smp_chan), GFP_ATOMIC);
377 if (!smp)
378 return NULL;
379
380 INIT_WORK(&smp->confirm, confirm_work);
381 INIT_WORK(&smp->random, random_work);
382
383 smp->conn = conn;
384 conn->smp_chan = smp;
385
386 hci_conn_hold(conn->hcon);
387
388 return smp;
389}
390
391void smp_chan_destroy(struct l2cap_conn *conn)
392{
393 kfree(conn->smp_chan);
394 hci_conn_put(conn->hcon);
395}
396
Vinicius Costa Gomesda85e5e2011-06-09 18:50:53 -0300397static u8 smp_cmd_pairing_req(struct l2cap_conn *conn, struct sk_buff *skb)
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300398{
Vinicius Costa Gomes3158c502011-06-14 13:37:42 -0300399 struct smp_cmd_pairing rsp, *req = (void *) skb->data;
Vinicius Costa Gomes8aab4752011-09-05 14:31:31 -0300400 struct smp_chan *smp;
Vinicius Costa Gomes3158c502011-06-14 13:37:42 -0300401 u8 key_size;
Vinicius Costa Gomes8aab4752011-09-05 14:31:31 -0300402 int ret;
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300403
404 BT_DBG("conn %p", conn);
405
Vinicius Costa Gomesd26a2342011-08-19 21:06:51 -0300406 if (!test_and_set_bit(HCI_CONN_LE_SMP_PEND, &conn->hcon->pend))
Vinicius Costa Gomes8aab4752011-09-05 14:31:31 -0300407 smp = smp_chan_create(conn);
408
409 smp = conn->smp_chan;
Vinicius Costa Gomesd26a2342011-08-19 21:06:51 -0300410
Vinicius Costa Gomes1c1def02011-09-05 14:31:30 -0300411 smp->preq[0] = SMP_CMD_PAIRING_REQ;
412 memcpy(&smp->preq[1], req, sizeof(*req));
Vinicius Costa Gomes3158c502011-06-14 13:37:42 -0300413 skb_pull(skb, sizeof(*req));
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300414
Vinicius Costa Gomes3158c502011-06-14 13:37:42 -0300415 if (req->oob_flag)
Vinicius Costa Gomesda85e5e2011-06-09 18:50:53 -0300416 return SMP_OOB_NOT_AVAIL;
417
418 /* We didn't start the pairing, so no requirements */
Vinicius Costa Gomes54790f72011-07-07 18:59:38 -0300419 build_pairing_cmd(conn, req, &rsp, SMP_AUTH_NONE);
Vinicius Costa Gomes3158c502011-06-14 13:37:42 -0300420
421 key_size = min(req->max_key_size, rsp.max_key_size);
422 if (check_enc_key_size(conn, key_size))
423 return SMP_ENC_KEY_SIZE;
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300424
Anderson Briglia7d24ddc2011-06-09 18:50:46 -0300425 /* Just works */
Vinicius Costa Gomes1c1def02011-09-05 14:31:30 -0300426 memset(smp->tk, 0, sizeof(smp->tk));
Anderson Briglia7d24ddc2011-06-09 18:50:46 -0300427
Vinicius Costa Gomes8aab4752011-09-05 14:31:31 -0300428 ret = smp_rand(smp->prnd);
429 if (ret)
430 return SMP_UNSPECIFIED;
431
Vinicius Costa Gomes1c1def02011-09-05 14:31:30 -0300432 smp->prsp[0] = SMP_CMD_PAIRING_RSP;
433 memcpy(&smp->prsp[1], &rsp, sizeof(rsp));
Anderson Brigliaf01ead32011-06-09 18:50:45 -0300434
Vinicius Costa Gomes3158c502011-06-14 13:37:42 -0300435 smp_send_cmd(conn, SMP_CMD_PAIRING_RSP, sizeof(rsp), &rsp);
Vinicius Costa Gomesda85e5e2011-06-09 18:50:53 -0300436
437 return 0;
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300438}
439
Vinicius Costa Gomesda85e5e2011-06-09 18:50:53 -0300440static u8 smp_cmd_pairing_rsp(struct l2cap_conn *conn, struct sk_buff *skb)
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300441{
Vinicius Costa Gomes3158c502011-06-14 13:37:42 -0300442 struct smp_cmd_pairing *req, *rsp = (void *) skb->data;
Vinicius Costa Gomes1c1def02011-09-05 14:31:30 -0300443 struct smp_chan *smp = conn->smp_chan;
Vinicius Costa Gomes8aab4752011-09-05 14:31:31 -0300444 struct hci_dev *hdev = conn->hcon->hdev;
445 u8 key_size;
Anderson Briglia7d24ddc2011-06-09 18:50:46 -0300446 int ret;
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300447
448 BT_DBG("conn %p", conn);
449
Vinicius Costa Gomes3158c502011-06-14 13:37:42 -0300450 skb_pull(skb, sizeof(*rsp));
Vinicius Costa Gomesda85e5e2011-06-09 18:50:53 -0300451
Vinicius Costa Gomes1c1def02011-09-05 14:31:30 -0300452 req = (void *) &smp->preq[1];
Vinicius Costa Gomes3158c502011-06-14 13:37:42 -0300453
454 key_size = min(req->max_key_size, rsp->max_key_size);
455 if (check_enc_key_size(conn, key_size))
456 return SMP_ENC_KEY_SIZE;
457
458 if (rsp->oob_flag)
Vinicius Costa Gomesda85e5e2011-06-09 18:50:53 -0300459 return SMP_OOB_NOT_AVAIL;
460
Anderson Briglia7d24ddc2011-06-09 18:50:46 -0300461 /* Just works */
Vinicius Costa Gomes1c1def02011-09-05 14:31:30 -0300462 memset(smp->tk, 0, sizeof(smp->tk));
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300463
Vinicius Costa Gomes1c1def02011-09-05 14:31:30 -0300464 ret = smp_rand(smp->prnd);
Anderson Briglia7d24ddc2011-06-09 18:50:46 -0300465 if (ret)
Vinicius Costa Gomesda85e5e2011-06-09 18:50:53 -0300466 return SMP_UNSPECIFIED;
Anderson Briglia7d24ddc2011-06-09 18:50:46 -0300467
Vinicius Costa Gomes8aab4752011-09-05 14:31:31 -0300468 smp->prsp[0] = SMP_CMD_PAIRING_RSP;
469 memcpy(&smp->prsp[1], rsp, sizeof(*rsp));
Anderson Briglia7d24ddc2011-06-09 18:50:46 -0300470
Vinicius Costa Gomes8aab4752011-09-05 14:31:31 -0300471 queue_work(hdev->workqueue, &smp->confirm);
Vinicius Costa Gomesda85e5e2011-06-09 18:50:53 -0300472
473 return 0;
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300474}
475
Vinicius Costa Gomesda85e5e2011-06-09 18:50:53 -0300476static u8 smp_cmd_pairing_confirm(struct l2cap_conn *conn, struct sk_buff *skb)
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300477{
Vinicius Costa Gomes1c1def02011-09-05 14:31:30 -0300478 struct smp_chan *smp = conn->smp_chan;
Vinicius Costa Gomes8aab4752011-09-05 14:31:31 -0300479 struct hci_dev *hdev = conn->hcon->hdev;
Anderson Briglia7d24ddc2011-06-09 18:50:46 -0300480
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300481 BT_DBG("conn %p %s", conn, conn->hcon->out ? "master" : "slave");
482
Vinicius Costa Gomes1c1def02011-09-05 14:31:30 -0300483 memcpy(smp->pcnf, skb->data, sizeof(smp->pcnf));
484 skb_pull(skb, sizeof(smp->pcnf));
Anderson Briglia7d24ddc2011-06-09 18:50:46 -0300485
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300486 if (conn->hcon->out) {
Anderson Briglia7d24ddc2011-06-09 18:50:46 -0300487 u8 random[16];
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300488
Vinicius Costa Gomes1c1def02011-09-05 14:31:30 -0300489 swap128(smp->prnd, random);
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300490 smp_send_cmd(conn, SMP_CMD_PAIRING_RANDOM, sizeof(random),
Anderson Briglia7d24ddc2011-06-09 18:50:46 -0300491 random);
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300492 } else {
Vinicius Costa Gomes8aab4752011-09-05 14:31:31 -0300493 queue_work(hdev->workqueue, &smp->confirm);
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300494 }
Vinicius Costa Gomesda85e5e2011-06-09 18:50:53 -0300495
496 return 0;
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300497}
498
Vinicius Costa Gomesda85e5e2011-06-09 18:50:53 -0300499static u8 smp_cmd_pairing_random(struct l2cap_conn *conn, struct sk_buff *skb)
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300500{
Vinicius Costa Gomes1c1def02011-09-05 14:31:30 -0300501 struct smp_chan *smp = conn->smp_chan;
Vinicius Costa Gomes8aab4752011-09-05 14:31:31 -0300502 struct hci_dev *hdev = conn->hcon->hdev;
Anderson Briglia7d24ddc2011-06-09 18:50:46 -0300503
Vinicius Costa Gomes8aab4752011-09-05 14:31:31 -0300504 BT_DBG("conn %p", conn);
Anderson Briglia7d24ddc2011-06-09 18:50:46 -0300505
Vinicius Costa Gomes8aab4752011-09-05 14:31:31 -0300506 swap128(skb->data, smp->rrnd);
507 skb_pull(skb, sizeof(smp->rrnd));
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300508
Vinicius Costa Gomes8aab4752011-09-05 14:31:31 -0300509 queue_work(hdev->workqueue, &smp->random);
Vinicius Costa Gomesda85e5e2011-06-09 18:50:53 -0300510
511 return 0;
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300512}
513
Vinicius Costa Gomesda85e5e2011-06-09 18:50:53 -0300514static u8 smp_cmd_security_req(struct l2cap_conn *conn, struct sk_buff *skb)
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300515{
516 struct smp_cmd_security_req *rp = (void *) skb->data;
517 struct smp_cmd_pairing cp;
Vinicius Costa Gomesf1cb9af2011-01-26 21:42:57 -0300518 struct hci_conn *hcon = conn->hcon;
Vinicius Costa Gomes8aab4752011-09-05 14:31:31 -0300519 struct smp_chan *smp;
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300520
521 BT_DBG("conn %p", conn);
522
Vinicius Costa Gomesd26a2342011-08-19 21:06:51 -0300523 if (test_and_set_bit(HCI_CONN_LE_SMP_PEND, &hcon->pend))
Vinicius Costa Gomesda85e5e2011-06-09 18:50:53 -0300524 return 0;
Vinicius Costa Gomesf1cb9af2011-01-26 21:42:57 -0300525
Vinicius Costa Gomes8aab4752011-09-05 14:31:31 -0300526 smp = smp_chan_create(conn);
Vinicius Costa Gomesd26a2342011-08-19 21:06:51 -0300527
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300528 skb_pull(skb, sizeof(*rp));
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300529
Vinicius Costa Gomesda85e5e2011-06-09 18:50:53 -0300530 memset(&cp, 0, sizeof(cp));
Vinicius Costa Gomes54790f72011-07-07 18:59:38 -0300531 build_pairing_cmd(conn, &cp, NULL, rp->auth_req);
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300532
Vinicius Costa Gomes1c1def02011-09-05 14:31:30 -0300533 smp->preq[0] = SMP_CMD_PAIRING_REQ;
534 memcpy(&smp->preq[1], &cp, sizeof(cp));
Anderson Brigliaf01ead32011-06-09 18:50:45 -0300535
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300536 smp_send_cmd(conn, SMP_CMD_PAIRING_REQ, sizeof(cp), &cp);
Vinicius Costa Gomesf1cb9af2011-01-26 21:42:57 -0300537
Vinicius Costa Gomesda85e5e2011-06-09 18:50:53 -0300538 return 0;
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300539}
540
Anderson Brigliaeb492e02011-06-09 18:50:40 -0300541int smp_conn_security(struct l2cap_conn *conn, __u8 sec_level)
542{
Vinicius Costa Gomes3a0259b2011-06-09 18:50:43 -0300543 struct hci_conn *hcon = conn->hcon;
Vinicius Costa Gomes1c1def02011-09-05 14:31:30 -0300544 struct smp_chan *smp = conn->smp_chan;
Anderson Brigliaeb492e02011-06-09 18:50:40 -0300545 __u8 authreq;
546
Vinicius Costa Gomes3a0259b2011-06-09 18:50:43 -0300547 BT_DBG("conn %p hcon %p level 0x%2.2x", conn, hcon, sec_level);
548
Andre Guedes2e65c9d2011-06-30 19:20:56 -0300549 if (!lmp_host_le_capable(hcon->hdev))
550 return 1;
551
Vinicius Costa Gomesf1cb9af2011-01-26 21:42:57 -0300552 if (sec_level == BT_SECURITY_LOW)
Anderson Brigliaeb492e02011-06-09 18:50:40 -0300553 return 1;
Vinicius Costa Gomesf1cb9af2011-01-26 21:42:57 -0300554
555 if (hcon->sec_level >= sec_level)
556 return 1;
557
Vinicius Costa Gomes3a0259b2011-06-09 18:50:43 -0300558 if (hcon->link_mode & HCI_LM_MASTER) {
Vinicius Costa Gomes02bc7452011-07-07 18:59:41 -0300559 struct link_key *key;
560
561 key = hci_find_link_key_type(hcon->hdev, conn->dst,
562 HCI_LK_SMP_LTK);
563 if (key) {
564 struct key_master_id *master = (void *) key->data;
565
Vinicius Costa Gomesd26a2342011-08-19 21:06:51 -0300566 if (test_and_set_bit(HCI_CONN_ENCRYPT_PEND,
567 &hcon->pend))
568 goto done;
569
Vinicius Costa Gomes02bc7452011-07-07 18:59:41 -0300570 hci_le_start_enc(hcon, master->ediv, master->rand,
571 key->val);
Vinicius Costa Gomes726b4ff2011-07-08 18:31:45 -0300572 hcon->enc_key_size = key->pin_len;
573
Vinicius Costa Gomes02bc7452011-07-07 18:59:41 -0300574 goto done;
575 }
Vinicius Costa Gomesd26a2342011-08-19 21:06:51 -0300576 }
577
578 if (test_and_set_bit(HCI_CONN_LE_SMP_PEND, &hcon->pend))
579 return 0;
580
Vinicius Costa Gomes8aab4752011-09-05 14:31:31 -0300581 smp = smp_chan_create(conn);
Vinicius Costa Gomesd26a2342011-08-19 21:06:51 -0300582
583 authreq = seclevel_to_authreq(sec_level);
584
585 if (hcon->link_mode & HCI_LM_MASTER) {
586 struct smp_cmd_pairing cp;
Anderson Brigliaf01ead32011-06-09 18:50:45 -0300587
Vinicius Costa Gomes54790f72011-07-07 18:59:38 -0300588 build_pairing_cmd(conn, &cp, NULL, authreq);
Vinicius Costa Gomes1c1def02011-09-05 14:31:30 -0300589 smp->preq[0] = SMP_CMD_PAIRING_REQ;
590 memcpy(&smp->preq[1], &cp, sizeof(cp));
Anderson Brigliaf01ead32011-06-09 18:50:45 -0300591
Anderson Brigliaeb492e02011-06-09 18:50:40 -0300592 smp_send_cmd(conn, SMP_CMD_PAIRING_REQ, sizeof(cp), &cp);
593 } else {
594 struct smp_cmd_security_req cp;
595 cp.auth_req = authreq;
596 smp_send_cmd(conn, SMP_CMD_SECURITY_REQ, sizeof(cp), &cp);
597 }
598
Vinicius Costa Gomes02bc7452011-07-07 18:59:41 -0300599done:
Vinicius Costa Gomesf1cb9af2011-01-26 21:42:57 -0300600 hcon->pending_sec_level = sec_level;
Vinicius Costa Gomesf1cb9af2011-01-26 21:42:57 -0300601
Anderson Brigliaeb492e02011-06-09 18:50:40 -0300602 return 0;
603}
604
Vinicius Costa Gomes7034b912011-07-07 18:59:34 -0300605static int smp_cmd_encrypt_info(struct l2cap_conn *conn, struct sk_buff *skb)
606{
Vinicius Costa Gomes16b90832011-07-07 18:59:39 -0300607 struct smp_cmd_encrypt_info *rp = (void *) skb->data;
Vinicius Costa Gomes1c1def02011-09-05 14:31:30 -0300608 struct smp_chan *smp = conn->smp_chan;
Vinicius Costa Gomes16b90832011-07-07 18:59:39 -0300609
610 skb_pull(skb, sizeof(*rp));
611
Vinicius Costa Gomes1c1def02011-09-05 14:31:30 -0300612 memcpy(smp->tk, rp->ltk, sizeof(smp->tk));
Vinicius Costa Gomes16b90832011-07-07 18:59:39 -0300613
Vinicius Costa Gomes7034b912011-07-07 18:59:34 -0300614 return 0;
615}
616
617static int smp_cmd_master_ident(struct l2cap_conn *conn, struct sk_buff *skb)
618{
Vinicius Costa Gomes16b90832011-07-07 18:59:39 -0300619 struct smp_cmd_master_ident *rp = (void *) skb->data;
Vinicius Costa Gomes1c1def02011-09-05 14:31:30 -0300620 struct smp_chan *smp = conn->smp_chan;
Vinicius Costa Gomes7034b912011-07-07 18:59:34 -0300621
Vinicius Costa Gomes16b90832011-07-07 18:59:39 -0300622 skb_pull(skb, sizeof(*rp));
623
Vinicius Costa Gomes1c1def02011-09-05 14:31:30 -0300624 hci_add_ltk(conn->hcon->hdev, 1, conn->src, smp->smp_key_size,
625 rp->ediv, rp->rand, smp->tk);
Vinicius Costa Gomes7034b912011-07-07 18:59:34 -0300626
627 smp_distribute_keys(conn, 1);
628
629 return 0;
630}
631
Anderson Brigliaeb492e02011-06-09 18:50:40 -0300632int smp_sig_channel(struct l2cap_conn *conn, struct sk_buff *skb)
633{
634 __u8 code = skb->data[0];
635 __u8 reason;
636 int err = 0;
637
Andre Guedes2e65c9d2011-06-30 19:20:56 -0300638 if (!lmp_host_le_capable(conn->hcon->hdev)) {
639 err = -ENOTSUPP;
640 reason = SMP_PAIRING_NOTSUPP;
641 goto done;
642 }
643
Anderson Brigliaeb492e02011-06-09 18:50:40 -0300644 skb_pull(skb, sizeof(code));
645
646 switch (code) {
647 case SMP_CMD_PAIRING_REQ:
Vinicius Costa Gomesda85e5e2011-06-09 18:50:53 -0300648 reason = smp_cmd_pairing_req(conn, skb);
Anderson Brigliaeb492e02011-06-09 18:50:40 -0300649 break;
650
651 case SMP_CMD_PAIRING_FAIL:
Vinicius Costa Gomesda85e5e2011-06-09 18:50:53 -0300652 reason = 0;
653 err = -EPERM;
Anderson Brigliaeb492e02011-06-09 18:50:40 -0300654 break;
655
656 case SMP_CMD_PAIRING_RSP:
Vinicius Costa Gomesda85e5e2011-06-09 18:50:53 -0300657 reason = smp_cmd_pairing_rsp(conn, skb);
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300658 break;
659
660 case SMP_CMD_SECURITY_REQ:
Vinicius Costa Gomesda85e5e2011-06-09 18:50:53 -0300661 reason = smp_cmd_security_req(conn, skb);
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300662 break;
663
Anderson Brigliaeb492e02011-06-09 18:50:40 -0300664 case SMP_CMD_PAIRING_CONFIRM:
Vinicius Costa Gomesda85e5e2011-06-09 18:50:53 -0300665 reason = smp_cmd_pairing_confirm(conn, skb);
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300666 break;
667
Anderson Brigliaeb492e02011-06-09 18:50:40 -0300668 case SMP_CMD_PAIRING_RANDOM:
Vinicius Costa Gomesda85e5e2011-06-09 18:50:53 -0300669 reason = smp_cmd_pairing_random(conn, skb);
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300670 break;
671
Anderson Brigliaeb492e02011-06-09 18:50:40 -0300672 case SMP_CMD_ENCRYPT_INFO:
Vinicius Costa Gomes7034b912011-07-07 18:59:34 -0300673 reason = smp_cmd_encrypt_info(conn, skb);
674 break;
675
Anderson Brigliaeb492e02011-06-09 18:50:40 -0300676 case SMP_CMD_MASTER_IDENT:
Vinicius Costa Gomes7034b912011-07-07 18:59:34 -0300677 reason = smp_cmd_master_ident(conn, skb);
678 break;
679
Anderson Brigliaeb492e02011-06-09 18:50:40 -0300680 case SMP_CMD_IDENT_INFO:
681 case SMP_CMD_IDENT_ADDR_INFO:
682 case SMP_CMD_SIGN_INFO:
Vinicius Costa Gomes7034b912011-07-07 18:59:34 -0300683 /* Just ignored */
684 reason = 0;
685 break;
686
Anderson Brigliaeb492e02011-06-09 18:50:40 -0300687 default:
688 BT_DBG("Unknown command code 0x%2.2x", code);
689
690 reason = SMP_CMD_NOTSUPP;
Vinicius Costa Gomes3a0259b2011-06-09 18:50:43 -0300691 err = -EOPNOTSUPP;
692 goto done;
693 }
694
695done:
696 if (reason)
Anderson Brigliaeb492e02011-06-09 18:50:40 -0300697 smp_send_cmd(conn, SMP_CMD_PAIRING_FAIL, sizeof(reason),
698 &reason);
Anderson Brigliaeb492e02011-06-09 18:50:40 -0300699
700 kfree_skb(skb);
701 return err;
702}
Vinicius Costa Gomes7034b912011-07-07 18:59:34 -0300703
704int smp_distribute_keys(struct l2cap_conn *conn, __u8 force)
705{
706 struct smp_cmd_pairing *req, *rsp;
Vinicius Costa Gomes1c1def02011-09-05 14:31:30 -0300707 struct smp_chan *smp = conn->smp_chan;
Vinicius Costa Gomes7034b912011-07-07 18:59:34 -0300708 __u8 *keydist;
709
710 BT_DBG("conn %p force %d", conn, force);
711
Vinicius Costa Gomesd26a2342011-08-19 21:06:51 -0300712 if (!test_bit(HCI_CONN_LE_SMP_PEND, &conn->hcon->pend))
713 return 0;
714
Vinicius Costa Gomes1c1def02011-09-05 14:31:30 -0300715 rsp = (void *) &smp->prsp[1];
Vinicius Costa Gomes7034b912011-07-07 18:59:34 -0300716
717 /* The responder sends its keys first */
718 if (!force && conn->hcon->out && (rsp->resp_key_dist & 0x07))
719 return 0;
720
Vinicius Costa Gomes1c1def02011-09-05 14:31:30 -0300721 req = (void *) &smp->preq[1];
Vinicius Costa Gomes7034b912011-07-07 18:59:34 -0300722
723 if (conn->hcon->out) {
724 keydist = &rsp->init_key_dist;
725 *keydist &= req->init_key_dist;
726 } else {
727 keydist = &rsp->resp_key_dist;
728 *keydist &= req->resp_key_dist;
729 }
730
731
732 BT_DBG("keydist 0x%x", *keydist);
733
734 if (*keydist & SMP_DIST_ENC_KEY) {
735 struct smp_cmd_encrypt_info enc;
736 struct smp_cmd_master_ident ident;
737 __le16 ediv;
738
739 get_random_bytes(enc.ltk, sizeof(enc.ltk));
740 get_random_bytes(&ediv, sizeof(ediv));
741 get_random_bytes(ident.rand, sizeof(ident.rand));
742
743 smp_send_cmd(conn, SMP_CMD_ENCRYPT_INFO, sizeof(enc), &enc);
744
Vinicius Costa Gomes1c1def02011-09-05 14:31:30 -0300745 hci_add_ltk(conn->hcon->hdev, 1, conn->dst, smp->smp_key_size,
Vinicius Costa Gomes726b4ff2011-07-08 18:31:45 -0300746 ediv, ident.rand, enc.ltk);
Vinicius Costa Gomes16b90832011-07-07 18:59:39 -0300747
Vinicius Costa Gomes7034b912011-07-07 18:59:34 -0300748 ident.ediv = cpu_to_le16(ediv);
749
750 smp_send_cmd(conn, SMP_CMD_MASTER_IDENT, sizeof(ident), &ident);
751
752 *keydist &= ~SMP_DIST_ENC_KEY;
753 }
754
755 if (*keydist & SMP_DIST_ID_KEY) {
756 struct smp_cmd_ident_addr_info addrinfo;
757 struct smp_cmd_ident_info idinfo;
758
759 /* Send a dummy key */
760 get_random_bytes(idinfo.irk, sizeof(idinfo.irk));
761
762 smp_send_cmd(conn, SMP_CMD_IDENT_INFO, sizeof(idinfo), &idinfo);
763
764 /* Just public address */
765 memset(&addrinfo, 0, sizeof(addrinfo));
766 bacpy(&addrinfo.bdaddr, conn->src);
767
768 smp_send_cmd(conn, SMP_CMD_IDENT_ADDR_INFO, sizeof(addrinfo),
769 &addrinfo);
770
771 *keydist &= ~SMP_DIST_ID_KEY;
772 }
773
774 if (*keydist & SMP_DIST_SIGN) {
775 struct smp_cmd_sign_info sign;
776
777 /* Send a dummy key */
778 get_random_bytes(sign.csrk, sizeof(sign.csrk));
779
780 smp_send_cmd(conn, SMP_CMD_SIGN_INFO, sizeof(sign), &sign);
781
782 *keydist &= ~SMP_DIST_SIGN;
783 }
784
Vinicius Costa Gomesd26a2342011-08-19 21:06:51 -0300785 if (conn->hcon->out || force) {
786 clear_bit(HCI_CONN_LE_SMP_PEND, &conn->hcon->pend);
787 del_timer(&conn->security_timer);
Vinicius Costa Gomes8aab4752011-09-05 14:31:31 -0300788 smp_chan_destroy(conn);
Vinicius Costa Gomesd26a2342011-08-19 21:06:51 -0300789 }
790
Vinicius Costa Gomes7034b912011-07-07 18:59:34 -0300791 return 0;
792}