blob: 6838fd52bb01870f0cc5a9b98761d788216e8945 [file] [log] [blame]
Anderson Briglia133e14c2011-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>
Brian Gixa68668b2011-08-11 15:49:36 -070026#include <net/bluetooth/mgmt.h>
Anderson Briglia133e14c2011-06-09 18:50:40 -030027#include <net/bluetooth/smp.h>
Anderson Briglia8e7a3c52011-06-09 18:50:44 -030028#include <linux/crypto.h>
29#include <crypto/b128ops.h>
Brian Gixa68668b2011-08-11 15:49:36 -070030#include <asm/unaligned.h>
Anderson Briglia8e7a3c52011-06-09 18:50:44 -030031
Vinicius Costa Gomesb19d5ce2011-06-14 13:37:41 -030032#define SMP_TIMEOUT 30000 /* 30 seconds */
33
Brian Gixa68668b2011-08-11 15:49:36 -070034#ifndef FALSE
35#define FALSE 0
36#define TRUE (!FALSE)
37#endif
38
39static int smp_distribute_keys(struct l2cap_conn *conn, __u8 force);
40
Anderson Briglia8e7a3c52011-06-09 18:50:44 -030041static inline void swap128(u8 src[16], u8 dst[16])
42{
43 int i;
44 for (i = 0; i < 16; i++)
45 dst[15 - i] = src[i];
46}
47
48static inline void swap56(u8 src[7], u8 dst[7])
49{
50 int i;
51 for (i = 0; i < 7; i++)
52 dst[6 - i] = src[i];
53}
54
55static int smp_e(struct crypto_blkcipher *tfm, const u8 *k, u8 *r)
56{
57 struct blkcipher_desc desc;
58 struct scatterlist sg;
59 int err, iv_len;
60 unsigned char iv[128];
61
62 if (tfm == NULL) {
63 BT_ERR("tfm %p", tfm);
64 return -EINVAL;
65 }
66
67 desc.tfm = tfm;
68 desc.flags = 0;
69
70 err = crypto_blkcipher_setkey(tfm, k, 16);
71 if (err) {
72 BT_ERR("cipher setkey failed: %d", err);
73 return err;
74 }
75
76 sg_init_one(&sg, r, 16);
77
78 iv_len = crypto_blkcipher_ivsize(tfm);
79 if (iv_len) {
80 memset(&iv, 0xff, iv_len);
81 crypto_blkcipher_set_iv(tfm, iv, iv_len);
82 }
83
84 err = crypto_blkcipher_encrypt(&desc, &sg, &sg, 16);
85 if (err)
86 BT_ERR("Encrypt data error %d", err);
87
88 return err;
89}
90
91static int smp_c1(struct crypto_blkcipher *tfm, u8 k[16], u8 r[16],
92 u8 preq[7], u8 pres[7], u8 _iat, bdaddr_t *ia,
93 u8 _rat, bdaddr_t *ra, u8 res[16])
94{
95 u8 p1[16], p2[16];
96 int err;
97
98 memset(p1, 0, 16);
99
100 /* p1 = pres || preq || _rat || _iat */
101 swap56(pres, p1);
102 swap56(preq, p1 + 7);
103 p1[14] = _rat;
104 p1[15] = _iat;
105
106 memset(p2, 0, 16);
107
108 /* p2 = padding || ia || ra */
109 baswap((bdaddr_t *) (p2 + 4), ia);
110 baswap((bdaddr_t *) (p2 + 10), ra);
111
112 /* res = r XOR p1 */
113 u128_xor((u128 *) res, (u128 *) r, (u128 *) p1);
114
115 /* res = e(k, res) */
116 err = smp_e(tfm, k, res);
117 if (err) {
118 BT_ERR("Encrypt data error");
119 return err;
120 }
121
122 /* res = res XOR p2 */
123 u128_xor((u128 *) res, (u128 *) res, (u128 *) p2);
124
125 /* res = e(k, res) */
126 err = smp_e(tfm, k, res);
127 if (err)
128 BT_ERR("Encrypt data error");
129
130 return err;
131}
132
133static int smp_s1(struct crypto_blkcipher *tfm, u8 k[16],
134 u8 r1[16], u8 r2[16], u8 _r[16])
135{
136 int err;
137
138 /* Just least significant octets from r1 and r2 are considered */
139 memcpy(_r, r1 + 8, 8);
140 memcpy(_r + 8, r2 + 8, 8);
141
142 err = smp_e(tfm, k, _r);
143 if (err)
144 BT_ERR("Encrypt data error");
145
146 return err;
147}
148
149static int smp_rand(u8 *buf)
150{
151 get_random_bytes(buf, 16);
152
153 return 0;
154}
Anderson Briglia133e14c2011-06-09 18:50:40 -0300155
156static struct sk_buff *smp_build_cmd(struct l2cap_conn *conn, u8 code,
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700157 u16 dlen, void *data)
Anderson Briglia133e14c2011-06-09 18:50:40 -0300158{
159 struct sk_buff *skb;
160 struct l2cap_hdr *lh;
161 int len;
162
163 len = L2CAP_HDR_SIZE + sizeof(code) + dlen;
164
165 if (len > conn->mtu)
166 return NULL;
167
168 skb = bt_skb_alloc(len, GFP_ATOMIC);
169 if (!skb)
170 return NULL;
171
172 lh = (struct l2cap_hdr *) skb_put(skb, L2CAP_HDR_SIZE);
173 lh->len = cpu_to_le16(sizeof(code) + dlen);
174 lh->cid = cpu_to_le16(L2CAP_CID_SMP);
175
176 memcpy(skb_put(skb, sizeof(code)), &code, sizeof(code));
177
178 memcpy(skb_put(skb, dlen), data, dlen);
179
180 return skb;
181}
182
183static void smp_send_cmd(struct l2cap_conn *conn, u8 code, u16 len, void *data)
184{
185 struct sk_buff *skb = smp_build_cmd(conn, code, len, data);
186
187 BT_DBG("code 0x%2.2x", code);
188
189 if (!skb)
190 return;
191
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700192 hci_send_acl(conn->hcon, NULL, skb, 0);
Anderson Briglia133e14c2011-06-09 18:50:40 -0300193}
194
Brian Gixa68668b2011-08-11 15:49:36 -0700195static __u8 authreq_to_seclevel(__u8 authreq)
196{
197 if (authreq & SMP_AUTH_MITM)
198 return BT_SECURITY_HIGH;
199 else if (authreq & SMP_AUTH_BONDING)
200 return BT_SECURITY_MEDIUM;
201 else
202 return BT_SECURITY_LOW;
203}
204
Vinicius Costa Gomes64532ec2011-06-09 18:50:53 -0300205static __u8 seclevel_to_authreq(__u8 level)
206{
207 switch (level) {
208 case BT_SECURITY_HIGH:
Brian Gixa68668b2011-08-11 15:49:36 -0700209 return SMP_AUTH_MITM | SMP_AUTH_BONDING;
Vinicius Costa Gomes64532ec2011-06-09 18:50:53 -0300210
211 default:
212 return SMP_AUTH_NONE;
213 }
214}
215
Vinicius Costa Gomes901920a2011-06-09 18:50:52 -0300216static void build_pairing_cmd(struct l2cap_conn *conn,
Vinicius Costa Gomes10daf972011-07-07 18:59:38 -0300217 struct smp_cmd_pairing *req,
218 struct smp_cmd_pairing *rsp,
219 __u8 authreq)
Vinicius Costa Gomes901920a2011-06-09 18:50:52 -0300220{
Brian Gixa68668b2011-08-11 15:49:36 -0700221 struct hci_conn *hcon = conn->hcon;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700222 u8 all_keys = 0;
Brian Gixa68668b2011-08-11 15:49:36 -0700223 u8 dist_keys = 0;
Vinicius Costa Gomes10daf972011-07-07 18:59:38 -0300224
Brian Gixa68668b2011-08-11 15:49:36 -0700225 dist_keys = SMP_DIST_ENC_KEY;
226 authreq |= SMP_AUTH_BONDING;
227
228 BT_DBG("conn->hcon->io_capability:%d", conn->hcon->io_capability);
Vinicius Costa Gomes10daf972011-07-07 18:59:38 -0300229
230 if (rsp == NULL) {
231 req->io_capability = conn->hcon->io_capability;
Brian Gixa68668b2011-08-11 15:49:36 -0700232 req->oob_flag = hcon->oob ? SMP_OOB_PRESENT :
233 SMP_OOB_NOT_PRESENT;
Vinicius Costa Gomes10daf972011-07-07 18:59:38 -0300234 req->max_key_size = SMP_MAX_ENC_KEY_SIZE;
Brian Gixa68668b2011-08-11 15:49:36 -0700235 req->init_key_dist = all_keys;
236 req->resp_key_dist = dist_keys;
Vinicius Costa Gomes10daf972011-07-07 18:59:38 -0300237 req->auth_req = authreq;
Brian Gixa68668b2011-08-11 15:49:36 -0700238 BT_DBG("SMP_CMD_PAIRING_REQ %d %d %d %d %2.2x %2.2x",
239 req->io_capability, req->oob_flag,
240 req->auth_req, req->max_key_size,
241 req->init_key_dist, req->resp_key_dist);
Vinicius Costa Gomes10daf972011-07-07 18:59:38 -0300242 return;
243 }
244
Brian Gixa68668b2011-08-11 15:49:36 -0700245 /* Only request OOB if remote AND we support it */
246 if (req->oob_flag)
247 rsp->oob_flag = hcon->oob ? SMP_OOB_PRESENT :
248 SMP_OOB_NOT_PRESENT;
249 else
250 rsp->oob_flag = SMP_OOB_NOT_PRESENT;
251
Vinicius Costa Gomes10daf972011-07-07 18:59:38 -0300252 rsp->io_capability = conn->hcon->io_capability;
Vinicius Costa Gomes10daf972011-07-07 18:59:38 -0300253 rsp->max_key_size = SMP_MAX_ENC_KEY_SIZE;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700254 rsp->init_key_dist = req->init_key_dist & all_keys;
Vinicius Costa Gomes10daf972011-07-07 18:59:38 -0300255 rsp->resp_key_dist = req->resp_key_dist & dist_keys;
256 rsp->auth_req = authreq;
Brian Gixa68668b2011-08-11 15:49:36 -0700257 BT_DBG("SMP_CMD_PAIRING_RSP %d %d %d %d %2.2x %2.2x",
258 req->io_capability, req->oob_flag, req->auth_req,
259 req->max_key_size, req->init_key_dist,
260 req->resp_key_dist);
Vinicius Costa Gomes901920a2011-06-09 18:50:52 -0300261}
262
Vinicius Costa Gomes397d9ae2011-06-14 13:37:42 -0300263static u8 check_enc_key_size(struct l2cap_conn *conn, __u8 max_key_size)
264{
Brian Gixa68668b2011-08-11 15:49:36 -0700265 struct hci_conn *hcon = conn->hcon;
266
Vinicius Costa Gomes397d9ae2011-06-14 13:37:42 -0300267 if ((max_key_size > SMP_MAX_ENC_KEY_SIZE) ||
268 (max_key_size < SMP_MIN_ENC_KEY_SIZE))
269 return SMP_ENC_KEY_SIZE;
270
Brian Gixa68668b2011-08-11 15:49:36 -0700271 hcon->smp_key_size = max_key_size;
Vinicius Costa Gomes397d9ae2011-06-14 13:37:42 -0300272
273 return 0;
274}
275
Brian Gixa68668b2011-08-11 15:49:36 -0700276#define JUST_WORKS SMP_JUST_WORKS
277#define REQ_PASSKEY SMP_REQ_PASSKEY
278#define CFM_PASSKEY SMP_CFM_PASSKEY
279#define JUST_CFM SMP_JUST_CFM
280#define OVERLAP SMP_OVERLAP
281static const u8 gen_method[5][5] = {
282 {JUST_WORKS, JUST_CFM, REQ_PASSKEY, JUST_WORKS, REQ_PASSKEY},
283 {JUST_WORKS, JUST_CFM, REQ_PASSKEY, JUST_WORKS, REQ_PASSKEY},
284 {CFM_PASSKEY, CFM_PASSKEY, REQ_PASSKEY, JUST_WORKS, CFM_PASSKEY},
285 {JUST_WORKS, JUST_CFM, JUST_WORKS, JUST_WORKS, JUST_CFM},
286 {CFM_PASSKEY, CFM_PASSKEY, REQ_PASSKEY, JUST_WORKS, OVERLAP}
287};
288
289static int tk_request(struct l2cap_conn *conn, u8 remote_oob, u8 auth,
290 u8 local_io, u8 remote_io)
291{
292 struct hci_conn *hcon = conn->hcon;
293 u8 method;
294 u32 passkey = 0;
Brian Gix3dd70172011-09-16 21:38:54 -0700295 int ret = 0;
Brian Gixa68668b2011-08-11 15:49:36 -0700296
297 /* Initialize key to JUST WORKS */
298 memset(hcon->tk, 0, sizeof(hcon->tk));
299 hcon->tk_valid = FALSE;
300 hcon->auth = auth;
301
302 /* By definition, OOB data will be used if both sides have it available
303 */
304 if (remote_oob && hcon->oob) {
305 method = SMP_REQ_OOB;
306 goto agent_request;
307 }
308
309 BT_DBG("tk_request: auth:%d lcl:%d rem:%d", auth, local_io, remote_io);
310
311 /* If neither side wants MITM, use JUST WORKS */
312 /* If either side has unknown io_caps, use JUST_WORKS */
313 if (!(auth & SMP_AUTH_MITM) ||
314 local_io > SMP_IO_KEYBOARD_DISPLAY ||
315 remote_io > SMP_IO_KEYBOARD_DISPLAY) {
316 hcon->auth &= ~SMP_AUTH_MITM;
317 hcon->tk_valid = TRUE;
318 return 0;
319 }
320
321 /* MITM is now officially requested, but not required */
322 /* Determine what we need (if anything) from the agent */
323 method = gen_method[local_io][remote_io];
324
325 BT_DBG("tk_method: %d", method);
326
327 if (method == SMP_JUST_WORKS || method == SMP_JUST_CFM)
328 hcon->auth &= ~SMP_AUTH_MITM;
329
330 /* Don't bother confirming unbonded JUST_WORKS */
331 if (!(auth & SMP_AUTH_BONDING) && method == SMP_JUST_CFM) {
332 hcon->tk_valid = TRUE;
333 return 0;
334 } else if (method == SMP_JUST_WORKS) {
335 hcon->tk_valid = TRUE;
336 return 0;
337 } else if (method == SMP_OVERLAP) {
338 if (hcon->link_mode & HCI_LM_MASTER)
339 method = SMP_CFM_PASSKEY;
340 else
341 method = SMP_REQ_PASSKEY;
342 }
343
344 BT_DBG("tk_method-2: %d", method);
345
346 if (method == SMP_CFM_PASSKEY) {
347 u8 key[16];
348 /* Generate a passkey for display. It is not valid until
349 * confirmed.
350 */
351 memset(key, 0, sizeof(key));
352 get_random_bytes(&passkey, sizeof(passkey));
353 passkey %= 1000000;
354 put_unaligned_le32(passkey, key);
355 swap128(key, hcon->tk);
356 BT_DBG("PassKey: %d", passkey);
357 }
358
359agent_request:
Brian Gix3dd70172011-09-16 21:38:54 -0700360 hci_dev_lock(hcon->hdev);
361
Brian Gixa68668b2011-08-11 15:49:36 -0700362 switch (method) {
363 case SMP_REQ_PASSKEY:
Brian Gix3dd70172011-09-16 21:38:54 -0700364 ret = mgmt_user_confirm_request(hcon->hdev->id,
365 HCI_EV_USER_PASSKEY_REQUEST, conn->dst, 0);
366 break;
Brian Gixa68668b2011-08-11 15:49:36 -0700367 case SMP_CFM_PASSKEY:
368 default:
Brian Gix3dd70172011-09-16 21:38:54 -0700369 ret = mgmt_user_confirm_request(hcon->hdev->id,
370 HCI_EV_USER_CONFIRM_REQUEST, conn->dst, passkey);
371 break;
Brian Gixa68668b2011-08-11 15:49:36 -0700372 }
Brian Gix3dd70172011-09-16 21:38:54 -0700373
374 hci_dev_unlock(hcon->hdev);
375
376 return ret;
Brian Gixa68668b2011-08-11 15:49:36 -0700377}
378
379static int send_pairing_confirm(struct l2cap_conn *conn)
380{
381 struct hci_conn *hcon = conn->hcon;
382 struct crypto_blkcipher *tfm = hcon->hdev->tfm;
383 struct smp_cmd_pairing_confirm cp;
384 int ret;
385 u8 res[16];
386
387 if (conn->hcon->out)
388 ret = smp_c1(tfm, hcon->tk, hcon->prnd, hcon->preq, hcon->prsp,
389 0, conn->src, hcon->dst_type, conn->dst, res);
390 else
391 ret = smp_c1(tfm, hcon->tk, hcon->prnd, hcon->preq, hcon->prsp,
392 hcon->dst_type, conn->dst, 0, conn->src, res);
393
394 if (ret)
395 return SMP_CONFIRM_FAILED;
396
397 swap128(res, cp.confirm_val);
398
399 hcon->cfm_pending = FALSE;
400
401 smp_send_cmd(conn, SMP_CMD_PAIRING_CONFIRM, sizeof(cp), &cp);
402
403 return 0;
404}
405
Brian Gix6d5fb8a2011-09-09 14:53:04 -0700406int le_user_confirm_reply(struct hci_conn *hcon, u16 mgmt_op, void *cp)
Brian Gixa68668b2011-08-11 15:49:36 -0700407{
408 struct mgmt_cp_user_passkey_reply *psk_reply = cp;
Brian Gix6d5fb8a2011-09-09 14:53:04 -0700409 struct l2cap_conn *conn = hcon->smp_conn;
Brian Gixa68668b2011-08-11 15:49:36 -0700410 u8 key[16];
411 u8 reason = 0;
412 int ret = 0;
413
414 BT_DBG("");
415
Brian Gix6d5fb8a2011-09-09 14:53:04 -0700416 hcon->tk_valid = TRUE;
Brian Gixa68668b2011-08-11 15:49:36 -0700417
418 switch (mgmt_op) {
419 case MGMT_OP_USER_CONFIRM_NEG_REPLY:
420 reason = SMP_CONFIRM_FAILED;
421 break;
422 case MGMT_OP_USER_CONFIRM_REPLY:
423 break;
424 case MGMT_OP_USER_PASSKEY_REPLY:
425 memset(key, 0, sizeof(key));
426 BT_DBG("PassKey: %d", psk_reply->passkey);
427 put_unaligned_le32(psk_reply->passkey, key);
Brian Gix6d5fb8a2011-09-09 14:53:04 -0700428 swap128(key, hcon->tk);
Brian Gixa68668b2011-08-11 15:49:36 -0700429 break;
430 default:
431 reason = SMP_CONFIRM_FAILED;
432 ret = -EOPNOTSUPP;
433 break;
434 }
435
436 if (reason) {
437 BT_DBG("smp_send_cmd: SMP_CMD_PAIRING_FAIL");
438 smp_send_cmd(conn, SMP_CMD_PAIRING_FAIL, sizeof(reason),
439 &reason);
Brian Gixe9ceb522011-09-22 10:46:35 -0700440 del_timer(&hcon->smp_timer);
Brian Gix8d0b7d62011-10-12 15:12:42 -0700441 clear_bit(HCI_CONN_ENCRYPT_PEND, &hcon->pend);
Brian Gix58ba0772011-09-23 13:40:16 -0700442 mgmt_auth_failed(hcon->hdev->id, conn->dst, reason);
Brian Gix6d5fb8a2011-09-09 14:53:04 -0700443 hci_conn_put(hcon);
444 } else if (hcon->cfm_pending) {
Brian Gixa68668b2011-08-11 15:49:36 -0700445 BT_DBG("send_pairing_confirm");
446 ret = send_pairing_confirm(conn);
447 }
448
449 return ret;
450}
451
Vinicius Costa Gomes64532ec2011-06-09 18:50:53 -0300452static u8 smp_cmd_pairing_req(struct l2cap_conn *conn, struct sk_buff *skb)
Anderson Briglia13b48392011-06-09 18:50:42 -0300453{
Brian Gixa68668b2011-08-11 15:49:36 -0700454 struct hci_conn *hcon = conn->hcon;
Vinicius Costa Gomes397d9ae2011-06-14 13:37:42 -0300455 struct smp_cmd_pairing rsp, *req = (void *) skb->data;
456 u8 key_size;
Brian Gixa68668b2011-08-11 15:49:36 -0700457 u8 auth = SMP_AUTH_NONE;
458 int ret;
Anderson Briglia13b48392011-06-09 18:50:42 -0300459
460 BT_DBG("conn %p", conn);
461
Brian Gixa68668b2011-08-11 15:49:36 -0700462 hcon->preq[0] = SMP_CMD_PAIRING_REQ;
463 memcpy(&hcon->preq[1], req, sizeof(*req));
Vinicius Costa Gomes397d9ae2011-06-14 13:37:42 -0300464 skb_pull(skb, sizeof(*req));
Anderson Briglia13b48392011-06-09 18:50:42 -0300465
Brian Gixa68668b2011-08-11 15:49:36 -0700466 if (req->oob_flag && hcon->oob) {
467 /* By definition, OOB data pairing will have MITM protection */
468 auth = req->auth_req | SMP_AUTH_MITM;
469 } else if (req->auth_req & SMP_AUTH_BONDING) {
470 /* We will attempt MITM for all Bonding attempts */
471 auth = SMP_AUTH_BONDING | SMP_AUTH_MITM;
472 }
Vinicius Costa Gomes64532ec2011-06-09 18:50:53 -0300473
474 /* We didn't start the pairing, so no requirements */
Brian Gixa68668b2011-08-11 15:49:36 -0700475 build_pairing_cmd(conn, req, &rsp, auth);
Vinicius Costa Gomes397d9ae2011-06-14 13:37:42 -0300476
477 key_size = min(req->max_key_size, rsp.max_key_size);
478 if (check_enc_key_size(conn, key_size))
479 return SMP_ENC_KEY_SIZE;
Anderson Briglia13b48392011-06-09 18:50:42 -0300480
Brian Gixa68668b2011-08-11 15:49:36 -0700481 ret = smp_rand(hcon->prnd);
482 if (ret)
483 return SMP_UNSPECIFIED;
Anderson Briglia21b8a2b2011-06-09 18:50:46 -0300484
Brian Gixa68668b2011-08-11 15:49:36 -0700485 /* Request setup of TK */
486 ret = tk_request(conn, req->oob_flag, auth, rsp.io_capability,
487 req->io_capability);
488 if (ret)
489 return SMP_UNSPECIFIED;
490
491 hcon->prsp[0] = SMP_CMD_PAIRING_RSP;
492 memcpy(&hcon->prsp[1], &rsp, sizeof(rsp));
Anderson Brigliac8e856e2011-06-09 18:50:45 -0300493
Vinicius Costa Gomes397d9ae2011-06-14 13:37:42 -0300494 smp_send_cmd(conn, SMP_CMD_PAIRING_RSP, sizeof(rsp), &rsp);
Vinicius Costa Gomes64532ec2011-06-09 18:50:53 -0300495
Brian Gixe9ceb522011-09-22 10:46:35 -0700496 mod_timer(&hcon->smp_timer, jiffies + msecs_to_jiffies(SMP_TIMEOUT));
Vinicius Costa Gomesb19d5ce2011-06-14 13:37:41 -0300497
Vinicius Costa Gomes64532ec2011-06-09 18:50:53 -0300498 return 0;
Anderson Briglia13b48392011-06-09 18:50:42 -0300499}
500
Vinicius Costa Gomes64532ec2011-06-09 18:50:53 -0300501static u8 smp_cmd_pairing_rsp(struct l2cap_conn *conn, struct sk_buff *skb)
Anderson Briglia13b48392011-06-09 18:50:42 -0300502{
Brian Gixa68668b2011-08-11 15:49:36 -0700503 struct hci_conn *hcon = conn->hcon;
Vinicius Costa Gomes397d9ae2011-06-14 13:37:42 -0300504 struct smp_cmd_pairing *req, *rsp = (void *) skb->data;
Brian Gixa68668b2011-08-11 15:49:36 -0700505 u8 key_size, auth = SMP_AUTH_NONE;
Anderson Briglia21b8a2b2011-06-09 18:50:46 -0300506 int ret;
Anderson Briglia13b48392011-06-09 18:50:42 -0300507
508 BT_DBG("conn %p", conn);
509
Vinicius Costa Gomes397d9ae2011-06-14 13:37:42 -0300510 skb_pull(skb, sizeof(*rsp));
Vinicius Costa Gomes64532ec2011-06-09 18:50:53 -0300511
Brian Gixa68668b2011-08-11 15:49:36 -0700512 req = (void *) &hcon->preq[1];
Vinicius Costa Gomes397d9ae2011-06-14 13:37:42 -0300513
514 key_size = min(req->max_key_size, rsp->max_key_size);
515 if (check_enc_key_size(conn, key_size))
516 return SMP_ENC_KEY_SIZE;
517
Brian Gixa68668b2011-08-11 15:49:36 -0700518 hcon->prsp[0] = SMP_CMD_PAIRING_RSP;
519 memcpy(&hcon->prsp[1], rsp, sizeof(*rsp));
Vinicius Costa Gomes64532ec2011-06-09 18:50:53 -0300520
Brian Gixa68668b2011-08-11 15:49:36 -0700521 ret = smp_rand(hcon->prnd);
Anderson Briglia21b8a2b2011-06-09 18:50:46 -0300522 if (ret)
Vinicius Costa Gomes64532ec2011-06-09 18:50:53 -0300523 return SMP_UNSPECIFIED;
Anderson Briglia21b8a2b2011-06-09 18:50:46 -0300524
Brian Gixa68668b2011-08-11 15:49:36 -0700525 if ((req->auth_req & SMP_AUTH_BONDING) &&
526 (rsp->auth_req & SMP_AUTH_BONDING))
527 auth = SMP_AUTH_BONDING;
528
529 auth |= (req->auth_req | rsp->auth_req) & SMP_AUTH_MITM;
530
531 ret = tk_request(conn, req->oob_flag, auth, rsp->io_capability,
532 req->io_capability);
Anderson Briglia21b8a2b2011-06-09 18:50:46 -0300533 if (ret)
Vinicius Costa Gomes64532ec2011-06-09 18:50:53 -0300534 return SMP_UNSPECIFIED;
Anderson Briglia21b8a2b2011-06-09 18:50:46 -0300535
Brian Gixa68668b2011-08-11 15:49:36 -0700536 hcon->cfm_pending = TRUE;
Anderson Briglia21b8a2b2011-06-09 18:50:46 -0300537
Brian Gixa68668b2011-08-11 15:49:36 -0700538 /* Can't compose response until we have been confirmed */
539 if (!hcon->tk_valid)
540 return 0;
541
542 ret = send_pairing_confirm(conn);
543 if (ret)
544 return SMP_CONFIRM_FAILED;
Vinicius Costa Gomes64532ec2011-06-09 18:50:53 -0300545
546 return 0;
Anderson Briglia13b48392011-06-09 18:50:42 -0300547}
548
Vinicius Costa Gomes64532ec2011-06-09 18:50:53 -0300549static u8 smp_cmd_pairing_confirm(struct l2cap_conn *conn, struct sk_buff *skb)
Anderson Briglia13b48392011-06-09 18:50:42 -0300550{
Brian Gixa68668b2011-08-11 15:49:36 -0700551 struct hci_conn *hcon = conn->hcon;
552 int ret;
Anderson Briglia21b8a2b2011-06-09 18:50:46 -0300553
Anderson Briglia13b48392011-06-09 18:50:42 -0300554 BT_DBG("conn %p %s", conn, conn->hcon->out ? "master" : "slave");
555
Brian Gixa68668b2011-08-11 15:49:36 -0700556 memcpy(hcon->pcnf, skb->data, sizeof(hcon->pcnf));
557 skb_pull(skb, sizeof(hcon->pcnf));
Anderson Briglia21b8a2b2011-06-09 18:50:46 -0300558
Anderson Briglia13b48392011-06-09 18:50:42 -0300559 if (conn->hcon->out) {
Anderson Briglia21b8a2b2011-06-09 18:50:46 -0300560 u8 random[16];
Anderson Briglia13b48392011-06-09 18:50:42 -0300561
Brian Gixa68668b2011-08-11 15:49:36 -0700562 swap128(hcon->prnd, random);
Anderson Briglia13b48392011-06-09 18:50:42 -0300563 smp_send_cmd(conn, SMP_CMD_PAIRING_RANDOM, sizeof(random),
Anderson Briglia21b8a2b2011-06-09 18:50:46 -0300564 random);
Brian Gixa68668b2011-08-11 15:49:36 -0700565 } else if (hcon->tk_valid) {
566 ret = send_pairing_confirm(conn);
Anderson Briglia13b48392011-06-09 18:50:42 -0300567
Anderson Briglia21b8a2b2011-06-09 18:50:46 -0300568 if (ret)
Vinicius Costa Gomes64532ec2011-06-09 18:50:53 -0300569 return SMP_CONFIRM_FAILED;
Brian Gixa68668b2011-08-11 15:49:36 -0700570 } else
571 hcon->cfm_pending = TRUE;
Anderson Briglia21b8a2b2011-06-09 18:50:46 -0300572
Vinicius Costa Gomes64532ec2011-06-09 18:50:53 -0300573
Brian Gixe9ceb522011-09-22 10:46:35 -0700574 mod_timer(&hcon->smp_timer, jiffies + msecs_to_jiffies(SMP_TIMEOUT));
Vinicius Costa Gomesb19d5ce2011-06-14 13:37:41 -0300575
Vinicius Costa Gomes64532ec2011-06-09 18:50:53 -0300576 return 0;
Anderson Briglia13b48392011-06-09 18:50:42 -0300577}
578
Vinicius Costa Gomes64532ec2011-06-09 18:50:53 -0300579static u8 smp_cmd_pairing_random(struct l2cap_conn *conn, struct sk_buff *skb)
Anderson Briglia13b48392011-06-09 18:50:42 -0300580{
Vinicius Costa Gomes735038c2011-06-09 18:50:47 -0300581 struct hci_conn *hcon = conn->hcon;
582 struct crypto_blkcipher *tfm = hcon->hdev->tfm;
Anderson Briglia21b8a2b2011-06-09 18:50:46 -0300583 int ret;
Vinicius Costa Gomesc34e25e2011-06-09 18:50:48 -0300584 u8 key[16], res[16], random[16], confirm[16];
Anderson Briglia21b8a2b2011-06-09 18:50:46 -0300585
586 swap128(skb->data, random);
587 skb_pull(skb, sizeof(random));
588
589 if (conn->hcon->out)
Brian Gixa68668b2011-08-11 15:49:36 -0700590 ret = smp_c1(tfm, hcon->tk, random, hcon->preq, hcon->prsp, 0,
591 conn->src, hcon->dst_type, conn->dst,
Anderson Briglia21b8a2b2011-06-09 18:50:46 -0300592 res);
593 else
Brian Gixa68668b2011-08-11 15:49:36 -0700594 ret = smp_c1(tfm, hcon->tk, random, hcon->preq, hcon->prsp,
595 hcon->dst_type, conn->dst, 0, conn->src,
Anderson Briglia21b8a2b2011-06-09 18:50:46 -0300596 res);
597 if (ret)
Vinicius Costa Gomes64532ec2011-06-09 18:50:53 -0300598 return SMP_UNSPECIFIED;
Anderson Briglia13b48392011-06-09 18:50:42 -0300599
600 BT_DBG("conn %p %s", conn, conn->hcon->out ? "master" : "slave");
601
Anderson Briglia21b8a2b2011-06-09 18:50:46 -0300602 swap128(res, confirm);
603
Brian Gixa68668b2011-08-11 15:49:36 -0700604 if (memcmp(hcon->pcnf, confirm, sizeof(hcon->pcnf)) != 0) {
Anderson Briglia21b8a2b2011-06-09 18:50:46 -0300605 BT_ERR("Pairing failed (confirmation values mismatch)");
Vinicius Costa Gomes64532ec2011-06-09 18:50:53 -0300606 return SMP_CONFIRM_FAILED;
Anderson Briglia21b8a2b2011-06-09 18:50:46 -0300607 }
Anderson Briglia13b48392011-06-09 18:50:42 -0300608
609 if (conn->hcon->out) {
Vinicius Costa Gomesf1b45c52011-07-07 18:59:40 -0300610 u8 stk[16], rand[8];
Vinicius Costa Gomes735038c2011-06-09 18:50:47 -0300611 __le16 ediv;
Vinicius Costa Gomes397d9ae2011-06-14 13:37:42 -0300612
Vinicius Costa Gomes735038c2011-06-09 18:50:47 -0300613 memset(rand, 0, sizeof(rand));
614 ediv = 0;
Vinicius Costa Gomesf1b45c52011-07-07 18:59:40 -0300615
Brian Gixa68668b2011-08-11 15:49:36 -0700616 smp_s1(tfm, hcon->tk, random, hcon->prnd, key);
Vinicius Costa Gomesf1b45c52011-07-07 18:59:40 -0300617 swap128(key, stk);
618
Brian Gixa68668b2011-08-11 15:49:36 -0700619 memset(stk + hcon->smp_key_size, 0,
620 SMP_MAX_ENC_KEY_SIZE - hcon->smp_key_size);
Vinicius Costa Gomesf1b45c52011-07-07 18:59:40 -0300621
622 hci_le_start_enc(hcon, ediv, rand, stk);
Brian Gixa68668b2011-08-11 15:49:36 -0700623 hcon->enc_key_size = hcon->smp_key_size;
Anderson Briglia21b8a2b2011-06-09 18:50:46 -0300624 } else {
Vinicius Costa Gomesf1b45c52011-07-07 18:59:40 -0300625 u8 stk[16], r[16], rand[8];
626 __le16 ediv;
627
628 memset(rand, 0, sizeof(rand));
629 ediv = 0;
Anderson Briglia21b8a2b2011-06-09 18:50:46 -0300630
Brian Gixa68668b2011-08-11 15:49:36 -0700631 swap128(hcon->prnd, r);
Anderson Briglia21b8a2b2011-06-09 18:50:46 -0300632 smp_send_cmd(conn, SMP_CMD_PAIRING_RANDOM, sizeof(r), r);
633
Brian Gixa68668b2011-08-11 15:49:36 -0700634 smp_s1(tfm, hcon->tk, hcon->prnd, random, key);
Vinicius Costa Gomesf1b45c52011-07-07 18:59:40 -0300635 swap128(key, stk);
Vinicius Costa Gomes397d9ae2011-06-14 13:37:42 -0300636
Brian Gixa68668b2011-08-11 15:49:36 -0700637 memset(stk + hcon->smp_key_size, 0,
638 SMP_MAX_ENC_KEY_SIZE - hcon->smp_key_size);
Vinicius Costa Gomesf1b45c52011-07-07 18:59:40 -0300639
Brian Gixa68668b2011-08-11 15:49:36 -0700640 hci_add_ltk(conn->hcon->hdev, 0, conn->dst, hcon->smp_key_size,
641 hcon->auth, ediv, rand, stk);
Anderson Briglia13b48392011-06-09 18:50:42 -0300642 }
Vinicius Costa Gomes64532ec2011-06-09 18:50:53 -0300643
644 return 0;
Anderson Briglia13b48392011-06-09 18:50:42 -0300645}
646
Vinicius Costa Gomes64532ec2011-06-09 18:50:53 -0300647static u8 smp_cmd_security_req(struct l2cap_conn *conn, struct sk_buff *skb)
Anderson Briglia13b48392011-06-09 18:50:42 -0300648{
Brian Gixa68668b2011-08-11 15:49:36 -0700649 struct hci_conn *hcon = conn->hcon;
Anderson Briglia13b48392011-06-09 18:50:42 -0300650 struct smp_cmd_security_req *rp = (void *) skb->data;
651 struct smp_cmd_pairing cp;
Brian Gixa68668b2011-08-11 15:49:36 -0700652 struct link_key *key;
Anderson Briglia13b48392011-06-09 18:50:42 -0300653
654 BT_DBG("conn %p", conn);
655
Vinicius Costa Gomesa5474a82011-01-26 21:42:57 -0300656 if (test_bit(HCI_CONN_ENCRYPT_PEND, &hcon->pend))
Vinicius Costa Gomes64532ec2011-06-09 18:50:53 -0300657 return 0;
Vinicius Costa Gomesa5474a82011-01-26 21:42:57 -0300658
Brian Gixa68668b2011-08-11 15:49:36 -0700659 key = hci_find_link_key_type(hcon->hdev, conn->dst, KEY_TYPE_LTK);
660 if (key && ((key->auth & SMP_AUTH_MITM) ||
661 !(rp->auth_req & SMP_AUTH_MITM))) {
662 struct key_master_id *master = (void *) key->data;
663
664 hci_le_start_enc(hcon, master->ediv, master->rand,
665 key->val);
666 hcon->enc_key_size = key->pin_len;
667
668 hcon->sec_req = TRUE;
669 hcon->sec_level = authreq_to_seclevel(rp->auth_req);
670
671 return 0;
672 }
673
674 hcon->sec_req = FALSE;
675
Anderson Briglia13b48392011-06-09 18:50:42 -0300676 skb_pull(skb, sizeof(*rp));
Anderson Briglia13b48392011-06-09 18:50:42 -0300677
Vinicius Costa Gomes64532ec2011-06-09 18:50:53 -0300678 memset(&cp, 0, sizeof(cp));
Vinicius Costa Gomes10daf972011-07-07 18:59:38 -0300679 build_pairing_cmd(conn, &cp, NULL, rp->auth_req);
Anderson Briglia13b48392011-06-09 18:50:42 -0300680
Brian Gixa68668b2011-08-11 15:49:36 -0700681 hcon->preq[0] = SMP_CMD_PAIRING_REQ;
682 memcpy(&hcon->preq[1], &cp, sizeof(cp));
Anderson Brigliac8e856e2011-06-09 18:50:45 -0300683
Anderson Briglia13b48392011-06-09 18:50:42 -0300684 smp_send_cmd(conn, SMP_CMD_PAIRING_REQ, sizeof(cp), &cp);
Vinicius Costa Gomesa5474a82011-01-26 21:42:57 -0300685
Brian Gixe9ceb522011-09-22 10:46:35 -0700686 mod_timer(&hcon->smp_timer, jiffies + msecs_to_jiffies(SMP_TIMEOUT));
Vinicius Costa Gomesb19d5ce2011-06-14 13:37:41 -0300687
Vinicius Costa Gomesa5474a82011-01-26 21:42:57 -0300688 set_bit(HCI_CONN_ENCRYPT_PEND, &hcon->pend);
Vinicius Costa Gomesa5474a82011-01-26 21:42:57 -0300689
Brian Gix8d0b7d62011-10-12 15:12:42 -0700690 hci_conn_hold(hcon);
691
Vinicius Costa Gomes64532ec2011-06-09 18:50:53 -0300692 return 0;
Anderson Briglia13b48392011-06-09 18:50:42 -0300693}
694
Anderson Briglia133e14c2011-06-09 18:50:40 -0300695int smp_conn_security(struct l2cap_conn *conn, __u8 sec_level)
696{
Vinicius Costa Gomes09fabbc2011-06-09 18:50:43 -0300697 struct hci_conn *hcon = conn->hcon;
Anderson Briglia133e14c2011-06-09 18:50:40 -0300698 __u8 authreq;
699
Vinicius Costa Gomes09fabbc2011-06-09 18:50:43 -0300700 BT_DBG("conn %p hcon %p level 0x%2.2x", conn, hcon, sec_level);
701
Brian Gixa68668b2011-08-11 15:49:36 -0700702 if (IS_ERR(hcon->hdev->tfm)) {
703 BT_DBG("IS_ERR");
Vinicius Costa Gomes09fabbc2011-06-09 18:50:43 -0300704 return 1;
Brian Gixa68668b2011-08-11 15:49:36 -0700705 }
Anderson Briglia133e14c2011-06-09 18:50:40 -0300706
Brian Gixa68668b2011-08-11 15:49:36 -0700707 if (test_bit(HCI_CONN_ENCRYPT_PEND, &hcon->pend)) {
708 BT_DBG("HCI_CONN_ENCRYPT_PEND");
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700709 return -EINPROGRESS;
Brian Gixa68668b2011-08-11 15:49:36 -0700710 }
Anderson Briglia133e14c2011-06-09 18:50:40 -0300711
Brian Gixa68668b2011-08-11 15:49:36 -0700712 if (sec_level == BT_SECURITY_LOW) {
713 BT_DBG("BT_SECURITY_LOW");
Anderson Briglia133e14c2011-06-09 18:50:40 -0300714 return 1;
Brian Gixa68668b2011-08-11 15:49:36 -0700715 }
Vinicius Costa Gomesa5474a82011-01-26 21:42:57 -0300716
Brian Gixa68668b2011-08-11 15:49:36 -0700717 if (hcon->sec_level > sec_level) {
718 BT_DBG("hcon->sec_level > sec_level");
Vinicius Costa Gomesa5474a82011-01-26 21:42:57 -0300719 return 1;
Brian Gixa68668b2011-08-11 15:49:36 -0700720 }
Vinicius Costa Gomesa5474a82011-01-26 21:42:57 -0300721
722 authreq = seclevel_to_authreq(sec_level);
Anderson Briglia133e14c2011-06-09 18:50:40 -0300723
Brian Gixa68668b2011-08-11 15:49:36 -0700724 BT_ERR("conn = %p, sec: %d", conn, sec_level);
725 hcon->smp_conn = conn;
726 hcon->sec_level = sec_level;
727
728 if ((hcon->link_mode & HCI_LM_MASTER) && !hcon->sec_req) {
Vinicius Costa Gomes5d873ca2011-07-07 18:59:41 -0300729 struct link_key *key;
730
731 key = hci_find_link_key_type(hcon->hdev, conn->dst,
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700732 KEY_TYPE_LTK);
Vinicius Costa Gomes5d873ca2011-07-07 18:59:41 -0300733 if (key) {
734 struct key_master_id *master = (void *) key->data;
735
736 hci_le_start_enc(hcon, master->ediv, master->rand,
737 key->val);
Vinicius Costa Gomes1fa2de32011-07-08 18:31:45 -0300738 hcon->enc_key_size = key->pin_len;
739
Brian Gixa68668b2011-08-11 15:49:36 -0700740 hcon->sec_req = TRUE;
741
Vinicius Costa Gomes5d873ca2011-07-07 18:59:41 -0300742 goto done;
743 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700744 }
745
Brian Gixa68668b2011-08-11 15:49:36 -0700746 hcon->sec_req = FALSE;
747
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700748 if (hcon->link_mode & HCI_LM_MASTER) {
749 struct smp_cmd_pairing cp;
Anderson Brigliac8e856e2011-06-09 18:50:45 -0300750
Vinicius Costa Gomes10daf972011-07-07 18:59:38 -0300751 build_pairing_cmd(conn, &cp, NULL, authreq);
Brian Gixa68668b2011-08-11 15:49:36 -0700752 hcon->preq[0] = SMP_CMD_PAIRING_REQ;
753 memcpy(&hcon->preq[1], &cp, sizeof(cp));
Anderson Brigliac8e856e2011-06-09 18:50:45 -0300754
Brian Gixe9ceb522011-09-22 10:46:35 -0700755 mod_timer(&hcon->smp_timer, jiffies +
Vinicius Costa Gomesb19d5ce2011-06-14 13:37:41 -0300756 msecs_to_jiffies(SMP_TIMEOUT));
757
Anderson Briglia133e14c2011-06-09 18:50:40 -0300758 smp_send_cmd(conn, SMP_CMD_PAIRING_REQ, sizeof(cp), &cp);
759 } else {
760 struct smp_cmd_security_req cp;
761 cp.auth_req = authreq;
762 smp_send_cmd(conn, SMP_CMD_SECURITY_REQ, sizeof(cp), &cp);
763 }
764
Vinicius Costa Gomes5d873ca2011-07-07 18:59:41 -0300765done:
Vinicius Costa Gomesa5474a82011-01-26 21:42:57 -0300766 hcon->pending_sec_level = sec_level;
767 set_bit(HCI_CONN_ENCRYPT_PEND, &hcon->pend);
768
Anderson Briglia133e14c2011-06-09 18:50:40 -0300769 return 0;
770}
771
Vinicius Costa Gomesc1d5e1d2011-07-07 18:59:34 -0300772static int smp_cmd_encrypt_info(struct l2cap_conn *conn, struct sk_buff *skb)
773{
Brian Gixa68668b2011-08-11 15:49:36 -0700774 struct hci_conn *hcon = conn->hcon;
Vinicius Costa Gomese56cede2011-07-07 18:59:39 -0300775 struct smp_cmd_encrypt_info *rp = (void *) skb->data;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700776 u8 rand[8];
777 int err;
Vinicius Costa Gomese56cede2011-07-07 18:59:39 -0300778
779 skb_pull(skb, sizeof(*rp));
780
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700781 BT_DBG("conn %p", conn);
782
783 memset(rand, 0, sizeof(rand));
784
Brian Gixa68668b2011-08-11 15:49:36 -0700785 err = hci_add_ltk(hcon->hdev, 0, conn->dst, 0, 0, 0,
786 rand, rp->ltk);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700787 if (err)
788 return SMP_UNSPECIFIED;
Vinicius Costa Gomese56cede2011-07-07 18:59:39 -0300789
Vinicius Costa Gomesc1d5e1d2011-07-07 18:59:34 -0300790 return 0;
791}
792
793static int smp_cmd_master_ident(struct l2cap_conn *conn, struct sk_buff *skb)
794{
Brian Gixa68668b2011-08-11 15:49:36 -0700795 struct hci_conn *hcon = conn->hcon;
Vinicius Costa Gomese56cede2011-07-07 18:59:39 -0300796 struct smp_cmd_master_ident *rp = (void *) skb->data;
Brian Gixa68668b2011-08-11 15:49:36 -0700797 struct smp_cmd_pairing *paircmd = (void *) &hcon->prsp[1];
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700798 struct link_key *key;
Brian Gixa68668b2011-08-11 15:49:36 -0700799 u8 *keydist;
Vinicius Costa Gomesc1d5e1d2011-07-07 18:59:34 -0300800
Vinicius Costa Gomese56cede2011-07-07 18:59:39 -0300801 skb_pull(skb, sizeof(*rp));
802
Brian Gixa68668b2011-08-11 15:49:36 -0700803 key = hci_find_link_key_type(hcon->hdev, conn->dst, KEY_TYPE_LTK);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700804 if (key == NULL)
805 return SMP_UNSPECIFIED;
806
Brian Gixa68668b2011-08-11 15:49:36 -0700807 if (hcon->out)
808 keydist = &paircmd->resp_key_dist;
809 else
810 keydist = &paircmd->init_key_dist;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700811
Brian Gixa68668b2011-08-11 15:49:36 -0700812 BT_DBG("keydist 0x%x", *keydist);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700813
Brian Gixa68668b2011-08-11 15:49:36 -0700814 hci_add_ltk(hcon->hdev, 1, conn->dst, hcon->smp_key_size,
815 hcon->auth, rp->ediv, rp->rand, key->val);
Vinicius Costa Gomesc1d5e1d2011-07-07 18:59:34 -0300816
Brian Gixa68668b2011-08-11 15:49:36 -0700817 *keydist &= ~SMP_DIST_ENC_KEY;
818 if (hcon->out) {
819 if (!(*keydist))
820 smp_distribute_keys(conn, 1);
821 }
Vinicius Costa Gomesc1d5e1d2011-07-07 18:59:34 -0300822
823 return 0;
824}
825
Anderson Briglia133e14c2011-06-09 18:50:40 -0300826int smp_sig_channel(struct l2cap_conn *conn, struct sk_buff *skb)
827{
Brian Gixa68668b2011-08-11 15:49:36 -0700828 struct hci_conn *hcon = conn->hcon;
Anderson Briglia133e14c2011-06-09 18:50:40 -0300829 __u8 code = skb->data[0];
830 __u8 reason;
831 int err = 0;
832
Brian Gixa68668b2011-08-11 15:49:36 -0700833 if (IS_ERR(hcon->hdev->tfm)) {
834 err = PTR_ERR(hcon->hdev->tfm);
Vinicius Costa Gomes09fabbc2011-06-09 18:50:43 -0300835 reason = SMP_PAIRING_NOTSUPP;
Brian Gixa68668b2011-08-11 15:49:36 -0700836 BT_ERR("SMP_PAIRING_NOTSUPP %p", hcon->hdev->tfm);
Vinicius Costa Gomes09fabbc2011-06-09 18:50:43 -0300837 goto done;
838 }
839
Brian Gixa68668b2011-08-11 15:49:36 -0700840 hcon->smp_conn = conn;
Anderson Briglia133e14c2011-06-09 18:50:40 -0300841 skb_pull(skb, sizeof(code));
842
843 switch (code) {
844 case SMP_CMD_PAIRING_REQ:
Vinicius Costa Gomes64532ec2011-06-09 18:50:53 -0300845 reason = smp_cmd_pairing_req(conn, skb);
Anderson Briglia133e14c2011-06-09 18:50:40 -0300846 break;
847
848 case SMP_CMD_PAIRING_FAIL:
Vinicius Costa Gomes64532ec2011-06-09 18:50:53 -0300849 reason = 0;
850 err = -EPERM;
Brian Gixe9ceb522011-09-22 10:46:35 -0700851 del_timer(&hcon->smp_timer);
Brian Gix8d0b7d62011-10-12 15:12:42 -0700852 clear_bit(HCI_CONN_ENCRYPT_PEND, &hcon->pend);
Brian Gix58ba0772011-09-23 13:40:16 -0700853 mgmt_auth_failed(hcon->hdev->id, conn->dst, skb->data[1]);
Brian Gix6d5fb8a2011-09-09 14:53:04 -0700854 hci_conn_put(hcon);
Anderson Briglia133e14c2011-06-09 18:50:40 -0300855 break;
856
857 case SMP_CMD_PAIRING_RSP:
Vinicius Costa Gomes64532ec2011-06-09 18:50:53 -0300858 reason = smp_cmd_pairing_rsp(conn, skb);
Anderson Briglia13b48392011-06-09 18:50:42 -0300859 break;
860
861 case SMP_CMD_SECURITY_REQ:
Vinicius Costa Gomes64532ec2011-06-09 18:50:53 -0300862 reason = smp_cmd_security_req(conn, skb);
Anderson Briglia13b48392011-06-09 18:50:42 -0300863 break;
864
Anderson Briglia133e14c2011-06-09 18:50:40 -0300865 case SMP_CMD_PAIRING_CONFIRM:
Vinicius Costa Gomes64532ec2011-06-09 18:50:53 -0300866 reason = smp_cmd_pairing_confirm(conn, skb);
Anderson Briglia13b48392011-06-09 18:50:42 -0300867 break;
868
Anderson Briglia133e14c2011-06-09 18:50:40 -0300869 case SMP_CMD_PAIRING_RANDOM:
Vinicius Costa Gomes64532ec2011-06-09 18:50:53 -0300870 reason = smp_cmd_pairing_random(conn, skb);
Anderson Briglia13b48392011-06-09 18:50:42 -0300871 break;
872
Anderson Briglia133e14c2011-06-09 18:50:40 -0300873 case SMP_CMD_ENCRYPT_INFO:
Vinicius Costa Gomesc1d5e1d2011-07-07 18:59:34 -0300874 reason = smp_cmd_encrypt_info(conn, skb);
875 break;
876
Anderson Briglia133e14c2011-06-09 18:50:40 -0300877 case SMP_CMD_MASTER_IDENT:
Vinicius Costa Gomesc1d5e1d2011-07-07 18:59:34 -0300878 reason = smp_cmd_master_ident(conn, skb);
879 break;
880
Anderson Briglia133e14c2011-06-09 18:50:40 -0300881 case SMP_CMD_IDENT_INFO:
882 case SMP_CMD_IDENT_ADDR_INFO:
883 case SMP_CMD_SIGN_INFO:
Vinicius Costa Gomesc1d5e1d2011-07-07 18:59:34 -0300884 /* Just ignored */
885 reason = 0;
886 break;
887
Anderson Briglia133e14c2011-06-09 18:50:40 -0300888 default:
889 BT_DBG("Unknown command code 0x%2.2x", code);
890
891 reason = SMP_CMD_NOTSUPP;
Vinicius Costa Gomes09fabbc2011-06-09 18:50:43 -0300892 err = -EOPNOTSUPP;
893 goto done;
894 }
895
896done:
Brian Gixa68668b2011-08-11 15:49:36 -0700897 if (reason) {
898 BT_ERR("SMP_CMD_PAIRING_FAIL: %d", reason);
Anderson Briglia133e14c2011-06-09 18:50:40 -0300899 smp_send_cmd(conn, SMP_CMD_PAIRING_FAIL, sizeof(reason),
900 &reason);
Brian Gixe9ceb522011-09-22 10:46:35 -0700901 del_timer(&hcon->smp_timer);
Brian Gix8d0b7d62011-10-12 15:12:42 -0700902 clear_bit(HCI_CONN_ENCRYPT_PEND, &hcon->pend);
Brian Gix58ba0772011-09-23 13:40:16 -0700903 mgmt_auth_failed(hcon->hdev->id, conn->dst, reason);
Brian Gix6d5fb8a2011-09-09 14:53:04 -0700904 hci_conn_put(hcon);
Brian Gixa68668b2011-08-11 15:49:36 -0700905 }
Anderson Briglia133e14c2011-06-09 18:50:40 -0300906
907 kfree_skb(skb);
908 return err;
909}
Vinicius Costa Gomesc1d5e1d2011-07-07 18:59:34 -0300910
Brian Gixa68668b2011-08-11 15:49:36 -0700911static int smp_distribute_keys(struct l2cap_conn *conn, __u8 force)
Vinicius Costa Gomesc1d5e1d2011-07-07 18:59:34 -0300912{
Brian Gixa68668b2011-08-11 15:49:36 -0700913 struct hci_conn *hcon = conn->hcon;
Vinicius Costa Gomesc1d5e1d2011-07-07 18:59:34 -0300914 struct smp_cmd_pairing *req, *rsp;
915 __u8 *keydist;
916
917 BT_DBG("conn %p force %d", conn, force);
918
Brian Gixa68668b2011-08-11 15:49:36 -0700919 if (IS_ERR(hcon->hdev->tfm))
920 return PTR_ERR(hcon->hdev->tfm);
Vinicius Costa Gomesc1d5e1d2011-07-07 18:59:34 -0300921
Brian Gixa68668b2011-08-11 15:49:36 -0700922 rsp = (void *) &hcon->prsp[1];
Vinicius Costa Gomesc1d5e1d2011-07-07 18:59:34 -0300923
924 /* The responder sends its keys first */
Brian Gixa68668b2011-08-11 15:49:36 -0700925 if (!force && hcon->out && (rsp->resp_key_dist & 0x07))
Vinicius Costa Gomesc1d5e1d2011-07-07 18:59:34 -0300926 return 0;
927
Brian Gixa68668b2011-08-11 15:49:36 -0700928 req = (void *) &hcon->preq[1];
Vinicius Costa Gomesc1d5e1d2011-07-07 18:59:34 -0300929
Brian Gixa68668b2011-08-11 15:49:36 -0700930 if (hcon->out) {
Vinicius Costa Gomesc1d5e1d2011-07-07 18:59:34 -0300931 keydist = &rsp->init_key_dist;
932 *keydist &= req->init_key_dist;
933 } else {
934 keydist = &rsp->resp_key_dist;
935 *keydist &= req->resp_key_dist;
936 }
937
938
939 BT_DBG("keydist 0x%x", *keydist);
940
941 if (*keydist & SMP_DIST_ENC_KEY) {
942 struct smp_cmd_encrypt_info enc;
943 struct smp_cmd_master_ident ident;
944 __le16 ediv;
945
946 get_random_bytes(enc.ltk, sizeof(enc.ltk));
947 get_random_bytes(&ediv, sizeof(ediv));
948 get_random_bytes(ident.rand, sizeof(ident.rand));
949
950 smp_send_cmd(conn, SMP_CMD_ENCRYPT_INFO, sizeof(enc), &enc);
951
Brian Gixa68668b2011-08-11 15:49:36 -0700952 hci_add_ltk(hcon->hdev, 1, conn->dst, hcon->smp_key_size,
953 hcon->auth, ediv, ident.rand, enc.ltk);
Vinicius Costa Gomese56cede2011-07-07 18:59:39 -0300954
Vinicius Costa Gomesc1d5e1d2011-07-07 18:59:34 -0300955 ident.ediv = cpu_to_le16(ediv);
956
957 smp_send_cmd(conn, SMP_CMD_MASTER_IDENT, sizeof(ident), &ident);
958
959 *keydist &= ~SMP_DIST_ENC_KEY;
960 }
961
962 if (*keydist & SMP_DIST_ID_KEY) {
963 struct smp_cmd_ident_addr_info addrinfo;
964 struct smp_cmd_ident_info idinfo;
965
966 /* Send a dummy key */
967 get_random_bytes(idinfo.irk, sizeof(idinfo.irk));
968
969 smp_send_cmd(conn, SMP_CMD_IDENT_INFO, sizeof(idinfo), &idinfo);
970
971 /* Just public address */
972 memset(&addrinfo, 0, sizeof(addrinfo));
973 bacpy(&addrinfo.bdaddr, conn->src);
974
975 smp_send_cmd(conn, SMP_CMD_IDENT_ADDR_INFO, sizeof(addrinfo),
976 &addrinfo);
977
978 *keydist &= ~SMP_DIST_ID_KEY;
979 }
980
981 if (*keydist & SMP_DIST_SIGN) {
982 struct smp_cmd_sign_info sign;
983
984 /* Send a dummy key */
985 get_random_bytes(sign.csrk, sizeof(sign.csrk));
986
987 smp_send_cmd(conn, SMP_CMD_SIGN_INFO, sizeof(sign), &sign);
988
989 *keydist &= ~SMP_DIST_SIGN;
990 }
991
Brian Gix6d5fb8a2011-09-09 14:53:04 -0700992 if (hcon->out || rsp->resp_key_dist) {
Brian Gixe57c1672011-09-13 12:34:59 -0700993 if (hcon->disconn_cfm_cb)
994 hcon->disconn_cfm_cb(hcon, 0);
Brian Gixe9ceb522011-09-22 10:46:35 -0700995
996 del_timer(&hcon->smp_timer);
Brian Gix8d0b7d62011-10-12 15:12:42 -0700997 clear_bit(HCI_CONN_ENCRYPT_PEND, &hcon->pend);
Brian Gix58ba0772011-09-23 13:40:16 -0700998 mgmt_auth_failed(hcon->hdev->id, conn->dst, SMP_UNSPECIFIED);
Brian Gix6d5fb8a2011-09-09 14:53:04 -0700999 hci_conn_put(hcon);
1000 }
Brian Gixa68668b2011-08-11 15:49:36 -07001001
1002 return 0;
1003}
1004
1005int smp_link_encrypt_cmplt(struct l2cap_conn *conn, u8 status, u8 encrypt)
1006{
1007 struct hci_conn *hcon = conn->hcon;
1008
1009 BT_DBG("smp: %d %d %d", status, encrypt, hcon->sec_req);
1010
Brian Gix8d0b7d62011-10-12 15:12:42 -07001011 clear_bit(HCI_CONN_ENCRYPT_PEND, &hcon->pend);
1012
Brian Gixa68668b2011-08-11 15:49:36 -07001013 if (!status && encrypt && !hcon->sec_req)
1014 smp_distribute_keys(conn, 0);
1015
1016 /* Fall back to Pairing request if failed a Link Security request */
1017 else if (hcon->sec_req && (status || !encrypt))
1018 smp_conn_security(conn, hcon->sec_level);
1019
Brian Gix8d0b7d62011-10-12 15:12:42 -07001020 else
1021 hci_conn_put(hcon);
1022
Vinicius Costa Gomesc1d5e1d2011-07-07 18:59:34 -03001023 return 0;
1024}
Brian Gixe9ceb522011-09-22 10:46:35 -07001025
1026void smp_timeout(unsigned long arg)
1027{
1028 struct l2cap_conn *conn = (void *) arg;
1029 u8 reason = SMP_UNSPECIFIED;
1030
1031 BT_DBG("%p", conn);
1032
1033 smp_send_cmd(conn, SMP_CMD_PAIRING_FAIL, sizeof(reason), &reason);
Brian Gix8d0b7d62011-10-12 15:12:42 -07001034 clear_bit(HCI_CONN_ENCRYPT_PEND, &conn->hcon->pend);
Brian Gix58ba0772011-09-23 13:40:16 -07001035 mgmt_auth_failed(conn->hcon->hdev->id, conn->dst, SMP_UNSPECIFIED);
Brian Gixe9ceb522011-09-22 10:46:35 -07001036 hci_conn_put(conn->hcon);
1037}