blob: e7251480f16737b5937f737ca448c9aaa6af942f [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 Gixcf956772011-10-20 15:18:51 -0700640 hci_add_ltk(conn->hcon->hdev, 0, conn->dst, hcon->dst_type,
641 hcon->smp_key_size, 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
Brian Gix372257b2011-10-25 09:06:30 -0700647static int smp_encrypt_link(struct hci_conn *hcon, struct link_key *key)
648{
649 struct key_master_id *master;
650 u8 zerobuf[8];
651
652 if (!hcon || !key || !key->data)
653 return -EINVAL;
654
655 memset(zerobuf, 0, sizeof(zerobuf));
656
657 master = (void *) key->data;
658
659 if (!master->ediv && !memcmp(master->rand, zerobuf, sizeof(zerobuf)))
660 return -EINVAL;
661
662 hcon->enc_key_size = key->pin_len;
663 hcon->sec_req = TRUE;
664 hci_le_start_enc(hcon, master->ediv, master->rand, key->val);
665
666 return 0;
667}
668
Vinicius Costa Gomes64532ec2011-06-09 18:50:53 -0300669static u8 smp_cmd_security_req(struct l2cap_conn *conn, struct sk_buff *skb)
Anderson Briglia13b48392011-06-09 18:50:42 -0300670{
Brian Gixa68668b2011-08-11 15:49:36 -0700671 struct hci_conn *hcon = conn->hcon;
Anderson Briglia13b48392011-06-09 18:50:42 -0300672 struct smp_cmd_security_req *rp = (void *) skb->data;
673 struct smp_cmd_pairing cp;
Brian Gixa68668b2011-08-11 15:49:36 -0700674 struct link_key *key;
Anderson Briglia13b48392011-06-09 18:50:42 -0300675
676 BT_DBG("conn %p", conn);
677
Vinicius Costa Gomesa5474a82011-01-26 21:42:57 -0300678 if (test_bit(HCI_CONN_ENCRYPT_PEND, &hcon->pend))
Vinicius Costa Gomes64532ec2011-06-09 18:50:53 -0300679 return 0;
Vinicius Costa Gomesa5474a82011-01-26 21:42:57 -0300680
Brian Gixa68668b2011-08-11 15:49:36 -0700681 key = hci_find_link_key_type(hcon->hdev, conn->dst, KEY_TYPE_LTK);
682 if (key && ((key->auth & SMP_AUTH_MITM) ||
683 !(rp->auth_req & SMP_AUTH_MITM))) {
Brian Gixa68668b2011-08-11 15:49:36 -0700684
Brian Gix372257b2011-10-25 09:06:30 -0700685 if (smp_encrypt_link(hcon, key) < 0)
686 goto invalid_key;
Brian Gixa68668b2011-08-11 15:49:36 -0700687
Brian Gix372257b2011-10-25 09:06:30 -0700688 hcon->sec_level = authreq_to_seclevel(key->auth);
689
690 if (!(hcon->link_mode & HCI_LM_ENCRYPT))
691 hci_conn_hold(hcon);
Brian Gixa68668b2011-08-11 15:49:36 -0700692
693 return 0;
694 }
695
Brian Gix372257b2011-10-25 09:06:30 -0700696invalid_key:
Brian Gixa68668b2011-08-11 15:49:36 -0700697 hcon->sec_req = FALSE;
698
Anderson Briglia13b48392011-06-09 18:50:42 -0300699 skb_pull(skb, sizeof(*rp));
Anderson Briglia13b48392011-06-09 18:50:42 -0300700
Vinicius Costa Gomes64532ec2011-06-09 18:50:53 -0300701 memset(&cp, 0, sizeof(cp));
Vinicius Costa Gomes10daf972011-07-07 18:59:38 -0300702 build_pairing_cmd(conn, &cp, NULL, rp->auth_req);
Anderson Briglia13b48392011-06-09 18:50:42 -0300703
Brian Gixa68668b2011-08-11 15:49:36 -0700704 hcon->preq[0] = SMP_CMD_PAIRING_REQ;
705 memcpy(&hcon->preq[1], &cp, sizeof(cp));
Anderson Brigliac8e856e2011-06-09 18:50:45 -0300706
Anderson Briglia13b48392011-06-09 18:50:42 -0300707 smp_send_cmd(conn, SMP_CMD_PAIRING_REQ, sizeof(cp), &cp);
Vinicius Costa Gomesa5474a82011-01-26 21:42:57 -0300708
Brian Gixe9ceb522011-09-22 10:46:35 -0700709 mod_timer(&hcon->smp_timer, jiffies + msecs_to_jiffies(SMP_TIMEOUT));
Vinicius Costa Gomesb19d5ce2011-06-14 13:37:41 -0300710
Vinicius Costa Gomesa5474a82011-01-26 21:42:57 -0300711 set_bit(HCI_CONN_ENCRYPT_PEND, &hcon->pend);
Vinicius Costa Gomesa5474a82011-01-26 21:42:57 -0300712
Brian Gix8d0b7d62011-10-12 15:12:42 -0700713 hci_conn_hold(hcon);
714
Vinicius Costa Gomes64532ec2011-06-09 18:50:53 -0300715 return 0;
Anderson Briglia13b48392011-06-09 18:50:42 -0300716}
717
Anderson Briglia133e14c2011-06-09 18:50:40 -0300718int smp_conn_security(struct l2cap_conn *conn, __u8 sec_level)
719{
Vinicius Costa Gomes09fabbc2011-06-09 18:50:43 -0300720 struct hci_conn *hcon = conn->hcon;
Anderson Briglia133e14c2011-06-09 18:50:40 -0300721 __u8 authreq;
722
Vinicius Costa Gomes09fabbc2011-06-09 18:50:43 -0300723 BT_DBG("conn %p hcon %p level 0x%2.2x", conn, hcon, sec_level);
724
Brian Gixa68668b2011-08-11 15:49:36 -0700725 if (IS_ERR(hcon->hdev->tfm)) {
726 BT_DBG("IS_ERR");
Vinicius Costa Gomes09fabbc2011-06-09 18:50:43 -0300727 return 1;
Brian Gixa68668b2011-08-11 15:49:36 -0700728 }
Anderson Briglia133e14c2011-06-09 18:50:40 -0300729
Brian Gixa68668b2011-08-11 15:49:36 -0700730 if (test_bit(HCI_CONN_ENCRYPT_PEND, &hcon->pend)) {
731 BT_DBG("HCI_CONN_ENCRYPT_PEND");
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700732 return -EINPROGRESS;
Brian Gixa68668b2011-08-11 15:49:36 -0700733 }
Anderson Briglia133e14c2011-06-09 18:50:40 -0300734
Brian Gixa68668b2011-08-11 15:49:36 -0700735 if (sec_level == BT_SECURITY_LOW) {
736 BT_DBG("BT_SECURITY_LOW");
Anderson Briglia133e14c2011-06-09 18:50:40 -0300737 return 1;
Brian Gixa68668b2011-08-11 15:49:36 -0700738 }
Vinicius Costa Gomesa5474a82011-01-26 21:42:57 -0300739
Brian Gixa68668b2011-08-11 15:49:36 -0700740 if (hcon->sec_level > sec_level) {
741 BT_DBG("hcon->sec_level > sec_level");
Vinicius Costa Gomesa5474a82011-01-26 21:42:57 -0300742 return 1;
Brian Gixa68668b2011-08-11 15:49:36 -0700743 }
Vinicius Costa Gomesa5474a82011-01-26 21:42:57 -0300744
745 authreq = seclevel_to_authreq(sec_level);
Anderson Briglia133e14c2011-06-09 18:50:40 -0300746
Brian Gixa68668b2011-08-11 15:49:36 -0700747 BT_ERR("conn = %p, sec: %d", conn, sec_level);
748 hcon->smp_conn = conn;
749 hcon->sec_level = sec_level;
750
751 if ((hcon->link_mode & HCI_LM_MASTER) && !hcon->sec_req) {
Vinicius Costa Gomes5d873ca2011-07-07 18:59:41 -0300752 struct link_key *key;
753
754 key = hci_find_link_key_type(hcon->hdev, conn->dst,
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700755 KEY_TYPE_LTK);
Vinicius Costa Gomes5d873ca2011-07-07 18:59:41 -0300756
Brian Gix372257b2011-10-25 09:06:30 -0700757 if (smp_encrypt_link(hcon, key) == 0)
Vinicius Costa Gomes5d873ca2011-07-07 18:59:41 -0300758 goto done;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700759 }
760
Brian Gixa68668b2011-08-11 15:49:36 -0700761 hcon->sec_req = FALSE;
762
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700763 if (hcon->link_mode & HCI_LM_MASTER) {
764 struct smp_cmd_pairing cp;
Anderson Brigliac8e856e2011-06-09 18:50:45 -0300765
Vinicius Costa Gomes10daf972011-07-07 18:59:38 -0300766 build_pairing_cmd(conn, &cp, NULL, authreq);
Brian Gixa68668b2011-08-11 15:49:36 -0700767 hcon->preq[0] = SMP_CMD_PAIRING_REQ;
768 memcpy(&hcon->preq[1], &cp, sizeof(cp));
Anderson Brigliac8e856e2011-06-09 18:50:45 -0300769
Brian Gixe9ceb522011-09-22 10:46:35 -0700770 mod_timer(&hcon->smp_timer, jiffies +
Vinicius Costa Gomesb19d5ce2011-06-14 13:37:41 -0300771 msecs_to_jiffies(SMP_TIMEOUT));
772
Anderson Briglia133e14c2011-06-09 18:50:40 -0300773 smp_send_cmd(conn, SMP_CMD_PAIRING_REQ, sizeof(cp), &cp);
774 } else {
775 struct smp_cmd_security_req cp;
776 cp.auth_req = authreq;
777 smp_send_cmd(conn, SMP_CMD_SECURITY_REQ, sizeof(cp), &cp);
778 }
779
Vinicius Costa Gomes5d873ca2011-07-07 18:59:41 -0300780done:
Vinicius Costa Gomesa5474a82011-01-26 21:42:57 -0300781 hcon->pending_sec_level = sec_level;
782 set_bit(HCI_CONN_ENCRYPT_PEND, &hcon->pend);
783
Anderson Briglia133e14c2011-06-09 18:50:40 -0300784 return 0;
785}
786
Vinicius Costa Gomesc1d5e1d2011-07-07 18:59:34 -0300787static int smp_cmd_encrypt_info(struct l2cap_conn *conn, struct sk_buff *skb)
788{
Brian Gixa68668b2011-08-11 15:49:36 -0700789 struct hci_conn *hcon = conn->hcon;
Vinicius Costa Gomese56cede2011-07-07 18:59:39 -0300790 struct smp_cmd_encrypt_info *rp = (void *) skb->data;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700791 u8 rand[8];
792 int err;
Vinicius Costa Gomese56cede2011-07-07 18:59:39 -0300793
794 skb_pull(skb, sizeof(*rp));
795
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700796 BT_DBG("conn %p", conn);
797
798 memset(rand, 0, sizeof(rand));
799
Brian Gixcf956772011-10-20 15:18:51 -0700800 err = hci_add_ltk(hcon->hdev, 0, conn->dst, hcon->dst_type,
801 0, 0, 0, rand, rp->ltk);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700802 if (err)
803 return SMP_UNSPECIFIED;
Vinicius Costa Gomese56cede2011-07-07 18:59:39 -0300804
Vinicius Costa Gomesc1d5e1d2011-07-07 18:59:34 -0300805 return 0;
806}
807
808static int smp_cmd_master_ident(struct l2cap_conn *conn, struct sk_buff *skb)
809{
Brian Gixa68668b2011-08-11 15:49:36 -0700810 struct hci_conn *hcon = conn->hcon;
Vinicius Costa Gomese56cede2011-07-07 18:59:39 -0300811 struct smp_cmd_master_ident *rp = (void *) skb->data;
Brian Gixa68668b2011-08-11 15:49:36 -0700812 struct smp_cmd_pairing *paircmd = (void *) &hcon->prsp[1];
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700813 struct link_key *key;
Brian Gixa68668b2011-08-11 15:49:36 -0700814 u8 *keydist;
Vinicius Costa Gomesc1d5e1d2011-07-07 18:59:34 -0300815
Vinicius Costa Gomese56cede2011-07-07 18:59:39 -0300816 skb_pull(skb, sizeof(*rp));
817
Brian Gixa68668b2011-08-11 15:49:36 -0700818 key = hci_find_link_key_type(hcon->hdev, conn->dst, KEY_TYPE_LTK);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700819 if (key == NULL)
820 return SMP_UNSPECIFIED;
821
Brian Gixa68668b2011-08-11 15:49:36 -0700822 if (hcon->out)
823 keydist = &paircmd->resp_key_dist;
824 else
825 keydist = &paircmd->init_key_dist;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700826
Brian Gixa68668b2011-08-11 15:49:36 -0700827 BT_DBG("keydist 0x%x", *keydist);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700828
Brian Gixcf956772011-10-20 15:18:51 -0700829 hci_add_ltk(hcon->hdev, 1, conn->dst, hcon->dst_type,
830 hcon->smp_key_size, hcon->auth, rp->ediv,
831 rp->rand, key->val);
Vinicius Costa Gomesc1d5e1d2011-07-07 18:59:34 -0300832
Brian Gixa68668b2011-08-11 15:49:36 -0700833 *keydist &= ~SMP_DIST_ENC_KEY;
834 if (hcon->out) {
835 if (!(*keydist))
836 smp_distribute_keys(conn, 1);
837 }
Vinicius Costa Gomesc1d5e1d2011-07-07 18:59:34 -0300838
839 return 0;
840}
841
Anderson Briglia133e14c2011-06-09 18:50:40 -0300842int smp_sig_channel(struct l2cap_conn *conn, struct sk_buff *skb)
843{
Brian Gixa68668b2011-08-11 15:49:36 -0700844 struct hci_conn *hcon = conn->hcon;
Anderson Briglia133e14c2011-06-09 18:50:40 -0300845 __u8 code = skb->data[0];
846 __u8 reason;
847 int err = 0;
848
Brian Gixa68668b2011-08-11 15:49:36 -0700849 if (IS_ERR(hcon->hdev->tfm)) {
850 err = PTR_ERR(hcon->hdev->tfm);
Vinicius Costa Gomes09fabbc2011-06-09 18:50:43 -0300851 reason = SMP_PAIRING_NOTSUPP;
Brian Gixa68668b2011-08-11 15:49:36 -0700852 BT_ERR("SMP_PAIRING_NOTSUPP %p", hcon->hdev->tfm);
Vinicius Costa Gomes09fabbc2011-06-09 18:50:43 -0300853 goto done;
854 }
855
Brian Gixa68668b2011-08-11 15:49:36 -0700856 hcon->smp_conn = conn;
Anderson Briglia133e14c2011-06-09 18:50:40 -0300857 skb_pull(skb, sizeof(code));
858
859 switch (code) {
860 case SMP_CMD_PAIRING_REQ:
Vinicius Costa Gomes64532ec2011-06-09 18:50:53 -0300861 reason = smp_cmd_pairing_req(conn, skb);
Anderson Briglia133e14c2011-06-09 18:50:40 -0300862 break;
863
864 case SMP_CMD_PAIRING_FAIL:
Vinicius Costa Gomes64532ec2011-06-09 18:50:53 -0300865 reason = 0;
866 err = -EPERM;
Brian Gixe9ceb522011-09-22 10:46:35 -0700867 del_timer(&hcon->smp_timer);
Brian Gix8d0b7d62011-10-12 15:12:42 -0700868 clear_bit(HCI_CONN_ENCRYPT_PEND, &hcon->pend);
Brian Gix570efc92011-10-13 15:59:51 -0700869 mgmt_auth_failed(hcon->hdev->id, conn->dst, skb->data[0]);
Brian Gix6d5fb8a2011-09-09 14:53:04 -0700870 hci_conn_put(hcon);
Anderson Briglia133e14c2011-06-09 18:50:40 -0300871 break;
872
873 case SMP_CMD_PAIRING_RSP:
Vinicius Costa Gomes64532ec2011-06-09 18:50:53 -0300874 reason = smp_cmd_pairing_rsp(conn, skb);
Anderson Briglia13b48392011-06-09 18:50:42 -0300875 break;
876
877 case SMP_CMD_SECURITY_REQ:
Vinicius Costa Gomes64532ec2011-06-09 18:50:53 -0300878 reason = smp_cmd_security_req(conn, skb);
Anderson Briglia13b48392011-06-09 18:50:42 -0300879 break;
880
Anderson Briglia133e14c2011-06-09 18:50:40 -0300881 case SMP_CMD_PAIRING_CONFIRM:
Vinicius Costa Gomes64532ec2011-06-09 18:50:53 -0300882 reason = smp_cmd_pairing_confirm(conn, skb);
Anderson Briglia13b48392011-06-09 18:50:42 -0300883 break;
884
Anderson Briglia133e14c2011-06-09 18:50:40 -0300885 case SMP_CMD_PAIRING_RANDOM:
Vinicius Costa Gomes64532ec2011-06-09 18:50:53 -0300886 reason = smp_cmd_pairing_random(conn, skb);
Anderson Briglia13b48392011-06-09 18:50:42 -0300887 break;
888
Anderson Briglia133e14c2011-06-09 18:50:40 -0300889 case SMP_CMD_ENCRYPT_INFO:
Vinicius Costa Gomesc1d5e1d2011-07-07 18:59:34 -0300890 reason = smp_cmd_encrypt_info(conn, skb);
891 break;
892
Anderson Briglia133e14c2011-06-09 18:50:40 -0300893 case SMP_CMD_MASTER_IDENT:
Vinicius Costa Gomesc1d5e1d2011-07-07 18:59:34 -0300894 reason = smp_cmd_master_ident(conn, skb);
895 break;
896
Anderson Briglia133e14c2011-06-09 18:50:40 -0300897 case SMP_CMD_IDENT_INFO:
898 case SMP_CMD_IDENT_ADDR_INFO:
899 case SMP_CMD_SIGN_INFO:
Vinicius Costa Gomesc1d5e1d2011-07-07 18:59:34 -0300900 /* Just ignored */
901 reason = 0;
902 break;
903
Anderson Briglia133e14c2011-06-09 18:50:40 -0300904 default:
905 BT_DBG("Unknown command code 0x%2.2x", code);
906
907 reason = SMP_CMD_NOTSUPP;
Vinicius Costa Gomes09fabbc2011-06-09 18:50:43 -0300908 err = -EOPNOTSUPP;
909 goto done;
910 }
911
912done:
Brian Gixa68668b2011-08-11 15:49:36 -0700913 if (reason) {
914 BT_ERR("SMP_CMD_PAIRING_FAIL: %d", reason);
Anderson Briglia133e14c2011-06-09 18:50:40 -0300915 smp_send_cmd(conn, SMP_CMD_PAIRING_FAIL, sizeof(reason),
916 &reason);
Brian Gixe9ceb522011-09-22 10:46:35 -0700917 del_timer(&hcon->smp_timer);
Brian Gix8d0b7d62011-10-12 15:12:42 -0700918 clear_bit(HCI_CONN_ENCRYPT_PEND, &hcon->pend);
Brian Gix58ba0772011-09-23 13:40:16 -0700919 mgmt_auth_failed(hcon->hdev->id, conn->dst, reason);
Brian Gix6d5fb8a2011-09-09 14:53:04 -0700920 hci_conn_put(hcon);
Brian Gixa68668b2011-08-11 15:49:36 -0700921 }
Anderson Briglia133e14c2011-06-09 18:50:40 -0300922
923 kfree_skb(skb);
924 return err;
925}
Vinicius Costa Gomesc1d5e1d2011-07-07 18:59:34 -0300926
Brian Gixa68668b2011-08-11 15:49:36 -0700927static int smp_distribute_keys(struct l2cap_conn *conn, __u8 force)
Vinicius Costa Gomesc1d5e1d2011-07-07 18:59:34 -0300928{
Brian Gixa68668b2011-08-11 15:49:36 -0700929 struct hci_conn *hcon = conn->hcon;
Vinicius Costa Gomesc1d5e1d2011-07-07 18:59:34 -0300930 struct smp_cmd_pairing *req, *rsp;
931 __u8 *keydist;
932
933 BT_DBG("conn %p force %d", conn, force);
934
Brian Gixa68668b2011-08-11 15:49:36 -0700935 if (IS_ERR(hcon->hdev->tfm))
936 return PTR_ERR(hcon->hdev->tfm);
Vinicius Costa Gomesc1d5e1d2011-07-07 18:59:34 -0300937
Brian Gixa68668b2011-08-11 15:49:36 -0700938 rsp = (void *) &hcon->prsp[1];
Vinicius Costa Gomesc1d5e1d2011-07-07 18:59:34 -0300939
940 /* The responder sends its keys first */
Brian Gixa68668b2011-08-11 15:49:36 -0700941 if (!force && hcon->out && (rsp->resp_key_dist & 0x07))
Vinicius Costa Gomesc1d5e1d2011-07-07 18:59:34 -0300942 return 0;
943
Brian Gixa68668b2011-08-11 15:49:36 -0700944 req = (void *) &hcon->preq[1];
Vinicius Costa Gomesc1d5e1d2011-07-07 18:59:34 -0300945
Brian Gixa68668b2011-08-11 15:49:36 -0700946 if (hcon->out) {
Vinicius Costa Gomesc1d5e1d2011-07-07 18:59:34 -0300947 keydist = &rsp->init_key_dist;
948 *keydist &= req->init_key_dist;
949 } else {
950 keydist = &rsp->resp_key_dist;
951 *keydist &= req->resp_key_dist;
952 }
953
954
955 BT_DBG("keydist 0x%x", *keydist);
956
957 if (*keydist & SMP_DIST_ENC_KEY) {
958 struct smp_cmd_encrypt_info enc;
959 struct smp_cmd_master_ident ident;
960 __le16 ediv;
961
962 get_random_bytes(enc.ltk, sizeof(enc.ltk));
963 get_random_bytes(&ediv, sizeof(ediv));
964 get_random_bytes(ident.rand, sizeof(ident.rand));
965
966 smp_send_cmd(conn, SMP_CMD_ENCRYPT_INFO, sizeof(enc), &enc);
967
Brian Gixcf956772011-10-20 15:18:51 -0700968 hci_add_ltk(hcon->hdev, 1, conn->dst, hcon->dst_type,
969 hcon->smp_key_size, hcon->auth, ediv,
970 ident.rand, enc.ltk);
Vinicius Costa Gomese56cede2011-07-07 18:59:39 -0300971
Vinicius Costa Gomesc1d5e1d2011-07-07 18:59:34 -0300972 ident.ediv = cpu_to_le16(ediv);
973
974 smp_send_cmd(conn, SMP_CMD_MASTER_IDENT, sizeof(ident), &ident);
975
976 *keydist &= ~SMP_DIST_ENC_KEY;
977 }
978
979 if (*keydist & SMP_DIST_ID_KEY) {
980 struct smp_cmd_ident_addr_info addrinfo;
981 struct smp_cmd_ident_info idinfo;
982
983 /* Send a dummy key */
984 get_random_bytes(idinfo.irk, sizeof(idinfo.irk));
985
986 smp_send_cmd(conn, SMP_CMD_IDENT_INFO, sizeof(idinfo), &idinfo);
987
988 /* Just public address */
989 memset(&addrinfo, 0, sizeof(addrinfo));
990 bacpy(&addrinfo.bdaddr, conn->src);
991
992 smp_send_cmd(conn, SMP_CMD_IDENT_ADDR_INFO, sizeof(addrinfo),
993 &addrinfo);
994
995 *keydist &= ~SMP_DIST_ID_KEY;
996 }
997
998 if (*keydist & SMP_DIST_SIGN) {
999 struct smp_cmd_sign_info sign;
1000
1001 /* Send a dummy key */
1002 get_random_bytes(sign.csrk, sizeof(sign.csrk));
1003
1004 smp_send_cmd(conn, SMP_CMD_SIGN_INFO, sizeof(sign), &sign);
1005
1006 *keydist &= ~SMP_DIST_SIGN;
1007 }
1008
Brian Gix6d5fb8a2011-09-09 14:53:04 -07001009 if (hcon->out || rsp->resp_key_dist) {
Brian Gixe57c1672011-09-13 12:34:59 -07001010 if (hcon->disconn_cfm_cb)
1011 hcon->disconn_cfm_cb(hcon, 0);
Brian Gixe9ceb522011-09-22 10:46:35 -07001012
1013 del_timer(&hcon->smp_timer);
Brian Gix8d0b7d62011-10-12 15:12:42 -07001014 clear_bit(HCI_CONN_ENCRYPT_PEND, &hcon->pend);
Brian Gix58ba0772011-09-23 13:40:16 -07001015 mgmt_auth_failed(hcon->hdev->id, conn->dst, SMP_UNSPECIFIED);
Brian Gix6d5fb8a2011-09-09 14:53:04 -07001016 hci_conn_put(hcon);
1017 }
Brian Gixa68668b2011-08-11 15:49:36 -07001018
1019 return 0;
1020}
1021
1022int smp_link_encrypt_cmplt(struct l2cap_conn *conn, u8 status, u8 encrypt)
1023{
1024 struct hci_conn *hcon = conn->hcon;
1025
1026 BT_DBG("smp: %d %d %d", status, encrypt, hcon->sec_req);
1027
Brian Gix8d0b7d62011-10-12 15:12:42 -07001028 clear_bit(HCI_CONN_ENCRYPT_PEND, &hcon->pend);
1029
Brian Gixa68668b2011-08-11 15:49:36 -07001030 if (!status && encrypt && !hcon->sec_req)
1031 smp_distribute_keys(conn, 0);
1032
1033 /* Fall back to Pairing request if failed a Link Security request */
1034 else if (hcon->sec_req && (status || !encrypt))
1035 smp_conn_security(conn, hcon->sec_level);
1036
Brian Gix8d0b7d62011-10-12 15:12:42 -07001037 else
1038 hci_conn_put(hcon);
1039
Vinicius Costa Gomesc1d5e1d2011-07-07 18:59:34 -03001040 return 0;
1041}
Brian Gixe9ceb522011-09-22 10:46:35 -07001042
1043void smp_timeout(unsigned long arg)
1044{
1045 struct l2cap_conn *conn = (void *) arg;
1046 u8 reason = SMP_UNSPECIFIED;
1047
1048 BT_DBG("%p", conn);
1049
1050 smp_send_cmd(conn, SMP_CMD_PAIRING_FAIL, sizeof(reason), &reason);
Brian Gix8d0b7d62011-10-12 15:12:42 -07001051 clear_bit(HCI_CONN_ENCRYPT_PEND, &conn->hcon->pend);
Brian Gix58ba0772011-09-23 13:40:16 -07001052 mgmt_auth_failed(conn->hcon->hdev->id, conn->dst, SMP_UNSPECIFIED);
Brian Gixe9ceb522011-09-22 10:46:35 -07001053 hci_conn_put(conn->hcon);
1054}