blob: a6e2aaba0027cb9bf668d84c156e60c92e53736a [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 Gix58ba0772011-09-23 13:40:16 -0700441 mgmt_auth_failed(hcon->hdev->id, conn->dst, reason);
Brian Gix6d5fb8a2011-09-09 14:53:04 -0700442 hci_conn_put(hcon);
443 } else if (hcon->cfm_pending) {
Brian Gixa68668b2011-08-11 15:49:36 -0700444 BT_DBG("send_pairing_confirm");
445 ret = send_pairing_confirm(conn);
446 }
447
448 return ret;
449}
450
Vinicius Costa Gomes64532ec2011-06-09 18:50:53 -0300451static u8 smp_cmd_pairing_req(struct l2cap_conn *conn, struct sk_buff *skb)
Anderson Briglia13b48392011-06-09 18:50:42 -0300452{
Brian Gixa68668b2011-08-11 15:49:36 -0700453 struct hci_conn *hcon = conn->hcon;
Vinicius Costa Gomes397d9ae2011-06-14 13:37:42 -0300454 struct smp_cmd_pairing rsp, *req = (void *) skb->data;
455 u8 key_size;
Brian Gixa68668b2011-08-11 15:49:36 -0700456 u8 auth = SMP_AUTH_NONE;
457 int ret;
Anderson Briglia13b48392011-06-09 18:50:42 -0300458
459 BT_DBG("conn %p", conn);
460
Brian Gixa68668b2011-08-11 15:49:36 -0700461 hcon->preq[0] = SMP_CMD_PAIRING_REQ;
462 memcpy(&hcon->preq[1], req, sizeof(*req));
Vinicius Costa Gomes397d9ae2011-06-14 13:37:42 -0300463 skb_pull(skb, sizeof(*req));
Anderson Briglia13b48392011-06-09 18:50:42 -0300464
Brian Gixa68668b2011-08-11 15:49:36 -0700465 if (req->oob_flag && hcon->oob) {
466 /* By definition, OOB data pairing will have MITM protection */
467 auth = req->auth_req | SMP_AUTH_MITM;
468 } else if (req->auth_req & SMP_AUTH_BONDING) {
469 /* We will attempt MITM for all Bonding attempts */
470 auth = SMP_AUTH_BONDING | SMP_AUTH_MITM;
471 }
Vinicius Costa Gomes64532ec2011-06-09 18:50:53 -0300472
473 /* We didn't start the pairing, so no requirements */
Brian Gixa68668b2011-08-11 15:49:36 -0700474 build_pairing_cmd(conn, req, &rsp, auth);
Vinicius Costa Gomes397d9ae2011-06-14 13:37:42 -0300475
476 key_size = min(req->max_key_size, rsp.max_key_size);
477 if (check_enc_key_size(conn, key_size))
478 return SMP_ENC_KEY_SIZE;
Anderson Briglia13b48392011-06-09 18:50:42 -0300479
Brian Gixa68668b2011-08-11 15:49:36 -0700480 ret = smp_rand(hcon->prnd);
481 if (ret)
482 return SMP_UNSPECIFIED;
Anderson Briglia21b8a2b2011-06-09 18:50:46 -0300483
Brian Gixa68668b2011-08-11 15:49:36 -0700484 /* Request setup of TK */
485 ret = tk_request(conn, req->oob_flag, auth, rsp.io_capability,
486 req->io_capability);
487 if (ret)
488 return SMP_UNSPECIFIED;
489
490 hcon->prsp[0] = SMP_CMD_PAIRING_RSP;
491 memcpy(&hcon->prsp[1], &rsp, sizeof(rsp));
Anderson Brigliac8e856e2011-06-09 18:50:45 -0300492
Vinicius Costa Gomes397d9ae2011-06-14 13:37:42 -0300493 smp_send_cmd(conn, SMP_CMD_PAIRING_RSP, sizeof(rsp), &rsp);
Vinicius Costa Gomes64532ec2011-06-09 18:50:53 -0300494
Brian Gixe9ceb522011-09-22 10:46:35 -0700495 mod_timer(&hcon->smp_timer, jiffies + msecs_to_jiffies(SMP_TIMEOUT));
Vinicius Costa Gomesb19d5ce2011-06-14 13:37:41 -0300496
Vinicius Costa Gomes64532ec2011-06-09 18:50:53 -0300497 return 0;
Anderson Briglia13b48392011-06-09 18:50:42 -0300498}
499
Vinicius Costa Gomes64532ec2011-06-09 18:50:53 -0300500static u8 smp_cmd_pairing_rsp(struct l2cap_conn *conn, struct sk_buff *skb)
Anderson Briglia13b48392011-06-09 18:50:42 -0300501{
Brian Gixa68668b2011-08-11 15:49:36 -0700502 struct hci_conn *hcon = conn->hcon;
Vinicius Costa Gomes397d9ae2011-06-14 13:37:42 -0300503 struct smp_cmd_pairing *req, *rsp = (void *) skb->data;
Brian Gixa68668b2011-08-11 15:49:36 -0700504 u8 key_size, auth = SMP_AUTH_NONE;
Anderson Briglia21b8a2b2011-06-09 18:50:46 -0300505 int ret;
Anderson Briglia13b48392011-06-09 18:50:42 -0300506
507 BT_DBG("conn %p", conn);
508
Vinicius Costa Gomes397d9ae2011-06-14 13:37:42 -0300509 skb_pull(skb, sizeof(*rsp));
Vinicius Costa Gomes64532ec2011-06-09 18:50:53 -0300510
Brian Gixa68668b2011-08-11 15:49:36 -0700511 req = (void *) &hcon->preq[1];
Vinicius Costa Gomes397d9ae2011-06-14 13:37:42 -0300512
513 key_size = min(req->max_key_size, rsp->max_key_size);
514 if (check_enc_key_size(conn, key_size))
515 return SMP_ENC_KEY_SIZE;
516
Brian Gixa68668b2011-08-11 15:49:36 -0700517 hcon->prsp[0] = SMP_CMD_PAIRING_RSP;
518 memcpy(&hcon->prsp[1], rsp, sizeof(*rsp));
Vinicius Costa Gomes64532ec2011-06-09 18:50:53 -0300519
Brian Gixa68668b2011-08-11 15:49:36 -0700520 ret = smp_rand(hcon->prnd);
Anderson Briglia21b8a2b2011-06-09 18:50:46 -0300521 if (ret)
Vinicius Costa Gomes64532ec2011-06-09 18:50:53 -0300522 return SMP_UNSPECIFIED;
Anderson Briglia21b8a2b2011-06-09 18:50:46 -0300523
Brian Gixa68668b2011-08-11 15:49:36 -0700524 if ((req->auth_req & SMP_AUTH_BONDING) &&
525 (rsp->auth_req & SMP_AUTH_BONDING))
526 auth = SMP_AUTH_BONDING;
527
528 auth |= (req->auth_req | rsp->auth_req) & SMP_AUTH_MITM;
529
530 ret = tk_request(conn, req->oob_flag, auth, rsp->io_capability,
531 req->io_capability);
Anderson Briglia21b8a2b2011-06-09 18:50:46 -0300532 if (ret)
Vinicius Costa Gomes64532ec2011-06-09 18:50:53 -0300533 return SMP_UNSPECIFIED;
Anderson Briglia21b8a2b2011-06-09 18:50:46 -0300534
Brian Gixa68668b2011-08-11 15:49:36 -0700535 hcon->cfm_pending = TRUE;
Anderson Briglia21b8a2b2011-06-09 18:50:46 -0300536
Brian Gixa68668b2011-08-11 15:49:36 -0700537 /* Can't compose response until we have been confirmed */
538 if (!hcon->tk_valid)
539 return 0;
540
541 ret = send_pairing_confirm(conn);
542 if (ret)
543 return SMP_CONFIRM_FAILED;
Vinicius Costa Gomes64532ec2011-06-09 18:50:53 -0300544
545 return 0;
Anderson Briglia13b48392011-06-09 18:50:42 -0300546}
547
Vinicius Costa Gomes64532ec2011-06-09 18:50:53 -0300548static u8 smp_cmd_pairing_confirm(struct l2cap_conn *conn, struct sk_buff *skb)
Anderson Briglia13b48392011-06-09 18:50:42 -0300549{
Brian Gixa68668b2011-08-11 15:49:36 -0700550 struct hci_conn *hcon = conn->hcon;
551 int ret;
Anderson Briglia21b8a2b2011-06-09 18:50:46 -0300552
Anderson Briglia13b48392011-06-09 18:50:42 -0300553 BT_DBG("conn %p %s", conn, conn->hcon->out ? "master" : "slave");
554
Brian Gixa68668b2011-08-11 15:49:36 -0700555 memcpy(hcon->pcnf, skb->data, sizeof(hcon->pcnf));
556 skb_pull(skb, sizeof(hcon->pcnf));
Anderson Briglia21b8a2b2011-06-09 18:50:46 -0300557
Anderson Briglia13b48392011-06-09 18:50:42 -0300558 if (conn->hcon->out) {
Anderson Briglia21b8a2b2011-06-09 18:50:46 -0300559 u8 random[16];
Anderson Briglia13b48392011-06-09 18:50:42 -0300560
Brian Gixa68668b2011-08-11 15:49:36 -0700561 swap128(hcon->prnd, random);
Anderson Briglia13b48392011-06-09 18:50:42 -0300562 smp_send_cmd(conn, SMP_CMD_PAIRING_RANDOM, sizeof(random),
Anderson Briglia21b8a2b2011-06-09 18:50:46 -0300563 random);
Brian Gixa68668b2011-08-11 15:49:36 -0700564 } else if (hcon->tk_valid) {
565 ret = send_pairing_confirm(conn);
Anderson Briglia13b48392011-06-09 18:50:42 -0300566
Anderson Briglia21b8a2b2011-06-09 18:50:46 -0300567 if (ret)
Vinicius Costa Gomes64532ec2011-06-09 18:50:53 -0300568 return SMP_CONFIRM_FAILED;
Brian Gixa68668b2011-08-11 15:49:36 -0700569 } else
570 hcon->cfm_pending = TRUE;
Anderson Briglia21b8a2b2011-06-09 18:50:46 -0300571
Vinicius Costa Gomes64532ec2011-06-09 18:50:53 -0300572
Brian Gixe9ceb522011-09-22 10:46:35 -0700573 mod_timer(&hcon->smp_timer, jiffies + msecs_to_jiffies(SMP_TIMEOUT));
Vinicius Costa Gomesb19d5ce2011-06-14 13:37:41 -0300574
Vinicius Costa Gomes64532ec2011-06-09 18:50:53 -0300575 return 0;
Anderson Briglia13b48392011-06-09 18:50:42 -0300576}
577
Vinicius Costa Gomes64532ec2011-06-09 18:50:53 -0300578static u8 smp_cmd_pairing_random(struct l2cap_conn *conn, struct sk_buff *skb)
Anderson Briglia13b48392011-06-09 18:50:42 -0300579{
Vinicius Costa Gomes735038c2011-06-09 18:50:47 -0300580 struct hci_conn *hcon = conn->hcon;
581 struct crypto_blkcipher *tfm = hcon->hdev->tfm;
Anderson Briglia21b8a2b2011-06-09 18:50:46 -0300582 int ret;
Vinicius Costa Gomesc34e25e2011-06-09 18:50:48 -0300583 u8 key[16], res[16], random[16], confirm[16];
Anderson Briglia21b8a2b2011-06-09 18:50:46 -0300584
585 swap128(skb->data, random);
586 skb_pull(skb, sizeof(random));
587
588 if (conn->hcon->out)
Brian Gixa68668b2011-08-11 15:49:36 -0700589 ret = smp_c1(tfm, hcon->tk, random, hcon->preq, hcon->prsp, 0,
590 conn->src, hcon->dst_type, conn->dst,
Anderson Briglia21b8a2b2011-06-09 18:50:46 -0300591 res);
592 else
Brian Gixa68668b2011-08-11 15:49:36 -0700593 ret = smp_c1(tfm, hcon->tk, random, hcon->preq, hcon->prsp,
594 hcon->dst_type, conn->dst, 0, conn->src,
Anderson Briglia21b8a2b2011-06-09 18:50:46 -0300595 res);
596 if (ret)
Vinicius Costa Gomes64532ec2011-06-09 18:50:53 -0300597 return SMP_UNSPECIFIED;
Anderson Briglia13b48392011-06-09 18:50:42 -0300598
599 BT_DBG("conn %p %s", conn, conn->hcon->out ? "master" : "slave");
600
Anderson Briglia21b8a2b2011-06-09 18:50:46 -0300601 swap128(res, confirm);
602
Brian Gixa68668b2011-08-11 15:49:36 -0700603 if (memcmp(hcon->pcnf, confirm, sizeof(hcon->pcnf)) != 0) {
Anderson Briglia21b8a2b2011-06-09 18:50:46 -0300604 BT_ERR("Pairing failed (confirmation values mismatch)");
Vinicius Costa Gomes64532ec2011-06-09 18:50:53 -0300605 return SMP_CONFIRM_FAILED;
Anderson Briglia21b8a2b2011-06-09 18:50:46 -0300606 }
Anderson Briglia13b48392011-06-09 18:50:42 -0300607
608 if (conn->hcon->out) {
Vinicius Costa Gomesf1b45c52011-07-07 18:59:40 -0300609 u8 stk[16], rand[8];
Vinicius Costa Gomes735038c2011-06-09 18:50:47 -0300610 __le16 ediv;
Vinicius Costa Gomes397d9ae2011-06-14 13:37:42 -0300611
Vinicius Costa Gomes735038c2011-06-09 18:50:47 -0300612 memset(rand, 0, sizeof(rand));
613 ediv = 0;
Vinicius Costa Gomesf1b45c52011-07-07 18:59:40 -0300614
Brian Gixa68668b2011-08-11 15:49:36 -0700615 smp_s1(tfm, hcon->tk, random, hcon->prnd, key);
Vinicius Costa Gomesf1b45c52011-07-07 18:59:40 -0300616 swap128(key, stk);
617
Brian Gixa68668b2011-08-11 15:49:36 -0700618 memset(stk + hcon->smp_key_size, 0,
619 SMP_MAX_ENC_KEY_SIZE - hcon->smp_key_size);
Vinicius Costa Gomesf1b45c52011-07-07 18:59:40 -0300620
621 hci_le_start_enc(hcon, ediv, rand, stk);
Brian Gixa68668b2011-08-11 15:49:36 -0700622 hcon->enc_key_size = hcon->smp_key_size;
Anderson Briglia21b8a2b2011-06-09 18:50:46 -0300623 } else {
Vinicius Costa Gomesf1b45c52011-07-07 18:59:40 -0300624 u8 stk[16], r[16], rand[8];
625 __le16 ediv;
626
627 memset(rand, 0, sizeof(rand));
628 ediv = 0;
Anderson Briglia21b8a2b2011-06-09 18:50:46 -0300629
Brian Gixa68668b2011-08-11 15:49:36 -0700630 swap128(hcon->prnd, r);
Anderson Briglia21b8a2b2011-06-09 18:50:46 -0300631 smp_send_cmd(conn, SMP_CMD_PAIRING_RANDOM, sizeof(r), r);
632
Brian Gixa68668b2011-08-11 15:49:36 -0700633 smp_s1(tfm, hcon->tk, hcon->prnd, random, key);
Vinicius Costa Gomesf1b45c52011-07-07 18:59:40 -0300634 swap128(key, stk);
Vinicius Costa Gomes397d9ae2011-06-14 13:37:42 -0300635
Brian Gixa68668b2011-08-11 15:49:36 -0700636 memset(stk + hcon->smp_key_size, 0,
637 SMP_MAX_ENC_KEY_SIZE - hcon->smp_key_size);
Vinicius Costa Gomesf1b45c52011-07-07 18:59:40 -0300638
Brian Gixa68668b2011-08-11 15:49:36 -0700639 hci_add_ltk(conn->hcon->hdev, 0, conn->dst, hcon->smp_key_size,
640 hcon->auth, ediv, rand, stk);
Anderson Briglia13b48392011-06-09 18:50:42 -0300641 }
Vinicius Costa Gomes64532ec2011-06-09 18:50:53 -0300642
643 return 0;
Anderson Briglia13b48392011-06-09 18:50:42 -0300644}
645
Vinicius Costa Gomes64532ec2011-06-09 18:50:53 -0300646static u8 smp_cmd_security_req(struct l2cap_conn *conn, struct sk_buff *skb)
Anderson Briglia13b48392011-06-09 18:50:42 -0300647{
Brian Gixa68668b2011-08-11 15:49:36 -0700648 struct hci_conn *hcon = conn->hcon;
Anderson Briglia13b48392011-06-09 18:50:42 -0300649 struct smp_cmd_security_req *rp = (void *) skb->data;
650 struct smp_cmd_pairing cp;
Brian Gixa68668b2011-08-11 15:49:36 -0700651 struct link_key *key;
Anderson Briglia13b48392011-06-09 18:50:42 -0300652
653 BT_DBG("conn %p", conn);
654
Vinicius Costa Gomesa5474a82011-01-26 21:42:57 -0300655 if (test_bit(HCI_CONN_ENCRYPT_PEND, &hcon->pend))
Vinicius Costa Gomes64532ec2011-06-09 18:50:53 -0300656 return 0;
Vinicius Costa Gomesa5474a82011-01-26 21:42:57 -0300657
Brian Gixa68668b2011-08-11 15:49:36 -0700658 key = hci_find_link_key_type(hcon->hdev, conn->dst, KEY_TYPE_LTK);
659 if (key && ((key->auth & SMP_AUTH_MITM) ||
660 !(rp->auth_req & SMP_AUTH_MITM))) {
661 struct key_master_id *master = (void *) key->data;
662
663 hci_le_start_enc(hcon, master->ediv, master->rand,
664 key->val);
665 hcon->enc_key_size = key->pin_len;
666
667 hcon->sec_req = TRUE;
668 hcon->sec_level = authreq_to_seclevel(rp->auth_req);
669
670 return 0;
671 }
672
673 hcon->sec_req = FALSE;
674
Anderson Briglia13b48392011-06-09 18:50:42 -0300675 skb_pull(skb, sizeof(*rp));
Anderson Briglia13b48392011-06-09 18:50:42 -0300676
Vinicius Costa Gomes64532ec2011-06-09 18:50:53 -0300677 memset(&cp, 0, sizeof(cp));
Vinicius Costa Gomes10daf972011-07-07 18:59:38 -0300678 build_pairing_cmd(conn, &cp, NULL, rp->auth_req);
Anderson Briglia13b48392011-06-09 18:50:42 -0300679
Brian Gixa68668b2011-08-11 15:49:36 -0700680 hcon->preq[0] = SMP_CMD_PAIRING_REQ;
681 memcpy(&hcon->preq[1], &cp, sizeof(cp));
Anderson Brigliac8e856e2011-06-09 18:50:45 -0300682
Anderson Briglia13b48392011-06-09 18:50:42 -0300683 smp_send_cmd(conn, SMP_CMD_PAIRING_REQ, sizeof(cp), &cp);
Vinicius Costa Gomesa5474a82011-01-26 21:42:57 -0300684
Brian Gixe9ceb522011-09-22 10:46:35 -0700685 mod_timer(&hcon->smp_timer, jiffies + msecs_to_jiffies(SMP_TIMEOUT));
Vinicius Costa Gomesb19d5ce2011-06-14 13:37:41 -0300686
Vinicius Costa Gomesa5474a82011-01-26 21:42:57 -0300687 set_bit(HCI_CONN_ENCRYPT_PEND, &hcon->pend);
Vinicius Costa Gomesa5474a82011-01-26 21:42:57 -0300688
Vinicius Costa Gomes64532ec2011-06-09 18:50:53 -0300689 return 0;
Anderson Briglia13b48392011-06-09 18:50:42 -0300690}
691
Anderson Briglia133e14c2011-06-09 18:50:40 -0300692int smp_conn_security(struct l2cap_conn *conn, __u8 sec_level)
693{
Vinicius Costa Gomes09fabbc2011-06-09 18:50:43 -0300694 struct hci_conn *hcon = conn->hcon;
Anderson Briglia133e14c2011-06-09 18:50:40 -0300695 __u8 authreq;
696
Vinicius Costa Gomes09fabbc2011-06-09 18:50:43 -0300697 BT_DBG("conn %p hcon %p level 0x%2.2x", conn, hcon, sec_level);
698
Brian Gixa68668b2011-08-11 15:49:36 -0700699 if (IS_ERR(hcon->hdev->tfm)) {
700 BT_DBG("IS_ERR");
Vinicius Costa Gomes09fabbc2011-06-09 18:50:43 -0300701 return 1;
Brian Gixa68668b2011-08-11 15:49:36 -0700702 }
Anderson Briglia133e14c2011-06-09 18:50:40 -0300703
Brian Gixa68668b2011-08-11 15:49:36 -0700704 if (test_bit(HCI_CONN_ENCRYPT_PEND, &hcon->pend)) {
705 BT_DBG("HCI_CONN_ENCRYPT_PEND");
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700706 return -EINPROGRESS;
Brian Gixa68668b2011-08-11 15:49:36 -0700707 }
Anderson Briglia133e14c2011-06-09 18:50:40 -0300708
Brian Gixa68668b2011-08-11 15:49:36 -0700709 if (sec_level == BT_SECURITY_LOW) {
710 BT_DBG("BT_SECURITY_LOW");
Anderson Briglia133e14c2011-06-09 18:50:40 -0300711 return 1;
Brian Gixa68668b2011-08-11 15:49:36 -0700712 }
Vinicius Costa Gomesa5474a82011-01-26 21:42:57 -0300713
Brian Gixa68668b2011-08-11 15:49:36 -0700714 if (hcon->sec_level > sec_level) {
715 BT_DBG("hcon->sec_level > sec_level");
Vinicius Costa Gomesa5474a82011-01-26 21:42:57 -0300716 return 1;
Brian Gixa68668b2011-08-11 15:49:36 -0700717 }
Vinicius Costa Gomesa5474a82011-01-26 21:42:57 -0300718
719 authreq = seclevel_to_authreq(sec_level);
Anderson Briglia133e14c2011-06-09 18:50:40 -0300720
Brian Gixa68668b2011-08-11 15:49:36 -0700721 BT_ERR("conn = %p, sec: %d", conn, sec_level);
722 hcon->smp_conn = conn;
723 hcon->sec_level = sec_level;
724
725 if ((hcon->link_mode & HCI_LM_MASTER) && !hcon->sec_req) {
Vinicius Costa Gomes5d873ca2011-07-07 18:59:41 -0300726 struct link_key *key;
727
728 key = hci_find_link_key_type(hcon->hdev, conn->dst,
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700729 KEY_TYPE_LTK);
Vinicius Costa Gomes5d873ca2011-07-07 18:59:41 -0300730 if (key) {
731 struct key_master_id *master = (void *) key->data;
732
733 hci_le_start_enc(hcon, master->ediv, master->rand,
734 key->val);
Vinicius Costa Gomes1fa2de32011-07-08 18:31:45 -0300735 hcon->enc_key_size = key->pin_len;
736
Brian Gixa68668b2011-08-11 15:49:36 -0700737 hcon->sec_req = TRUE;
738
Vinicius Costa Gomes5d873ca2011-07-07 18:59:41 -0300739 goto done;
740 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700741 }
742
Brian Gixa68668b2011-08-11 15:49:36 -0700743 hcon->sec_req = FALSE;
744
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700745 if (hcon->link_mode & HCI_LM_MASTER) {
746 struct smp_cmd_pairing cp;
Anderson Brigliac8e856e2011-06-09 18:50:45 -0300747
Vinicius Costa Gomes10daf972011-07-07 18:59:38 -0300748 build_pairing_cmd(conn, &cp, NULL, authreq);
Brian Gixa68668b2011-08-11 15:49:36 -0700749 hcon->preq[0] = SMP_CMD_PAIRING_REQ;
750 memcpy(&hcon->preq[1], &cp, sizeof(cp));
Anderson Brigliac8e856e2011-06-09 18:50:45 -0300751
Brian Gixe9ceb522011-09-22 10:46:35 -0700752 mod_timer(&hcon->smp_timer, jiffies +
Vinicius Costa Gomesb19d5ce2011-06-14 13:37:41 -0300753 msecs_to_jiffies(SMP_TIMEOUT));
754
Anderson Briglia133e14c2011-06-09 18:50:40 -0300755 smp_send_cmd(conn, SMP_CMD_PAIRING_REQ, sizeof(cp), &cp);
756 } else {
757 struct smp_cmd_security_req cp;
758 cp.auth_req = authreq;
759 smp_send_cmd(conn, SMP_CMD_SECURITY_REQ, sizeof(cp), &cp);
760 }
761
Vinicius Costa Gomes5d873ca2011-07-07 18:59:41 -0300762done:
Vinicius Costa Gomesa5474a82011-01-26 21:42:57 -0300763 hcon->pending_sec_level = sec_level;
764 set_bit(HCI_CONN_ENCRYPT_PEND, &hcon->pend);
765
Anderson Briglia133e14c2011-06-09 18:50:40 -0300766 return 0;
767}
768
Vinicius Costa Gomesc1d5e1d2011-07-07 18:59:34 -0300769static int smp_cmd_encrypt_info(struct l2cap_conn *conn, struct sk_buff *skb)
770{
Brian Gixa68668b2011-08-11 15:49:36 -0700771 struct hci_conn *hcon = conn->hcon;
Vinicius Costa Gomese56cede2011-07-07 18:59:39 -0300772 struct smp_cmd_encrypt_info *rp = (void *) skb->data;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700773 u8 rand[8];
774 int err;
Vinicius Costa Gomese56cede2011-07-07 18:59:39 -0300775
776 skb_pull(skb, sizeof(*rp));
777
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700778 BT_DBG("conn %p", conn);
779
780 memset(rand, 0, sizeof(rand));
781
Brian Gixa68668b2011-08-11 15:49:36 -0700782 err = hci_add_ltk(hcon->hdev, 0, conn->dst, 0, 0, 0,
783 rand, rp->ltk);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700784 if (err)
785 return SMP_UNSPECIFIED;
Vinicius Costa Gomese56cede2011-07-07 18:59:39 -0300786
Vinicius Costa Gomesc1d5e1d2011-07-07 18:59:34 -0300787 return 0;
788}
789
790static int smp_cmd_master_ident(struct l2cap_conn *conn, struct sk_buff *skb)
791{
Brian Gixa68668b2011-08-11 15:49:36 -0700792 struct hci_conn *hcon = conn->hcon;
Vinicius Costa Gomese56cede2011-07-07 18:59:39 -0300793 struct smp_cmd_master_ident *rp = (void *) skb->data;
Brian Gixa68668b2011-08-11 15:49:36 -0700794 struct smp_cmd_pairing *paircmd = (void *) &hcon->prsp[1];
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700795 struct link_key *key;
Brian Gixa68668b2011-08-11 15:49:36 -0700796 u8 *keydist;
Vinicius Costa Gomesc1d5e1d2011-07-07 18:59:34 -0300797
Vinicius Costa Gomese56cede2011-07-07 18:59:39 -0300798 skb_pull(skb, sizeof(*rp));
799
Brian Gixa68668b2011-08-11 15:49:36 -0700800 key = hci_find_link_key_type(hcon->hdev, conn->dst, KEY_TYPE_LTK);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700801 if (key == NULL)
802 return SMP_UNSPECIFIED;
803
Brian Gixa68668b2011-08-11 15:49:36 -0700804 if (hcon->out)
805 keydist = &paircmd->resp_key_dist;
806 else
807 keydist = &paircmd->init_key_dist;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700808
Brian Gixa68668b2011-08-11 15:49:36 -0700809 BT_DBG("keydist 0x%x", *keydist);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700810
Brian Gixa68668b2011-08-11 15:49:36 -0700811 hci_add_ltk(hcon->hdev, 1, conn->dst, hcon->smp_key_size,
812 hcon->auth, rp->ediv, rp->rand, key->val);
Vinicius Costa Gomesc1d5e1d2011-07-07 18:59:34 -0300813
Brian Gixa68668b2011-08-11 15:49:36 -0700814 *keydist &= ~SMP_DIST_ENC_KEY;
815 if (hcon->out) {
816 if (!(*keydist))
817 smp_distribute_keys(conn, 1);
818 }
Vinicius Costa Gomesc1d5e1d2011-07-07 18:59:34 -0300819
820 return 0;
821}
822
Anderson Briglia133e14c2011-06-09 18:50:40 -0300823int smp_sig_channel(struct l2cap_conn *conn, struct sk_buff *skb)
824{
Brian Gixa68668b2011-08-11 15:49:36 -0700825 struct hci_conn *hcon = conn->hcon;
Anderson Briglia133e14c2011-06-09 18:50:40 -0300826 __u8 code = skb->data[0];
827 __u8 reason;
828 int err = 0;
829
Brian Gixa68668b2011-08-11 15:49:36 -0700830 if (IS_ERR(hcon->hdev->tfm)) {
831 err = PTR_ERR(hcon->hdev->tfm);
Vinicius Costa Gomes09fabbc2011-06-09 18:50:43 -0300832 reason = SMP_PAIRING_NOTSUPP;
Brian Gixa68668b2011-08-11 15:49:36 -0700833 BT_ERR("SMP_PAIRING_NOTSUPP %p", hcon->hdev->tfm);
Vinicius Costa Gomes09fabbc2011-06-09 18:50:43 -0300834 goto done;
835 }
836
Brian Gixa68668b2011-08-11 15:49:36 -0700837 hcon->smp_conn = conn;
Anderson Briglia133e14c2011-06-09 18:50:40 -0300838 skb_pull(skb, sizeof(code));
839
840 switch (code) {
841 case SMP_CMD_PAIRING_REQ:
Vinicius Costa Gomes64532ec2011-06-09 18:50:53 -0300842 reason = smp_cmd_pairing_req(conn, skb);
Anderson Briglia133e14c2011-06-09 18:50:40 -0300843 break;
844
845 case SMP_CMD_PAIRING_FAIL:
Vinicius Costa Gomes64532ec2011-06-09 18:50:53 -0300846 reason = 0;
847 err = -EPERM;
Brian Gixe9ceb522011-09-22 10:46:35 -0700848 del_timer(&hcon->smp_timer);
Brian Gix58ba0772011-09-23 13:40:16 -0700849 mgmt_auth_failed(hcon->hdev->id, conn->dst, skb->data[1]);
Brian Gix6d5fb8a2011-09-09 14:53:04 -0700850 hci_conn_put(hcon);
Anderson Briglia133e14c2011-06-09 18:50:40 -0300851 break;
852
853 case SMP_CMD_PAIRING_RSP:
Vinicius Costa Gomes64532ec2011-06-09 18:50:53 -0300854 reason = smp_cmd_pairing_rsp(conn, skb);
Anderson Briglia13b48392011-06-09 18:50:42 -0300855 break;
856
857 case SMP_CMD_SECURITY_REQ:
Vinicius Costa Gomes64532ec2011-06-09 18:50:53 -0300858 reason = smp_cmd_security_req(conn, skb);
Anderson Briglia13b48392011-06-09 18:50:42 -0300859 break;
860
Anderson Briglia133e14c2011-06-09 18:50:40 -0300861 case SMP_CMD_PAIRING_CONFIRM:
Vinicius Costa Gomes64532ec2011-06-09 18:50:53 -0300862 reason = smp_cmd_pairing_confirm(conn, skb);
Anderson Briglia13b48392011-06-09 18:50:42 -0300863 break;
864
Anderson Briglia133e14c2011-06-09 18:50:40 -0300865 case SMP_CMD_PAIRING_RANDOM:
Vinicius Costa Gomes64532ec2011-06-09 18:50:53 -0300866 reason = smp_cmd_pairing_random(conn, skb);
Anderson Briglia13b48392011-06-09 18:50:42 -0300867 break;
868
Anderson Briglia133e14c2011-06-09 18:50:40 -0300869 case SMP_CMD_ENCRYPT_INFO:
Vinicius Costa Gomesc1d5e1d2011-07-07 18:59:34 -0300870 reason = smp_cmd_encrypt_info(conn, skb);
871 break;
872
Anderson Briglia133e14c2011-06-09 18:50:40 -0300873 case SMP_CMD_MASTER_IDENT:
Vinicius Costa Gomesc1d5e1d2011-07-07 18:59:34 -0300874 reason = smp_cmd_master_ident(conn, skb);
875 break;
876
Anderson Briglia133e14c2011-06-09 18:50:40 -0300877 case SMP_CMD_IDENT_INFO:
878 case SMP_CMD_IDENT_ADDR_INFO:
879 case SMP_CMD_SIGN_INFO:
Vinicius Costa Gomesc1d5e1d2011-07-07 18:59:34 -0300880 /* Just ignored */
881 reason = 0;
882 break;
883
Anderson Briglia133e14c2011-06-09 18:50:40 -0300884 default:
885 BT_DBG("Unknown command code 0x%2.2x", code);
886
887 reason = SMP_CMD_NOTSUPP;
Vinicius Costa Gomes09fabbc2011-06-09 18:50:43 -0300888 err = -EOPNOTSUPP;
889 goto done;
890 }
891
892done:
Brian Gixa68668b2011-08-11 15:49:36 -0700893 if (reason) {
894 BT_ERR("SMP_CMD_PAIRING_FAIL: %d", reason);
Anderson Briglia133e14c2011-06-09 18:50:40 -0300895 smp_send_cmd(conn, SMP_CMD_PAIRING_FAIL, sizeof(reason),
896 &reason);
Brian Gixe9ceb522011-09-22 10:46:35 -0700897 del_timer(&hcon->smp_timer);
Brian Gix58ba0772011-09-23 13:40:16 -0700898 mgmt_auth_failed(hcon->hdev->id, conn->dst, reason);
Brian Gix6d5fb8a2011-09-09 14:53:04 -0700899 hci_conn_put(hcon);
Brian Gixa68668b2011-08-11 15:49:36 -0700900 }
Anderson Briglia133e14c2011-06-09 18:50:40 -0300901
902 kfree_skb(skb);
903 return err;
904}
Vinicius Costa Gomesc1d5e1d2011-07-07 18:59:34 -0300905
Brian Gixa68668b2011-08-11 15:49:36 -0700906static int smp_distribute_keys(struct l2cap_conn *conn, __u8 force)
Vinicius Costa Gomesc1d5e1d2011-07-07 18:59:34 -0300907{
Brian Gixa68668b2011-08-11 15:49:36 -0700908 struct hci_conn *hcon = conn->hcon;
Vinicius Costa Gomesc1d5e1d2011-07-07 18:59:34 -0300909 struct smp_cmd_pairing *req, *rsp;
910 __u8 *keydist;
911
912 BT_DBG("conn %p force %d", conn, force);
913
Brian Gixa68668b2011-08-11 15:49:36 -0700914 if (IS_ERR(hcon->hdev->tfm))
915 return PTR_ERR(hcon->hdev->tfm);
Vinicius Costa Gomesc1d5e1d2011-07-07 18:59:34 -0300916
Brian Gixa68668b2011-08-11 15:49:36 -0700917 rsp = (void *) &hcon->prsp[1];
Vinicius Costa Gomesc1d5e1d2011-07-07 18:59:34 -0300918
919 /* The responder sends its keys first */
Brian Gixa68668b2011-08-11 15:49:36 -0700920 if (!force && hcon->out && (rsp->resp_key_dist & 0x07))
Vinicius Costa Gomesc1d5e1d2011-07-07 18:59:34 -0300921 return 0;
922
Brian Gixa68668b2011-08-11 15:49:36 -0700923 req = (void *) &hcon->preq[1];
Vinicius Costa Gomesc1d5e1d2011-07-07 18:59:34 -0300924
Brian Gixa68668b2011-08-11 15:49:36 -0700925 if (hcon->out) {
Vinicius Costa Gomesc1d5e1d2011-07-07 18:59:34 -0300926 keydist = &rsp->init_key_dist;
927 *keydist &= req->init_key_dist;
928 } else {
929 keydist = &rsp->resp_key_dist;
930 *keydist &= req->resp_key_dist;
931 }
932
933
934 BT_DBG("keydist 0x%x", *keydist);
935
936 if (*keydist & SMP_DIST_ENC_KEY) {
937 struct smp_cmd_encrypt_info enc;
938 struct smp_cmd_master_ident ident;
939 __le16 ediv;
940
941 get_random_bytes(enc.ltk, sizeof(enc.ltk));
942 get_random_bytes(&ediv, sizeof(ediv));
943 get_random_bytes(ident.rand, sizeof(ident.rand));
944
945 smp_send_cmd(conn, SMP_CMD_ENCRYPT_INFO, sizeof(enc), &enc);
946
Brian Gixa68668b2011-08-11 15:49:36 -0700947 hci_add_ltk(hcon->hdev, 1, conn->dst, hcon->smp_key_size,
948 hcon->auth, ediv, ident.rand, enc.ltk);
Vinicius Costa Gomese56cede2011-07-07 18:59:39 -0300949
Vinicius Costa Gomesc1d5e1d2011-07-07 18:59:34 -0300950 ident.ediv = cpu_to_le16(ediv);
951
952 smp_send_cmd(conn, SMP_CMD_MASTER_IDENT, sizeof(ident), &ident);
953
954 *keydist &= ~SMP_DIST_ENC_KEY;
955 }
956
957 if (*keydist & SMP_DIST_ID_KEY) {
958 struct smp_cmd_ident_addr_info addrinfo;
959 struct smp_cmd_ident_info idinfo;
960
961 /* Send a dummy key */
962 get_random_bytes(idinfo.irk, sizeof(idinfo.irk));
963
964 smp_send_cmd(conn, SMP_CMD_IDENT_INFO, sizeof(idinfo), &idinfo);
965
966 /* Just public address */
967 memset(&addrinfo, 0, sizeof(addrinfo));
968 bacpy(&addrinfo.bdaddr, conn->src);
969
970 smp_send_cmd(conn, SMP_CMD_IDENT_ADDR_INFO, sizeof(addrinfo),
971 &addrinfo);
972
973 *keydist &= ~SMP_DIST_ID_KEY;
974 }
975
976 if (*keydist & SMP_DIST_SIGN) {
977 struct smp_cmd_sign_info sign;
978
979 /* Send a dummy key */
980 get_random_bytes(sign.csrk, sizeof(sign.csrk));
981
982 smp_send_cmd(conn, SMP_CMD_SIGN_INFO, sizeof(sign), &sign);
983
984 *keydist &= ~SMP_DIST_SIGN;
985 }
986
Brian Gix6d5fb8a2011-09-09 14:53:04 -0700987 if (hcon->out || rsp->resp_key_dist) {
Brian Gixe57c1672011-09-13 12:34:59 -0700988 if (hcon->disconn_cfm_cb)
989 hcon->disconn_cfm_cb(hcon, 0);
Brian Gixe9ceb522011-09-22 10:46:35 -0700990
991 del_timer(&hcon->smp_timer);
Brian Gix58ba0772011-09-23 13:40:16 -0700992 mgmt_auth_failed(hcon->hdev->id, conn->dst, SMP_UNSPECIFIED);
Brian Gix6d5fb8a2011-09-09 14:53:04 -0700993 hci_conn_put(hcon);
994 }
Brian Gixa68668b2011-08-11 15:49:36 -0700995
996 return 0;
997}
998
999int smp_link_encrypt_cmplt(struct l2cap_conn *conn, u8 status, u8 encrypt)
1000{
1001 struct hci_conn *hcon = conn->hcon;
1002
1003 BT_DBG("smp: %d %d %d", status, encrypt, hcon->sec_req);
1004
1005 if (!status && encrypt && !hcon->sec_req)
1006 smp_distribute_keys(conn, 0);
1007
1008 /* Fall back to Pairing request if failed a Link Security request */
1009 else if (hcon->sec_req && (status || !encrypt))
1010 smp_conn_security(conn, hcon->sec_level);
1011
Vinicius Costa Gomesc1d5e1d2011-07-07 18:59:34 -03001012 return 0;
1013}
Brian Gixe9ceb522011-09-22 10:46:35 -07001014
1015void smp_timeout(unsigned long arg)
1016{
1017 struct l2cap_conn *conn = (void *) arg;
1018 u8 reason = SMP_UNSPECIFIED;
1019
1020 BT_DBG("%p", conn);
1021
1022 smp_send_cmd(conn, SMP_CMD_PAIRING_FAIL, sizeof(reason), &reason);
Brian Gix58ba0772011-09-23 13:40:16 -07001023 mgmt_auth_failed(conn->hcon->hdev->id, conn->dst, SMP_UNSPECIFIED);
Brian Gixe9ceb522011-09-22 10:46:35 -07001024 hci_conn_put(conn->hcon);
1025}