blob: aea2447f0934c0fef1a58add3bf5efc416665d80 [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 Gix6d5fb8a2011-09-09 14:53:04 -0700441 hci_conn_put(hcon);
442 } else if (hcon->cfm_pending) {
Brian Gixa68668b2011-08-11 15:49:36 -0700443 BT_DBG("send_pairing_confirm");
444 ret = send_pairing_confirm(conn);
445 }
446
447 return ret;
448}
449
Vinicius Costa Gomes64532ec2011-06-09 18:50:53 -0300450static u8 smp_cmd_pairing_req(struct l2cap_conn *conn, struct sk_buff *skb)
Anderson Briglia13b48392011-06-09 18:50:42 -0300451{
Brian Gixa68668b2011-08-11 15:49:36 -0700452 struct hci_conn *hcon = conn->hcon;
Vinicius Costa Gomes397d9ae2011-06-14 13:37:42 -0300453 struct smp_cmd_pairing rsp, *req = (void *) skb->data;
454 u8 key_size;
Brian Gixa68668b2011-08-11 15:49:36 -0700455 u8 auth = SMP_AUTH_NONE;
456 int ret;
Anderson Briglia13b48392011-06-09 18:50:42 -0300457
458 BT_DBG("conn %p", conn);
459
Brian Gixa68668b2011-08-11 15:49:36 -0700460 hcon->preq[0] = SMP_CMD_PAIRING_REQ;
461 memcpy(&hcon->preq[1], req, sizeof(*req));
Vinicius Costa Gomes397d9ae2011-06-14 13:37:42 -0300462 skb_pull(skb, sizeof(*req));
Anderson Briglia13b48392011-06-09 18:50:42 -0300463
Brian Gixa68668b2011-08-11 15:49:36 -0700464 if (req->oob_flag && hcon->oob) {
465 /* By definition, OOB data pairing will have MITM protection */
466 auth = req->auth_req | SMP_AUTH_MITM;
467 } else if (req->auth_req & SMP_AUTH_BONDING) {
468 /* We will attempt MITM for all Bonding attempts */
469 auth = SMP_AUTH_BONDING | SMP_AUTH_MITM;
470 }
Vinicius Costa Gomes64532ec2011-06-09 18:50:53 -0300471
472 /* We didn't start the pairing, so no requirements */
Brian Gixa68668b2011-08-11 15:49:36 -0700473 build_pairing_cmd(conn, req, &rsp, auth);
Vinicius Costa Gomes397d9ae2011-06-14 13:37:42 -0300474
475 key_size = min(req->max_key_size, rsp.max_key_size);
476 if (check_enc_key_size(conn, key_size))
477 return SMP_ENC_KEY_SIZE;
Anderson Briglia13b48392011-06-09 18:50:42 -0300478
Brian Gixa68668b2011-08-11 15:49:36 -0700479 ret = smp_rand(hcon->prnd);
480 if (ret)
481 return SMP_UNSPECIFIED;
Anderson Briglia21b8a2b2011-06-09 18:50:46 -0300482
Brian Gixa68668b2011-08-11 15:49:36 -0700483 /* Request setup of TK */
484 ret = tk_request(conn, req->oob_flag, auth, rsp.io_capability,
485 req->io_capability);
486 if (ret)
487 return SMP_UNSPECIFIED;
488
489 hcon->prsp[0] = SMP_CMD_PAIRING_RSP;
490 memcpy(&hcon->prsp[1], &rsp, sizeof(rsp));
Anderson Brigliac8e856e2011-06-09 18:50:45 -0300491
Vinicius Costa Gomes397d9ae2011-06-14 13:37:42 -0300492 smp_send_cmd(conn, SMP_CMD_PAIRING_RSP, sizeof(rsp), &rsp);
Vinicius Costa Gomes64532ec2011-06-09 18:50:53 -0300493
Brian Gixe9ceb522011-09-22 10:46:35 -0700494 mod_timer(&hcon->smp_timer, jiffies + msecs_to_jiffies(SMP_TIMEOUT));
Vinicius Costa Gomesb19d5ce2011-06-14 13:37:41 -0300495
Vinicius Costa Gomes64532ec2011-06-09 18:50:53 -0300496 return 0;
Anderson Briglia13b48392011-06-09 18:50:42 -0300497}
498
Vinicius Costa Gomes64532ec2011-06-09 18:50:53 -0300499static u8 smp_cmd_pairing_rsp(struct l2cap_conn *conn, struct sk_buff *skb)
Anderson Briglia13b48392011-06-09 18:50:42 -0300500{
Brian Gixa68668b2011-08-11 15:49:36 -0700501 struct hci_conn *hcon = conn->hcon;
Vinicius Costa Gomes397d9ae2011-06-14 13:37:42 -0300502 struct smp_cmd_pairing *req, *rsp = (void *) skb->data;
Brian Gixa68668b2011-08-11 15:49:36 -0700503 u8 key_size, auth = SMP_AUTH_NONE;
Anderson Briglia21b8a2b2011-06-09 18:50:46 -0300504 int ret;
Anderson Briglia13b48392011-06-09 18:50:42 -0300505
506 BT_DBG("conn %p", conn);
507
Vinicius Costa Gomes397d9ae2011-06-14 13:37:42 -0300508 skb_pull(skb, sizeof(*rsp));
Vinicius Costa Gomes64532ec2011-06-09 18:50:53 -0300509
Brian Gixa68668b2011-08-11 15:49:36 -0700510 req = (void *) &hcon->preq[1];
Vinicius Costa Gomes397d9ae2011-06-14 13:37:42 -0300511
512 key_size = min(req->max_key_size, rsp->max_key_size);
513 if (check_enc_key_size(conn, key_size))
514 return SMP_ENC_KEY_SIZE;
515
Brian Gixa68668b2011-08-11 15:49:36 -0700516 hcon->prsp[0] = SMP_CMD_PAIRING_RSP;
517 memcpy(&hcon->prsp[1], rsp, sizeof(*rsp));
Vinicius Costa Gomes64532ec2011-06-09 18:50:53 -0300518
Brian Gixa68668b2011-08-11 15:49:36 -0700519 ret = smp_rand(hcon->prnd);
Anderson Briglia21b8a2b2011-06-09 18:50:46 -0300520 if (ret)
Vinicius Costa Gomes64532ec2011-06-09 18:50:53 -0300521 return SMP_UNSPECIFIED;
Anderson Briglia21b8a2b2011-06-09 18:50:46 -0300522
Brian Gixa68668b2011-08-11 15:49:36 -0700523 if ((req->auth_req & SMP_AUTH_BONDING) &&
524 (rsp->auth_req & SMP_AUTH_BONDING))
525 auth = SMP_AUTH_BONDING;
526
527 auth |= (req->auth_req | rsp->auth_req) & SMP_AUTH_MITM;
528
529 ret = tk_request(conn, req->oob_flag, auth, rsp->io_capability,
530 req->io_capability);
Anderson Briglia21b8a2b2011-06-09 18:50:46 -0300531 if (ret)
Vinicius Costa Gomes64532ec2011-06-09 18:50:53 -0300532 return SMP_UNSPECIFIED;
Anderson Briglia21b8a2b2011-06-09 18:50:46 -0300533
Brian Gixa68668b2011-08-11 15:49:36 -0700534 hcon->cfm_pending = TRUE;
Anderson Briglia21b8a2b2011-06-09 18:50:46 -0300535
Brian Gixa68668b2011-08-11 15:49:36 -0700536 /* Can't compose response until we have been confirmed */
537 if (!hcon->tk_valid)
538 return 0;
539
540 ret = send_pairing_confirm(conn);
541 if (ret)
542 return SMP_CONFIRM_FAILED;
Vinicius Costa Gomes64532ec2011-06-09 18:50:53 -0300543
544 return 0;
Anderson Briglia13b48392011-06-09 18:50:42 -0300545}
546
Vinicius Costa Gomes64532ec2011-06-09 18:50:53 -0300547static u8 smp_cmd_pairing_confirm(struct l2cap_conn *conn, struct sk_buff *skb)
Anderson Briglia13b48392011-06-09 18:50:42 -0300548{
Brian Gixa68668b2011-08-11 15:49:36 -0700549 struct hci_conn *hcon = conn->hcon;
550 int ret;
Anderson Briglia21b8a2b2011-06-09 18:50:46 -0300551
Anderson Briglia13b48392011-06-09 18:50:42 -0300552 BT_DBG("conn %p %s", conn, conn->hcon->out ? "master" : "slave");
553
Brian Gixa68668b2011-08-11 15:49:36 -0700554 memcpy(hcon->pcnf, skb->data, sizeof(hcon->pcnf));
555 skb_pull(skb, sizeof(hcon->pcnf));
Anderson Briglia21b8a2b2011-06-09 18:50:46 -0300556
Anderson Briglia13b48392011-06-09 18:50:42 -0300557 if (conn->hcon->out) {
Anderson Briglia21b8a2b2011-06-09 18:50:46 -0300558 u8 random[16];
Anderson Briglia13b48392011-06-09 18:50:42 -0300559
Brian Gixa68668b2011-08-11 15:49:36 -0700560 swap128(hcon->prnd, random);
Anderson Briglia13b48392011-06-09 18:50:42 -0300561 smp_send_cmd(conn, SMP_CMD_PAIRING_RANDOM, sizeof(random),
Anderson Briglia21b8a2b2011-06-09 18:50:46 -0300562 random);
Brian Gixa68668b2011-08-11 15:49:36 -0700563 } else if (hcon->tk_valid) {
564 ret = send_pairing_confirm(conn);
Anderson Briglia13b48392011-06-09 18:50:42 -0300565
Anderson Briglia21b8a2b2011-06-09 18:50:46 -0300566 if (ret)
Vinicius Costa Gomes64532ec2011-06-09 18:50:53 -0300567 return SMP_CONFIRM_FAILED;
Brian Gixa68668b2011-08-11 15:49:36 -0700568 } else
569 hcon->cfm_pending = TRUE;
Anderson Briglia21b8a2b2011-06-09 18:50:46 -0300570
Vinicius Costa Gomes64532ec2011-06-09 18:50:53 -0300571
Brian Gixe9ceb522011-09-22 10:46:35 -0700572 mod_timer(&hcon->smp_timer, jiffies + msecs_to_jiffies(SMP_TIMEOUT));
Vinicius Costa Gomesb19d5ce2011-06-14 13:37:41 -0300573
Vinicius Costa Gomes64532ec2011-06-09 18:50:53 -0300574 return 0;
Anderson Briglia13b48392011-06-09 18:50:42 -0300575}
576
Vinicius Costa Gomes64532ec2011-06-09 18:50:53 -0300577static u8 smp_cmd_pairing_random(struct l2cap_conn *conn, struct sk_buff *skb)
Anderson Briglia13b48392011-06-09 18:50:42 -0300578{
Vinicius Costa Gomes735038c2011-06-09 18:50:47 -0300579 struct hci_conn *hcon = conn->hcon;
580 struct crypto_blkcipher *tfm = hcon->hdev->tfm;
Anderson Briglia21b8a2b2011-06-09 18:50:46 -0300581 int ret;
Vinicius Costa Gomesc34e25e2011-06-09 18:50:48 -0300582 u8 key[16], res[16], random[16], confirm[16];
Anderson Briglia21b8a2b2011-06-09 18:50:46 -0300583
584 swap128(skb->data, random);
585 skb_pull(skb, sizeof(random));
586
587 if (conn->hcon->out)
Brian Gixa68668b2011-08-11 15:49:36 -0700588 ret = smp_c1(tfm, hcon->tk, random, hcon->preq, hcon->prsp, 0,
589 conn->src, hcon->dst_type, conn->dst,
Anderson Briglia21b8a2b2011-06-09 18:50:46 -0300590 res);
591 else
Brian Gixa68668b2011-08-11 15:49:36 -0700592 ret = smp_c1(tfm, hcon->tk, random, hcon->preq, hcon->prsp,
593 hcon->dst_type, conn->dst, 0, conn->src,
Anderson Briglia21b8a2b2011-06-09 18:50:46 -0300594 res);
595 if (ret)
Vinicius Costa Gomes64532ec2011-06-09 18:50:53 -0300596 return SMP_UNSPECIFIED;
Anderson Briglia13b48392011-06-09 18:50:42 -0300597
598 BT_DBG("conn %p %s", conn, conn->hcon->out ? "master" : "slave");
599
Anderson Briglia21b8a2b2011-06-09 18:50:46 -0300600 swap128(res, confirm);
601
Brian Gixa68668b2011-08-11 15:49:36 -0700602 if (memcmp(hcon->pcnf, confirm, sizeof(hcon->pcnf)) != 0) {
Anderson Briglia21b8a2b2011-06-09 18:50:46 -0300603 BT_ERR("Pairing failed (confirmation values mismatch)");
Vinicius Costa Gomes64532ec2011-06-09 18:50:53 -0300604 return SMP_CONFIRM_FAILED;
Anderson Briglia21b8a2b2011-06-09 18:50:46 -0300605 }
Anderson Briglia13b48392011-06-09 18:50:42 -0300606
607 if (conn->hcon->out) {
Vinicius Costa Gomesf1b45c52011-07-07 18:59:40 -0300608 u8 stk[16], rand[8];
Vinicius Costa Gomes735038c2011-06-09 18:50:47 -0300609 __le16 ediv;
Vinicius Costa Gomes397d9ae2011-06-14 13:37:42 -0300610
Vinicius Costa Gomes735038c2011-06-09 18:50:47 -0300611 memset(rand, 0, sizeof(rand));
612 ediv = 0;
Vinicius Costa Gomesf1b45c52011-07-07 18:59:40 -0300613
Brian Gixa68668b2011-08-11 15:49:36 -0700614 smp_s1(tfm, hcon->tk, random, hcon->prnd, key);
Vinicius Costa Gomesf1b45c52011-07-07 18:59:40 -0300615 swap128(key, stk);
616
Brian Gixa68668b2011-08-11 15:49:36 -0700617 memset(stk + hcon->smp_key_size, 0,
618 SMP_MAX_ENC_KEY_SIZE - hcon->smp_key_size);
Vinicius Costa Gomesf1b45c52011-07-07 18:59:40 -0300619
620 hci_le_start_enc(hcon, ediv, rand, stk);
Brian Gixa68668b2011-08-11 15:49:36 -0700621 hcon->enc_key_size = hcon->smp_key_size;
Anderson Briglia21b8a2b2011-06-09 18:50:46 -0300622 } else {
Vinicius Costa Gomesf1b45c52011-07-07 18:59:40 -0300623 u8 stk[16], r[16], rand[8];
624 __le16 ediv;
625
626 memset(rand, 0, sizeof(rand));
627 ediv = 0;
Anderson Briglia21b8a2b2011-06-09 18:50:46 -0300628
Brian Gixa68668b2011-08-11 15:49:36 -0700629 swap128(hcon->prnd, r);
Anderson Briglia21b8a2b2011-06-09 18:50:46 -0300630 smp_send_cmd(conn, SMP_CMD_PAIRING_RANDOM, sizeof(r), r);
631
Brian Gixa68668b2011-08-11 15:49:36 -0700632 smp_s1(tfm, hcon->tk, hcon->prnd, random, key);
Vinicius Costa Gomesf1b45c52011-07-07 18:59:40 -0300633 swap128(key, stk);
Vinicius Costa Gomes397d9ae2011-06-14 13:37:42 -0300634
Brian Gixa68668b2011-08-11 15:49:36 -0700635 memset(stk + hcon->smp_key_size, 0,
636 SMP_MAX_ENC_KEY_SIZE - hcon->smp_key_size);
Vinicius Costa Gomesf1b45c52011-07-07 18:59:40 -0300637
Brian Gixa68668b2011-08-11 15:49:36 -0700638 hci_add_ltk(conn->hcon->hdev, 0, conn->dst, hcon->smp_key_size,
639 hcon->auth, ediv, rand, stk);
Anderson Briglia13b48392011-06-09 18:50:42 -0300640 }
Vinicius Costa Gomes64532ec2011-06-09 18:50:53 -0300641
642 return 0;
Anderson Briglia13b48392011-06-09 18:50:42 -0300643}
644
Vinicius Costa Gomes64532ec2011-06-09 18:50:53 -0300645static u8 smp_cmd_security_req(struct l2cap_conn *conn, struct sk_buff *skb)
Anderson Briglia13b48392011-06-09 18:50:42 -0300646{
Brian Gixa68668b2011-08-11 15:49:36 -0700647 struct hci_conn *hcon = conn->hcon;
Anderson Briglia13b48392011-06-09 18:50:42 -0300648 struct smp_cmd_security_req *rp = (void *) skb->data;
649 struct smp_cmd_pairing cp;
Brian Gixa68668b2011-08-11 15:49:36 -0700650 struct link_key *key;
Anderson Briglia13b48392011-06-09 18:50:42 -0300651
652 BT_DBG("conn %p", conn);
653
Vinicius Costa Gomesa5474a82011-01-26 21:42:57 -0300654 if (test_bit(HCI_CONN_ENCRYPT_PEND, &hcon->pend))
Vinicius Costa Gomes64532ec2011-06-09 18:50:53 -0300655 return 0;
Vinicius Costa Gomesa5474a82011-01-26 21:42:57 -0300656
Brian Gixa68668b2011-08-11 15:49:36 -0700657 key = hci_find_link_key_type(hcon->hdev, conn->dst, KEY_TYPE_LTK);
658 if (key && ((key->auth & SMP_AUTH_MITM) ||
659 !(rp->auth_req & SMP_AUTH_MITM))) {
660 struct key_master_id *master = (void *) key->data;
661
662 hci_le_start_enc(hcon, master->ediv, master->rand,
663 key->val);
664 hcon->enc_key_size = key->pin_len;
665
666 hcon->sec_req = TRUE;
667 hcon->sec_level = authreq_to_seclevel(rp->auth_req);
668
669 return 0;
670 }
671
672 hcon->sec_req = FALSE;
673
Anderson Briglia13b48392011-06-09 18:50:42 -0300674 skb_pull(skb, sizeof(*rp));
Anderson Briglia13b48392011-06-09 18:50:42 -0300675
Vinicius Costa Gomes64532ec2011-06-09 18:50:53 -0300676 memset(&cp, 0, sizeof(cp));
Vinicius Costa Gomes10daf972011-07-07 18:59:38 -0300677 build_pairing_cmd(conn, &cp, NULL, rp->auth_req);
Anderson Briglia13b48392011-06-09 18:50:42 -0300678
Brian Gixa68668b2011-08-11 15:49:36 -0700679 hcon->preq[0] = SMP_CMD_PAIRING_REQ;
680 memcpy(&hcon->preq[1], &cp, sizeof(cp));
Anderson Brigliac8e856e2011-06-09 18:50:45 -0300681
Anderson Briglia13b48392011-06-09 18:50:42 -0300682 smp_send_cmd(conn, SMP_CMD_PAIRING_REQ, sizeof(cp), &cp);
Vinicius Costa Gomesa5474a82011-01-26 21:42:57 -0300683
Brian Gixe9ceb522011-09-22 10:46:35 -0700684 mod_timer(&hcon->smp_timer, jiffies + msecs_to_jiffies(SMP_TIMEOUT));
Vinicius Costa Gomesb19d5ce2011-06-14 13:37:41 -0300685
Vinicius Costa Gomesa5474a82011-01-26 21:42:57 -0300686 set_bit(HCI_CONN_ENCRYPT_PEND, &hcon->pend);
Vinicius Costa Gomesa5474a82011-01-26 21:42:57 -0300687
Vinicius Costa Gomes64532ec2011-06-09 18:50:53 -0300688 return 0;
Anderson Briglia13b48392011-06-09 18:50:42 -0300689}
690
Anderson Briglia133e14c2011-06-09 18:50:40 -0300691int smp_conn_security(struct l2cap_conn *conn, __u8 sec_level)
692{
Vinicius Costa Gomes09fabbc2011-06-09 18:50:43 -0300693 struct hci_conn *hcon = conn->hcon;
Anderson Briglia133e14c2011-06-09 18:50:40 -0300694 __u8 authreq;
695
Vinicius Costa Gomes09fabbc2011-06-09 18:50:43 -0300696 BT_DBG("conn %p hcon %p level 0x%2.2x", conn, hcon, sec_level);
697
Brian Gixa68668b2011-08-11 15:49:36 -0700698 if (IS_ERR(hcon->hdev->tfm)) {
699 BT_DBG("IS_ERR");
Vinicius Costa Gomes09fabbc2011-06-09 18:50:43 -0300700 return 1;
Brian Gixa68668b2011-08-11 15:49:36 -0700701 }
Anderson Briglia133e14c2011-06-09 18:50:40 -0300702
Brian Gixa68668b2011-08-11 15:49:36 -0700703 if (test_bit(HCI_CONN_ENCRYPT_PEND, &hcon->pend)) {
704 BT_DBG("HCI_CONN_ENCRYPT_PEND");
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700705 return -EINPROGRESS;
Brian Gixa68668b2011-08-11 15:49:36 -0700706 }
Anderson Briglia133e14c2011-06-09 18:50:40 -0300707
Brian Gixa68668b2011-08-11 15:49:36 -0700708 if (sec_level == BT_SECURITY_LOW) {
709 BT_DBG("BT_SECURITY_LOW");
Anderson Briglia133e14c2011-06-09 18:50:40 -0300710 return 1;
Brian Gixa68668b2011-08-11 15:49:36 -0700711 }
Vinicius Costa Gomesa5474a82011-01-26 21:42:57 -0300712
Brian Gixa68668b2011-08-11 15:49:36 -0700713 if (hcon->sec_level > sec_level) {
714 BT_DBG("hcon->sec_level > sec_level");
Vinicius Costa Gomesa5474a82011-01-26 21:42:57 -0300715 return 1;
Brian Gixa68668b2011-08-11 15:49:36 -0700716 }
Vinicius Costa Gomesa5474a82011-01-26 21:42:57 -0300717
718 authreq = seclevel_to_authreq(sec_level);
Anderson Briglia133e14c2011-06-09 18:50:40 -0300719
Brian Gixa68668b2011-08-11 15:49:36 -0700720 BT_ERR("conn = %p, sec: %d", conn, sec_level);
721 hcon->smp_conn = conn;
722 hcon->sec_level = sec_level;
723
724 if ((hcon->link_mode & HCI_LM_MASTER) && !hcon->sec_req) {
Vinicius Costa Gomes5d873ca2011-07-07 18:59:41 -0300725 struct link_key *key;
726
727 key = hci_find_link_key_type(hcon->hdev, conn->dst,
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700728 KEY_TYPE_LTK);
Vinicius Costa Gomes5d873ca2011-07-07 18:59:41 -0300729 if (key) {
730 struct key_master_id *master = (void *) key->data;
731
732 hci_le_start_enc(hcon, master->ediv, master->rand,
733 key->val);
Vinicius Costa Gomes1fa2de32011-07-08 18:31:45 -0300734 hcon->enc_key_size = key->pin_len;
735
Brian Gixa68668b2011-08-11 15:49:36 -0700736 hcon->sec_req = TRUE;
737
Vinicius Costa Gomes5d873ca2011-07-07 18:59:41 -0300738 goto done;
739 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700740 }
741
Brian Gixa68668b2011-08-11 15:49:36 -0700742 hcon->sec_req = FALSE;
743
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700744 if (hcon->link_mode & HCI_LM_MASTER) {
745 struct smp_cmd_pairing cp;
Anderson Brigliac8e856e2011-06-09 18:50:45 -0300746
Vinicius Costa Gomes10daf972011-07-07 18:59:38 -0300747 build_pairing_cmd(conn, &cp, NULL, authreq);
Brian Gixa68668b2011-08-11 15:49:36 -0700748 hcon->preq[0] = SMP_CMD_PAIRING_REQ;
749 memcpy(&hcon->preq[1], &cp, sizeof(cp));
Anderson Brigliac8e856e2011-06-09 18:50:45 -0300750
Brian Gixe9ceb522011-09-22 10:46:35 -0700751 mod_timer(&hcon->smp_timer, jiffies +
Vinicius Costa Gomesb19d5ce2011-06-14 13:37:41 -0300752 msecs_to_jiffies(SMP_TIMEOUT));
753
Anderson Briglia133e14c2011-06-09 18:50:40 -0300754 smp_send_cmd(conn, SMP_CMD_PAIRING_REQ, sizeof(cp), &cp);
755 } else {
756 struct smp_cmd_security_req cp;
757 cp.auth_req = authreq;
758 smp_send_cmd(conn, SMP_CMD_SECURITY_REQ, sizeof(cp), &cp);
759 }
760
Vinicius Costa Gomes5d873ca2011-07-07 18:59:41 -0300761done:
Vinicius Costa Gomesa5474a82011-01-26 21:42:57 -0300762 hcon->pending_sec_level = sec_level;
763 set_bit(HCI_CONN_ENCRYPT_PEND, &hcon->pend);
764
Anderson Briglia133e14c2011-06-09 18:50:40 -0300765 return 0;
766}
767
Vinicius Costa Gomesc1d5e1d2011-07-07 18:59:34 -0300768static int smp_cmd_encrypt_info(struct l2cap_conn *conn, struct sk_buff *skb)
769{
Brian Gixa68668b2011-08-11 15:49:36 -0700770 struct hci_conn *hcon = conn->hcon;
Vinicius Costa Gomese56cede2011-07-07 18:59:39 -0300771 struct smp_cmd_encrypt_info *rp = (void *) skb->data;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700772 u8 rand[8];
773 int err;
Vinicius Costa Gomese56cede2011-07-07 18:59:39 -0300774
775 skb_pull(skb, sizeof(*rp));
776
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700777 BT_DBG("conn %p", conn);
778
779 memset(rand, 0, sizeof(rand));
780
Brian Gixa68668b2011-08-11 15:49:36 -0700781 err = hci_add_ltk(hcon->hdev, 0, conn->dst, 0, 0, 0,
782 rand, rp->ltk);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700783 if (err)
784 return SMP_UNSPECIFIED;
Vinicius Costa Gomese56cede2011-07-07 18:59:39 -0300785
Vinicius Costa Gomesc1d5e1d2011-07-07 18:59:34 -0300786 return 0;
787}
788
789static int smp_cmd_master_ident(struct l2cap_conn *conn, struct sk_buff *skb)
790{
Brian Gixa68668b2011-08-11 15:49:36 -0700791 struct hci_conn *hcon = conn->hcon;
Vinicius Costa Gomese56cede2011-07-07 18:59:39 -0300792 struct smp_cmd_master_ident *rp = (void *) skb->data;
Brian Gixa68668b2011-08-11 15:49:36 -0700793 struct smp_cmd_pairing *paircmd = (void *) &hcon->prsp[1];
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700794 struct link_key *key;
Brian Gixa68668b2011-08-11 15:49:36 -0700795 u8 *keydist;
Vinicius Costa Gomesc1d5e1d2011-07-07 18:59:34 -0300796
Vinicius Costa Gomese56cede2011-07-07 18:59:39 -0300797 skb_pull(skb, sizeof(*rp));
798
Brian Gixa68668b2011-08-11 15:49:36 -0700799 key = hci_find_link_key_type(hcon->hdev, conn->dst, KEY_TYPE_LTK);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700800 if (key == NULL)
801 return SMP_UNSPECIFIED;
802
Brian Gixa68668b2011-08-11 15:49:36 -0700803 if (hcon->out)
804 keydist = &paircmd->resp_key_dist;
805 else
806 keydist = &paircmd->init_key_dist;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700807
Brian Gixa68668b2011-08-11 15:49:36 -0700808 BT_DBG("keydist 0x%x", *keydist);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700809
Brian Gixa68668b2011-08-11 15:49:36 -0700810 hci_add_ltk(hcon->hdev, 1, conn->dst, hcon->smp_key_size,
811 hcon->auth, rp->ediv, rp->rand, key->val);
Vinicius Costa Gomesc1d5e1d2011-07-07 18:59:34 -0300812
Brian Gixa68668b2011-08-11 15:49:36 -0700813 *keydist &= ~SMP_DIST_ENC_KEY;
814 if (hcon->out) {
815 if (!(*keydist))
816 smp_distribute_keys(conn, 1);
817 }
Vinicius Costa Gomesc1d5e1d2011-07-07 18:59:34 -0300818
819 return 0;
820}
821
Anderson Briglia133e14c2011-06-09 18:50:40 -0300822int smp_sig_channel(struct l2cap_conn *conn, struct sk_buff *skb)
823{
Brian Gixa68668b2011-08-11 15:49:36 -0700824 struct hci_conn *hcon = conn->hcon;
Anderson Briglia133e14c2011-06-09 18:50:40 -0300825 __u8 code = skb->data[0];
826 __u8 reason;
827 int err = 0;
828
Brian Gixa68668b2011-08-11 15:49:36 -0700829 if (IS_ERR(hcon->hdev->tfm)) {
830 err = PTR_ERR(hcon->hdev->tfm);
Vinicius Costa Gomes09fabbc2011-06-09 18:50:43 -0300831 reason = SMP_PAIRING_NOTSUPP;
Brian Gixa68668b2011-08-11 15:49:36 -0700832 BT_ERR("SMP_PAIRING_NOTSUPP %p", hcon->hdev->tfm);
Vinicius Costa Gomes09fabbc2011-06-09 18:50:43 -0300833 goto done;
834 }
835
Brian Gixa68668b2011-08-11 15:49:36 -0700836 hcon->smp_conn = conn;
Anderson Briglia133e14c2011-06-09 18:50:40 -0300837 skb_pull(skb, sizeof(code));
838
839 switch (code) {
840 case SMP_CMD_PAIRING_REQ:
Vinicius Costa Gomes64532ec2011-06-09 18:50:53 -0300841 reason = smp_cmd_pairing_req(conn, skb);
Anderson Briglia133e14c2011-06-09 18:50:40 -0300842 break;
843
844 case SMP_CMD_PAIRING_FAIL:
Vinicius Costa Gomes64532ec2011-06-09 18:50:53 -0300845 reason = 0;
846 err = -EPERM;
Brian Gixe9ceb522011-09-22 10:46:35 -0700847 del_timer(&hcon->smp_timer);
Brian Gix6d5fb8a2011-09-09 14:53:04 -0700848 hci_conn_put(hcon);
Anderson Briglia133e14c2011-06-09 18:50:40 -0300849 break;
850
851 case SMP_CMD_PAIRING_RSP:
Vinicius Costa Gomes64532ec2011-06-09 18:50:53 -0300852 reason = smp_cmd_pairing_rsp(conn, skb);
Anderson Briglia13b48392011-06-09 18:50:42 -0300853 break;
854
855 case SMP_CMD_SECURITY_REQ:
Vinicius Costa Gomes64532ec2011-06-09 18:50:53 -0300856 reason = smp_cmd_security_req(conn, skb);
Anderson Briglia13b48392011-06-09 18:50:42 -0300857 break;
858
Anderson Briglia133e14c2011-06-09 18:50:40 -0300859 case SMP_CMD_PAIRING_CONFIRM:
Vinicius Costa Gomes64532ec2011-06-09 18:50:53 -0300860 reason = smp_cmd_pairing_confirm(conn, skb);
Anderson Briglia13b48392011-06-09 18:50:42 -0300861 break;
862
Anderson Briglia133e14c2011-06-09 18:50:40 -0300863 case SMP_CMD_PAIRING_RANDOM:
Vinicius Costa Gomes64532ec2011-06-09 18:50:53 -0300864 reason = smp_cmd_pairing_random(conn, skb);
Anderson Briglia13b48392011-06-09 18:50:42 -0300865 break;
866
Anderson Briglia133e14c2011-06-09 18:50:40 -0300867 case SMP_CMD_ENCRYPT_INFO:
Vinicius Costa Gomesc1d5e1d2011-07-07 18:59:34 -0300868 reason = smp_cmd_encrypt_info(conn, skb);
869 break;
870
Anderson Briglia133e14c2011-06-09 18:50:40 -0300871 case SMP_CMD_MASTER_IDENT:
Vinicius Costa Gomesc1d5e1d2011-07-07 18:59:34 -0300872 reason = smp_cmd_master_ident(conn, skb);
873 break;
874
Anderson Briglia133e14c2011-06-09 18:50:40 -0300875 case SMP_CMD_IDENT_INFO:
876 case SMP_CMD_IDENT_ADDR_INFO:
877 case SMP_CMD_SIGN_INFO:
Vinicius Costa Gomesc1d5e1d2011-07-07 18:59:34 -0300878 /* Just ignored */
879 reason = 0;
880 break;
881
Anderson Briglia133e14c2011-06-09 18:50:40 -0300882 default:
883 BT_DBG("Unknown command code 0x%2.2x", code);
884
885 reason = SMP_CMD_NOTSUPP;
Vinicius Costa Gomes09fabbc2011-06-09 18:50:43 -0300886 err = -EOPNOTSUPP;
887 goto done;
888 }
889
890done:
Brian Gixa68668b2011-08-11 15:49:36 -0700891 if (reason) {
892 BT_ERR("SMP_CMD_PAIRING_FAIL: %d", reason);
Anderson Briglia133e14c2011-06-09 18:50:40 -0300893 smp_send_cmd(conn, SMP_CMD_PAIRING_FAIL, sizeof(reason),
894 &reason);
Brian Gixe9ceb522011-09-22 10:46:35 -0700895 del_timer(&hcon->smp_timer);
Brian Gix6d5fb8a2011-09-09 14:53:04 -0700896 hci_conn_put(hcon);
Brian Gixa68668b2011-08-11 15:49:36 -0700897 }
Anderson Briglia133e14c2011-06-09 18:50:40 -0300898
899 kfree_skb(skb);
900 return err;
901}
Vinicius Costa Gomesc1d5e1d2011-07-07 18:59:34 -0300902
Brian Gixa68668b2011-08-11 15:49:36 -0700903static int smp_distribute_keys(struct l2cap_conn *conn, __u8 force)
Vinicius Costa Gomesc1d5e1d2011-07-07 18:59:34 -0300904{
Brian Gixa68668b2011-08-11 15:49:36 -0700905 struct hci_conn *hcon = conn->hcon;
Vinicius Costa Gomesc1d5e1d2011-07-07 18:59:34 -0300906 struct smp_cmd_pairing *req, *rsp;
907 __u8 *keydist;
908
909 BT_DBG("conn %p force %d", conn, force);
910
Brian Gixa68668b2011-08-11 15:49:36 -0700911 if (IS_ERR(hcon->hdev->tfm))
912 return PTR_ERR(hcon->hdev->tfm);
Vinicius Costa Gomesc1d5e1d2011-07-07 18:59:34 -0300913
Brian Gixa68668b2011-08-11 15:49:36 -0700914 rsp = (void *) &hcon->prsp[1];
Vinicius Costa Gomesc1d5e1d2011-07-07 18:59:34 -0300915
916 /* The responder sends its keys first */
Brian Gixa68668b2011-08-11 15:49:36 -0700917 if (!force && hcon->out && (rsp->resp_key_dist & 0x07))
Vinicius Costa Gomesc1d5e1d2011-07-07 18:59:34 -0300918 return 0;
919
Brian Gixa68668b2011-08-11 15:49:36 -0700920 req = (void *) &hcon->preq[1];
Vinicius Costa Gomesc1d5e1d2011-07-07 18:59:34 -0300921
Brian Gixa68668b2011-08-11 15:49:36 -0700922 if (hcon->out) {
Vinicius Costa Gomesc1d5e1d2011-07-07 18:59:34 -0300923 keydist = &rsp->init_key_dist;
924 *keydist &= req->init_key_dist;
925 } else {
926 keydist = &rsp->resp_key_dist;
927 *keydist &= req->resp_key_dist;
928 }
929
930
931 BT_DBG("keydist 0x%x", *keydist);
932
933 if (*keydist & SMP_DIST_ENC_KEY) {
934 struct smp_cmd_encrypt_info enc;
935 struct smp_cmd_master_ident ident;
936 __le16 ediv;
937
938 get_random_bytes(enc.ltk, sizeof(enc.ltk));
939 get_random_bytes(&ediv, sizeof(ediv));
940 get_random_bytes(ident.rand, sizeof(ident.rand));
941
942 smp_send_cmd(conn, SMP_CMD_ENCRYPT_INFO, sizeof(enc), &enc);
943
Brian Gixa68668b2011-08-11 15:49:36 -0700944 hci_add_ltk(hcon->hdev, 1, conn->dst, hcon->smp_key_size,
945 hcon->auth, ediv, ident.rand, enc.ltk);
Vinicius Costa Gomese56cede2011-07-07 18:59:39 -0300946
Vinicius Costa Gomesc1d5e1d2011-07-07 18:59:34 -0300947 ident.ediv = cpu_to_le16(ediv);
948
949 smp_send_cmd(conn, SMP_CMD_MASTER_IDENT, sizeof(ident), &ident);
950
951 *keydist &= ~SMP_DIST_ENC_KEY;
952 }
953
954 if (*keydist & SMP_DIST_ID_KEY) {
955 struct smp_cmd_ident_addr_info addrinfo;
956 struct smp_cmd_ident_info idinfo;
957
958 /* Send a dummy key */
959 get_random_bytes(idinfo.irk, sizeof(idinfo.irk));
960
961 smp_send_cmd(conn, SMP_CMD_IDENT_INFO, sizeof(idinfo), &idinfo);
962
963 /* Just public address */
964 memset(&addrinfo, 0, sizeof(addrinfo));
965 bacpy(&addrinfo.bdaddr, conn->src);
966
967 smp_send_cmd(conn, SMP_CMD_IDENT_ADDR_INFO, sizeof(addrinfo),
968 &addrinfo);
969
970 *keydist &= ~SMP_DIST_ID_KEY;
971 }
972
973 if (*keydist & SMP_DIST_SIGN) {
974 struct smp_cmd_sign_info sign;
975
976 /* Send a dummy key */
977 get_random_bytes(sign.csrk, sizeof(sign.csrk));
978
979 smp_send_cmd(conn, SMP_CMD_SIGN_INFO, sizeof(sign), &sign);
980
981 *keydist &= ~SMP_DIST_SIGN;
982 }
983
Brian Gix6d5fb8a2011-09-09 14:53:04 -0700984 if (hcon->out || rsp->resp_key_dist) {
Brian Gixe57c1672011-09-13 12:34:59 -0700985 if (hcon->disconn_cfm_cb)
986 hcon->disconn_cfm_cb(hcon, 0);
Brian Gixe9ceb522011-09-22 10:46:35 -0700987
988 del_timer(&hcon->smp_timer);
Brian Gix6d5fb8a2011-09-09 14:53:04 -0700989 hci_conn_put(hcon);
990 }
Brian Gixa68668b2011-08-11 15:49:36 -0700991
992 return 0;
993}
994
995int smp_link_encrypt_cmplt(struct l2cap_conn *conn, u8 status, u8 encrypt)
996{
997 struct hci_conn *hcon = conn->hcon;
998
999 BT_DBG("smp: %d %d %d", status, encrypt, hcon->sec_req);
1000
1001 if (!status && encrypt && !hcon->sec_req)
1002 smp_distribute_keys(conn, 0);
1003
1004 /* Fall back to Pairing request if failed a Link Security request */
1005 else if (hcon->sec_req && (status || !encrypt))
1006 smp_conn_security(conn, hcon->sec_level);
1007
Vinicius Costa Gomesc1d5e1d2011-07-07 18:59:34 -03001008 return 0;
1009}
Brian Gixe9ceb522011-09-22 10:46:35 -07001010
1011void smp_timeout(unsigned long arg)
1012{
1013 struct l2cap_conn *conn = (void *) arg;
1014 u8 reason = SMP_UNSPECIFIED;
1015
1016 BT_DBG("%p", conn);
1017
1018 smp_send_cmd(conn, SMP_CMD_PAIRING_FAIL, sizeof(reason), &reason);
1019 hci_conn_put(conn->hcon);
1020}