blob: 8943510119a604a0789bb981f7ea3a52c32641db [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 Gix6d5fb8a2011-09-09 14:53:04 -0700440 hci_conn_put(hcon);
441 } else if (hcon->cfm_pending) {
Brian Gixa68668b2011-08-11 15:49:36 -0700442 BT_DBG("send_pairing_confirm");
443 ret = send_pairing_confirm(conn);
444 }
445
446 return ret;
447}
448
Vinicius Costa Gomes64532ec2011-06-09 18:50:53 -0300449static u8 smp_cmd_pairing_req(struct l2cap_conn *conn, struct sk_buff *skb)
Anderson Briglia13b48392011-06-09 18:50:42 -0300450{
Brian Gixa68668b2011-08-11 15:49:36 -0700451 struct hci_conn *hcon = conn->hcon;
Vinicius Costa Gomes397d9ae2011-06-14 13:37:42 -0300452 struct smp_cmd_pairing rsp, *req = (void *) skb->data;
453 u8 key_size;
Brian Gixa68668b2011-08-11 15:49:36 -0700454 u8 auth = SMP_AUTH_NONE;
455 int ret;
Anderson Briglia13b48392011-06-09 18:50:42 -0300456
457 BT_DBG("conn %p", conn);
458
Brian Gixa68668b2011-08-11 15:49:36 -0700459 hcon->preq[0] = SMP_CMD_PAIRING_REQ;
460 memcpy(&hcon->preq[1], req, sizeof(*req));
Vinicius Costa Gomes397d9ae2011-06-14 13:37:42 -0300461 skb_pull(skb, sizeof(*req));
Anderson Briglia13b48392011-06-09 18:50:42 -0300462
Brian Gixa68668b2011-08-11 15:49:36 -0700463 if (req->oob_flag && hcon->oob) {
464 /* By definition, OOB data pairing will have MITM protection */
465 auth = req->auth_req | SMP_AUTH_MITM;
466 } else if (req->auth_req & SMP_AUTH_BONDING) {
467 /* We will attempt MITM for all Bonding attempts */
468 auth = SMP_AUTH_BONDING | SMP_AUTH_MITM;
469 }
Vinicius Costa Gomes64532ec2011-06-09 18:50:53 -0300470
471 /* We didn't start the pairing, so no requirements */
Brian Gixa68668b2011-08-11 15:49:36 -0700472 build_pairing_cmd(conn, req, &rsp, auth);
Vinicius Costa Gomes397d9ae2011-06-14 13:37:42 -0300473
474 key_size = min(req->max_key_size, rsp.max_key_size);
475 if (check_enc_key_size(conn, key_size))
476 return SMP_ENC_KEY_SIZE;
Anderson Briglia13b48392011-06-09 18:50:42 -0300477
Brian Gixa68668b2011-08-11 15:49:36 -0700478 ret = smp_rand(hcon->prnd);
479 if (ret)
480 return SMP_UNSPECIFIED;
Anderson Briglia21b8a2b2011-06-09 18:50:46 -0300481
Brian Gixa68668b2011-08-11 15:49:36 -0700482 /* Request setup of TK */
483 ret = tk_request(conn, req->oob_flag, auth, rsp.io_capability,
484 req->io_capability);
485 if (ret)
486 return SMP_UNSPECIFIED;
487
488 hcon->prsp[0] = SMP_CMD_PAIRING_RSP;
489 memcpy(&hcon->prsp[1], &rsp, sizeof(rsp));
Anderson Brigliac8e856e2011-06-09 18:50:45 -0300490
Vinicius Costa Gomes397d9ae2011-06-14 13:37:42 -0300491 smp_send_cmd(conn, SMP_CMD_PAIRING_RSP, sizeof(rsp), &rsp);
Vinicius Costa Gomes64532ec2011-06-09 18:50:53 -0300492
Vinicius Costa Gomesb19d5ce2011-06-14 13:37:41 -0300493 mod_timer(&conn->security_timer, jiffies +
494 msecs_to_jiffies(SMP_TIMEOUT));
495
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
Vinicius Costa Gomesb19d5ce2011-06-14 13:37:41 -0300572 mod_timer(&conn->security_timer, jiffies +
573 msecs_to_jiffies(SMP_TIMEOUT));
574
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
Vinicius Costa Gomesb19d5ce2011-06-14 13:37:41 -0300685 mod_timer(&conn->security_timer, jiffies +
Brian Gixa68668b2011-08-11 15:49:36 -0700686 msecs_to_jiffies(SMP_TIMEOUT));
Vinicius Costa Gomesb19d5ce2011-06-14 13:37:41 -0300687
Vinicius Costa Gomesa5474a82011-01-26 21:42:57 -0300688 set_bit(HCI_CONN_ENCRYPT_PEND, &hcon->pend);
Vinicius Costa Gomesa5474a82011-01-26 21:42:57 -0300689
Vinicius Costa Gomes64532ec2011-06-09 18:50:53 -0300690 return 0;
Anderson Briglia13b48392011-06-09 18:50:42 -0300691}
692
Anderson Briglia133e14c2011-06-09 18:50:40 -0300693int smp_conn_security(struct l2cap_conn *conn, __u8 sec_level)
694{
Vinicius Costa Gomes09fabbc2011-06-09 18:50:43 -0300695 struct hci_conn *hcon = conn->hcon;
Anderson Briglia133e14c2011-06-09 18:50:40 -0300696 __u8 authreq;
697
Vinicius Costa Gomes09fabbc2011-06-09 18:50:43 -0300698 BT_DBG("conn %p hcon %p level 0x%2.2x", conn, hcon, sec_level);
699
Brian Gixa68668b2011-08-11 15:49:36 -0700700 if (IS_ERR(hcon->hdev->tfm)) {
701 BT_DBG("IS_ERR");
Vinicius Costa Gomes09fabbc2011-06-09 18:50:43 -0300702 return 1;
Brian Gixa68668b2011-08-11 15:49:36 -0700703 }
Anderson Briglia133e14c2011-06-09 18:50:40 -0300704
Brian Gixa68668b2011-08-11 15:49:36 -0700705 if (test_bit(HCI_CONN_ENCRYPT_PEND, &hcon->pend)) {
706 BT_DBG("HCI_CONN_ENCRYPT_PEND");
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700707 return -EINPROGRESS;
Brian Gixa68668b2011-08-11 15:49:36 -0700708 }
Anderson Briglia133e14c2011-06-09 18:50:40 -0300709
Brian Gixa68668b2011-08-11 15:49:36 -0700710 if (sec_level == BT_SECURITY_LOW) {
711 BT_DBG("BT_SECURITY_LOW");
Anderson Briglia133e14c2011-06-09 18:50:40 -0300712 return 1;
Brian Gixa68668b2011-08-11 15:49:36 -0700713 }
Vinicius Costa Gomesa5474a82011-01-26 21:42:57 -0300714
Brian Gixa68668b2011-08-11 15:49:36 -0700715 if (hcon->sec_level > sec_level) {
716 BT_DBG("hcon->sec_level > sec_level");
Vinicius Costa Gomesa5474a82011-01-26 21:42:57 -0300717 return 1;
Brian Gixa68668b2011-08-11 15:49:36 -0700718 }
Vinicius Costa Gomesa5474a82011-01-26 21:42:57 -0300719
720 authreq = seclevel_to_authreq(sec_level);
Anderson Briglia133e14c2011-06-09 18:50:40 -0300721
Brian Gixa68668b2011-08-11 15:49:36 -0700722 BT_ERR("conn = %p, sec: %d", conn, sec_level);
723 hcon->smp_conn = conn;
724 hcon->sec_level = sec_level;
725
726 if ((hcon->link_mode & HCI_LM_MASTER) && !hcon->sec_req) {
Vinicius Costa Gomes5d873ca2011-07-07 18:59:41 -0300727 struct link_key *key;
728
729 key = hci_find_link_key_type(hcon->hdev, conn->dst,
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700730 KEY_TYPE_LTK);
Vinicius Costa Gomes5d873ca2011-07-07 18:59:41 -0300731 if (key) {
732 struct key_master_id *master = (void *) key->data;
733
734 hci_le_start_enc(hcon, master->ediv, master->rand,
735 key->val);
Vinicius Costa Gomes1fa2de32011-07-08 18:31:45 -0300736 hcon->enc_key_size = key->pin_len;
737
Brian Gixa68668b2011-08-11 15:49:36 -0700738 hcon->sec_req = TRUE;
739
Vinicius Costa Gomes5d873ca2011-07-07 18:59:41 -0300740 goto done;
741 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700742 }
743
Brian Gixa68668b2011-08-11 15:49:36 -0700744 hcon->sec_req = FALSE;
745
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700746 if (hcon->link_mode & HCI_LM_MASTER) {
747 struct smp_cmd_pairing cp;
Anderson Brigliac8e856e2011-06-09 18:50:45 -0300748
Vinicius Costa Gomes10daf972011-07-07 18:59:38 -0300749 build_pairing_cmd(conn, &cp, NULL, authreq);
Brian Gixa68668b2011-08-11 15:49:36 -0700750 hcon->preq[0] = SMP_CMD_PAIRING_REQ;
751 memcpy(&hcon->preq[1], &cp, sizeof(cp));
Anderson Brigliac8e856e2011-06-09 18:50:45 -0300752
Vinicius Costa Gomesb19d5ce2011-06-14 13:37:41 -0300753 mod_timer(&conn->security_timer, jiffies +
754 msecs_to_jiffies(SMP_TIMEOUT));
755
Anderson Briglia133e14c2011-06-09 18:50:40 -0300756 smp_send_cmd(conn, SMP_CMD_PAIRING_REQ, sizeof(cp), &cp);
757 } else {
758 struct smp_cmd_security_req cp;
759 cp.auth_req = authreq;
760 smp_send_cmd(conn, SMP_CMD_SECURITY_REQ, sizeof(cp), &cp);
761 }
762
Vinicius Costa Gomes5d873ca2011-07-07 18:59:41 -0300763done:
Vinicius Costa Gomesa5474a82011-01-26 21:42:57 -0300764 hcon->pending_sec_level = sec_level;
765 set_bit(HCI_CONN_ENCRYPT_PEND, &hcon->pend);
766
Anderson Briglia133e14c2011-06-09 18:50:40 -0300767 return 0;
768}
769
Vinicius Costa Gomesc1d5e1d2011-07-07 18:59:34 -0300770static int smp_cmd_encrypt_info(struct l2cap_conn *conn, struct sk_buff *skb)
771{
Brian Gixa68668b2011-08-11 15:49:36 -0700772 struct hci_conn *hcon = conn->hcon;
Vinicius Costa Gomese56cede2011-07-07 18:59:39 -0300773 struct smp_cmd_encrypt_info *rp = (void *) skb->data;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700774 u8 rand[8];
775 int err;
Vinicius Costa Gomese56cede2011-07-07 18:59:39 -0300776
777 skb_pull(skb, sizeof(*rp));
778
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700779 BT_DBG("conn %p", conn);
780
781 memset(rand, 0, sizeof(rand));
782
Brian Gixa68668b2011-08-11 15:49:36 -0700783 err = hci_add_ltk(hcon->hdev, 0, conn->dst, 0, 0, 0,
784 rand, rp->ltk);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700785 if (err)
786 return SMP_UNSPECIFIED;
Vinicius Costa Gomese56cede2011-07-07 18:59:39 -0300787
Vinicius Costa Gomesc1d5e1d2011-07-07 18:59:34 -0300788 return 0;
789}
790
791static int smp_cmd_master_ident(struct l2cap_conn *conn, struct sk_buff *skb)
792{
Brian Gixa68668b2011-08-11 15:49:36 -0700793 struct hci_conn *hcon = conn->hcon;
Vinicius Costa Gomese56cede2011-07-07 18:59:39 -0300794 struct smp_cmd_master_ident *rp = (void *) skb->data;
Brian Gixa68668b2011-08-11 15:49:36 -0700795 struct smp_cmd_pairing *paircmd = (void *) &hcon->prsp[1];
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700796 struct link_key *key;
Brian Gixa68668b2011-08-11 15:49:36 -0700797 u8 *keydist;
Vinicius Costa Gomesc1d5e1d2011-07-07 18:59:34 -0300798
Vinicius Costa Gomese56cede2011-07-07 18:59:39 -0300799 skb_pull(skb, sizeof(*rp));
800
Brian Gixa68668b2011-08-11 15:49:36 -0700801 key = hci_find_link_key_type(hcon->hdev, conn->dst, KEY_TYPE_LTK);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700802 if (key == NULL)
803 return SMP_UNSPECIFIED;
804
Brian Gixa68668b2011-08-11 15:49:36 -0700805 if (hcon->out)
806 keydist = &paircmd->resp_key_dist;
807 else
808 keydist = &paircmd->init_key_dist;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700809
Brian Gixa68668b2011-08-11 15:49:36 -0700810 BT_DBG("keydist 0x%x", *keydist);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700811
Brian Gixa68668b2011-08-11 15:49:36 -0700812 hci_add_ltk(hcon->hdev, 1, conn->dst, hcon->smp_key_size,
813 hcon->auth, rp->ediv, rp->rand, key->val);
Vinicius Costa Gomesc1d5e1d2011-07-07 18:59:34 -0300814
Brian Gixa68668b2011-08-11 15:49:36 -0700815 *keydist &= ~SMP_DIST_ENC_KEY;
816 if (hcon->out) {
817 if (!(*keydist))
818 smp_distribute_keys(conn, 1);
819 }
Vinicius Costa Gomesc1d5e1d2011-07-07 18:59:34 -0300820
821 return 0;
822}
823
Anderson Briglia133e14c2011-06-09 18:50:40 -0300824int smp_sig_channel(struct l2cap_conn *conn, struct sk_buff *skb)
825{
Brian Gixa68668b2011-08-11 15:49:36 -0700826 struct hci_conn *hcon = conn->hcon;
Anderson Briglia133e14c2011-06-09 18:50:40 -0300827 __u8 code = skb->data[0];
828 __u8 reason;
829 int err = 0;
830
Brian Gixa68668b2011-08-11 15:49:36 -0700831 if (IS_ERR(hcon->hdev->tfm)) {
832 err = PTR_ERR(hcon->hdev->tfm);
Vinicius Costa Gomes09fabbc2011-06-09 18:50:43 -0300833 reason = SMP_PAIRING_NOTSUPP;
Brian Gixa68668b2011-08-11 15:49:36 -0700834 BT_ERR("SMP_PAIRING_NOTSUPP %p", hcon->hdev->tfm);
Vinicius Costa Gomes09fabbc2011-06-09 18:50:43 -0300835 goto done;
836 }
837
Brian Gixa68668b2011-08-11 15:49:36 -0700838 hcon->smp_conn = conn;
Anderson Briglia133e14c2011-06-09 18:50:40 -0300839 skb_pull(skb, sizeof(code));
840
841 switch (code) {
842 case SMP_CMD_PAIRING_REQ:
Vinicius Costa Gomes64532ec2011-06-09 18:50:53 -0300843 reason = smp_cmd_pairing_req(conn, skb);
Anderson Briglia133e14c2011-06-09 18:50:40 -0300844 break;
845
846 case SMP_CMD_PAIRING_FAIL:
Vinicius Costa Gomes64532ec2011-06-09 18:50:53 -0300847 reason = 0;
848 err = -EPERM;
Brian Gix6d5fb8a2011-09-09 14:53:04 -0700849 hci_conn_put(hcon);
Anderson Briglia133e14c2011-06-09 18:50:40 -0300850 break;
851
852 case SMP_CMD_PAIRING_RSP:
Vinicius Costa Gomes64532ec2011-06-09 18:50:53 -0300853 reason = smp_cmd_pairing_rsp(conn, skb);
Anderson Briglia13b48392011-06-09 18:50:42 -0300854 break;
855
856 case SMP_CMD_SECURITY_REQ:
Vinicius Costa Gomes64532ec2011-06-09 18:50:53 -0300857 reason = smp_cmd_security_req(conn, skb);
Anderson Briglia13b48392011-06-09 18:50:42 -0300858 break;
859
Anderson Briglia133e14c2011-06-09 18:50:40 -0300860 case SMP_CMD_PAIRING_CONFIRM:
Vinicius Costa Gomes64532ec2011-06-09 18:50:53 -0300861 reason = smp_cmd_pairing_confirm(conn, skb);
Anderson Briglia13b48392011-06-09 18:50:42 -0300862 break;
863
Anderson Briglia133e14c2011-06-09 18:50:40 -0300864 case SMP_CMD_PAIRING_RANDOM:
Vinicius Costa Gomes64532ec2011-06-09 18:50:53 -0300865 reason = smp_cmd_pairing_random(conn, skb);
Anderson Briglia13b48392011-06-09 18:50:42 -0300866 break;
867
Anderson Briglia133e14c2011-06-09 18:50:40 -0300868 case SMP_CMD_ENCRYPT_INFO:
Vinicius Costa Gomesc1d5e1d2011-07-07 18:59:34 -0300869 reason = smp_cmd_encrypt_info(conn, skb);
870 break;
871
Anderson Briglia133e14c2011-06-09 18:50:40 -0300872 case SMP_CMD_MASTER_IDENT:
Vinicius Costa Gomesc1d5e1d2011-07-07 18:59:34 -0300873 reason = smp_cmd_master_ident(conn, skb);
874 break;
875
Anderson Briglia133e14c2011-06-09 18:50:40 -0300876 case SMP_CMD_IDENT_INFO:
877 case SMP_CMD_IDENT_ADDR_INFO:
878 case SMP_CMD_SIGN_INFO:
Vinicius Costa Gomesc1d5e1d2011-07-07 18:59:34 -0300879 /* Just ignored */
880 reason = 0;
881 break;
882
Anderson Briglia133e14c2011-06-09 18:50:40 -0300883 default:
884 BT_DBG("Unknown command code 0x%2.2x", code);
885
886 reason = SMP_CMD_NOTSUPP;
Vinicius Costa Gomes09fabbc2011-06-09 18:50:43 -0300887 err = -EOPNOTSUPP;
888 goto done;
889 }
890
891done:
Brian Gixa68668b2011-08-11 15:49:36 -0700892 if (reason) {
893 BT_ERR("SMP_CMD_PAIRING_FAIL: %d", reason);
Anderson Briglia133e14c2011-06-09 18:50:40 -0300894 smp_send_cmd(conn, SMP_CMD_PAIRING_FAIL, sizeof(reason),
895 &reason);
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 Gix6d5fb8a2011-09-09 14:53:04 -0700987 hci_conn_put(hcon);
988 }
Brian Gixa68668b2011-08-11 15:49:36 -0700989
990 return 0;
991}
992
993int smp_link_encrypt_cmplt(struct l2cap_conn *conn, u8 status, u8 encrypt)
994{
995 struct hci_conn *hcon = conn->hcon;
996
997 BT_DBG("smp: %d %d %d", status, encrypt, hcon->sec_req);
998
999 if (!status && encrypt && !hcon->sec_req)
1000 smp_distribute_keys(conn, 0);
1001
1002 /* Fall back to Pairing request if failed a Link Security request */
1003 else if (hcon->sec_req && (status || !encrypt))
1004 smp_conn_security(conn, hcon->sec_level);
1005
Vinicius Costa Gomesc1d5e1d2011-07-07 18:59:34 -03001006 return 0;
1007}