blob: 31fc4dcf572f8dd74fa97b18835676e049911635 [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 Gix7f7e16c2011-11-01 16:27:25 -070034#define SMP_MIN_CONN_INTERVAL 40 /* 50ms (40 * 1.25ms) */
35#define SMP_MAX_CONN_INTERVAL 56 /* 70ms (56 * 1.25ms) */
36#define SMP_MAX_CONN_LATENCY 0 /* 0ms (0 * 1.25ms) */
37#define SMP_SUPERVISION_TIMEOUT 500 /* 5 seconds (500 * 10ms) */
38
Brian Gixa68668b2011-08-11 15:49:36 -070039#ifndef FALSE
40#define FALSE 0
41#define TRUE (!FALSE)
42#endif
43
44static int smp_distribute_keys(struct l2cap_conn *conn, __u8 force);
45
Anderson Briglia8e7a3c52011-06-09 18:50:44 -030046static inline void swap128(u8 src[16], u8 dst[16])
47{
48 int i;
49 for (i = 0; i < 16; i++)
50 dst[15 - i] = src[i];
51}
52
53static inline void swap56(u8 src[7], u8 dst[7])
54{
55 int i;
56 for (i = 0; i < 7; i++)
57 dst[6 - i] = src[i];
58}
59
60static int smp_e(struct crypto_blkcipher *tfm, const u8 *k, u8 *r)
61{
62 struct blkcipher_desc desc;
63 struct scatterlist sg;
64 int err, iv_len;
65 unsigned char iv[128];
66
67 if (tfm == NULL) {
68 BT_ERR("tfm %p", tfm);
69 return -EINVAL;
70 }
71
72 desc.tfm = tfm;
73 desc.flags = 0;
74
75 err = crypto_blkcipher_setkey(tfm, k, 16);
76 if (err) {
77 BT_ERR("cipher setkey failed: %d", err);
78 return err;
79 }
80
81 sg_init_one(&sg, r, 16);
82
83 iv_len = crypto_blkcipher_ivsize(tfm);
84 if (iv_len) {
85 memset(&iv, 0xff, iv_len);
86 crypto_blkcipher_set_iv(tfm, iv, iv_len);
87 }
88
89 err = crypto_blkcipher_encrypt(&desc, &sg, &sg, 16);
90 if (err)
91 BT_ERR("Encrypt data error %d", err);
92
93 return err;
94}
95
96static int smp_c1(struct crypto_blkcipher *tfm, u8 k[16], u8 r[16],
97 u8 preq[7], u8 pres[7], u8 _iat, bdaddr_t *ia,
98 u8 _rat, bdaddr_t *ra, u8 res[16])
99{
100 u8 p1[16], p2[16];
101 int err;
102
103 memset(p1, 0, 16);
104
105 /* p1 = pres || preq || _rat || _iat */
106 swap56(pres, p1);
107 swap56(preq, p1 + 7);
108 p1[14] = _rat;
109 p1[15] = _iat;
110
111 memset(p2, 0, 16);
112
113 /* p2 = padding || ia || ra */
114 baswap((bdaddr_t *) (p2 + 4), ia);
115 baswap((bdaddr_t *) (p2 + 10), ra);
116
117 /* res = r XOR p1 */
118 u128_xor((u128 *) res, (u128 *) r, (u128 *) p1);
119
120 /* res = e(k, res) */
121 err = smp_e(tfm, k, res);
122 if (err) {
123 BT_ERR("Encrypt data error");
124 return err;
125 }
126
127 /* res = res XOR p2 */
128 u128_xor((u128 *) res, (u128 *) res, (u128 *) p2);
129
130 /* res = e(k, res) */
131 err = smp_e(tfm, k, res);
132 if (err)
133 BT_ERR("Encrypt data error");
134
135 return err;
136}
137
138static int smp_s1(struct crypto_blkcipher *tfm, u8 k[16],
139 u8 r1[16], u8 r2[16], u8 _r[16])
140{
141 int err;
142
143 /* Just least significant octets from r1 and r2 are considered */
144 memcpy(_r, r1 + 8, 8);
145 memcpy(_r + 8, r2 + 8, 8);
146
147 err = smp_e(tfm, k, _r);
148 if (err)
149 BT_ERR("Encrypt data error");
150
151 return err;
152}
153
154static int smp_rand(u8 *buf)
155{
156 get_random_bytes(buf, 16);
157
158 return 0;
159}
Anderson Briglia133e14c2011-06-09 18:50:40 -0300160
161static struct sk_buff *smp_build_cmd(struct l2cap_conn *conn, u8 code,
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700162 u16 dlen, void *data)
Anderson Briglia133e14c2011-06-09 18:50:40 -0300163{
164 struct sk_buff *skb;
165 struct l2cap_hdr *lh;
166 int len;
167
168 len = L2CAP_HDR_SIZE + sizeof(code) + dlen;
169
170 if (len > conn->mtu)
171 return NULL;
172
173 skb = bt_skb_alloc(len, GFP_ATOMIC);
174 if (!skb)
175 return NULL;
176
177 lh = (struct l2cap_hdr *) skb_put(skb, L2CAP_HDR_SIZE);
178 lh->len = cpu_to_le16(sizeof(code) + dlen);
179 lh->cid = cpu_to_le16(L2CAP_CID_SMP);
180
181 memcpy(skb_put(skb, sizeof(code)), &code, sizeof(code));
182
183 memcpy(skb_put(skb, dlen), data, dlen);
184
185 return skb;
186}
187
188static void smp_send_cmd(struct l2cap_conn *conn, u8 code, u16 len, void *data)
189{
190 struct sk_buff *skb = smp_build_cmd(conn, code, len, data);
191
192 BT_DBG("code 0x%2.2x", code);
193
194 if (!skb)
195 return;
196
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700197 hci_send_acl(conn->hcon, NULL, skb, 0);
Anderson Briglia133e14c2011-06-09 18:50:40 -0300198}
199
Brian Gixa68668b2011-08-11 15:49:36 -0700200static __u8 authreq_to_seclevel(__u8 authreq)
201{
202 if (authreq & SMP_AUTH_MITM)
203 return BT_SECURITY_HIGH;
204 else if (authreq & SMP_AUTH_BONDING)
205 return BT_SECURITY_MEDIUM;
206 else
207 return BT_SECURITY_LOW;
208}
209
Vinicius Costa Gomes64532ec2011-06-09 18:50:53 -0300210static __u8 seclevel_to_authreq(__u8 level)
211{
212 switch (level) {
213 case BT_SECURITY_HIGH:
Brian Gixa68668b2011-08-11 15:49:36 -0700214 return SMP_AUTH_MITM | SMP_AUTH_BONDING;
Vinicius Costa Gomes64532ec2011-06-09 18:50:53 -0300215
216 default:
217 return SMP_AUTH_NONE;
218 }
219}
220
Vinicius Costa Gomes901920a2011-06-09 18:50:52 -0300221static void build_pairing_cmd(struct l2cap_conn *conn,
Vinicius Costa Gomes10daf972011-07-07 18:59:38 -0300222 struct smp_cmd_pairing *req,
223 struct smp_cmd_pairing *rsp,
224 __u8 authreq)
Vinicius Costa Gomes901920a2011-06-09 18:50:52 -0300225{
Brian Gixa68668b2011-08-11 15:49:36 -0700226 struct hci_conn *hcon = conn->hcon;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700227 u8 all_keys = 0;
Brian Gixa68668b2011-08-11 15:49:36 -0700228 u8 dist_keys = 0;
Vinicius Costa Gomes10daf972011-07-07 18:59:38 -0300229
Brian Gixa68668b2011-08-11 15:49:36 -0700230 dist_keys = SMP_DIST_ENC_KEY;
231 authreq |= SMP_AUTH_BONDING;
232
233 BT_DBG("conn->hcon->io_capability:%d", conn->hcon->io_capability);
Vinicius Costa Gomes10daf972011-07-07 18:59:38 -0300234
235 if (rsp == NULL) {
236 req->io_capability = conn->hcon->io_capability;
Brian Gixa68668b2011-08-11 15:49:36 -0700237 req->oob_flag = hcon->oob ? SMP_OOB_PRESENT :
238 SMP_OOB_NOT_PRESENT;
Vinicius Costa Gomes10daf972011-07-07 18:59:38 -0300239 req->max_key_size = SMP_MAX_ENC_KEY_SIZE;
Brian Gixa68668b2011-08-11 15:49:36 -0700240 req->init_key_dist = all_keys;
241 req->resp_key_dist = dist_keys;
Vinicius Costa Gomes10daf972011-07-07 18:59:38 -0300242 req->auth_req = authreq;
Brian Gixa68668b2011-08-11 15:49:36 -0700243 BT_DBG("SMP_CMD_PAIRING_REQ %d %d %d %d %2.2x %2.2x",
244 req->io_capability, req->oob_flag,
245 req->auth_req, req->max_key_size,
246 req->init_key_dist, req->resp_key_dist);
Vinicius Costa Gomes10daf972011-07-07 18:59:38 -0300247 return;
248 }
249
Brian Gixa68668b2011-08-11 15:49:36 -0700250 /* Only request OOB if remote AND we support it */
251 if (req->oob_flag)
252 rsp->oob_flag = hcon->oob ? SMP_OOB_PRESENT :
253 SMP_OOB_NOT_PRESENT;
254 else
255 rsp->oob_flag = SMP_OOB_NOT_PRESENT;
256
Vinicius Costa Gomes10daf972011-07-07 18:59:38 -0300257 rsp->io_capability = conn->hcon->io_capability;
Vinicius Costa Gomes10daf972011-07-07 18:59:38 -0300258 rsp->max_key_size = SMP_MAX_ENC_KEY_SIZE;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700259 rsp->init_key_dist = req->init_key_dist & all_keys;
Vinicius Costa Gomes10daf972011-07-07 18:59:38 -0300260 rsp->resp_key_dist = req->resp_key_dist & dist_keys;
261 rsp->auth_req = authreq;
Brian Gixa68668b2011-08-11 15:49:36 -0700262 BT_DBG("SMP_CMD_PAIRING_RSP %d %d %d %d %2.2x %2.2x",
263 req->io_capability, req->oob_flag, req->auth_req,
264 req->max_key_size, req->init_key_dist,
265 req->resp_key_dist);
Vinicius Costa Gomes901920a2011-06-09 18:50:52 -0300266}
267
Vinicius Costa Gomes397d9ae2011-06-14 13:37:42 -0300268static u8 check_enc_key_size(struct l2cap_conn *conn, __u8 max_key_size)
269{
Brian Gixa68668b2011-08-11 15:49:36 -0700270 struct hci_conn *hcon = conn->hcon;
271
Vinicius Costa Gomes397d9ae2011-06-14 13:37:42 -0300272 if ((max_key_size > SMP_MAX_ENC_KEY_SIZE) ||
273 (max_key_size < SMP_MIN_ENC_KEY_SIZE))
274 return SMP_ENC_KEY_SIZE;
275
Brian Gixa68668b2011-08-11 15:49:36 -0700276 hcon->smp_key_size = max_key_size;
Vinicius Costa Gomes397d9ae2011-06-14 13:37:42 -0300277
278 return 0;
279}
280
Brian Gixa68668b2011-08-11 15:49:36 -0700281#define JUST_WORKS SMP_JUST_WORKS
282#define REQ_PASSKEY SMP_REQ_PASSKEY
283#define CFM_PASSKEY SMP_CFM_PASSKEY
284#define JUST_CFM SMP_JUST_CFM
285#define OVERLAP SMP_OVERLAP
286static const u8 gen_method[5][5] = {
287 {JUST_WORKS, JUST_CFM, REQ_PASSKEY, JUST_WORKS, REQ_PASSKEY},
288 {JUST_WORKS, JUST_CFM, REQ_PASSKEY, JUST_WORKS, REQ_PASSKEY},
289 {CFM_PASSKEY, CFM_PASSKEY, REQ_PASSKEY, JUST_WORKS, CFM_PASSKEY},
290 {JUST_WORKS, JUST_CFM, JUST_WORKS, JUST_WORKS, JUST_CFM},
291 {CFM_PASSKEY, CFM_PASSKEY, REQ_PASSKEY, JUST_WORKS, OVERLAP}
292};
293
294static int tk_request(struct l2cap_conn *conn, u8 remote_oob, u8 auth,
295 u8 local_io, u8 remote_io)
296{
297 struct hci_conn *hcon = conn->hcon;
298 u8 method;
299 u32 passkey = 0;
Brian Gix3dd70172011-09-16 21:38:54 -0700300 int ret = 0;
Brian Gixa68668b2011-08-11 15:49:36 -0700301
302 /* Initialize key to JUST WORKS */
303 memset(hcon->tk, 0, sizeof(hcon->tk));
304 hcon->tk_valid = FALSE;
305 hcon->auth = auth;
306
307 /* By definition, OOB data will be used if both sides have it available
308 */
309 if (remote_oob && hcon->oob) {
310 method = SMP_REQ_OOB;
311 goto agent_request;
312 }
313
314 BT_DBG("tk_request: auth:%d lcl:%d rem:%d", auth, local_io, remote_io);
315
316 /* If neither side wants MITM, use JUST WORKS */
317 /* If either side has unknown io_caps, use JUST_WORKS */
318 if (!(auth & SMP_AUTH_MITM) ||
319 local_io > SMP_IO_KEYBOARD_DISPLAY ||
320 remote_io > SMP_IO_KEYBOARD_DISPLAY) {
321 hcon->auth &= ~SMP_AUTH_MITM;
322 hcon->tk_valid = TRUE;
323 return 0;
324 }
325
326 /* MITM is now officially requested, but not required */
327 /* Determine what we need (if anything) from the agent */
328 method = gen_method[local_io][remote_io];
329
330 BT_DBG("tk_method: %d", method);
331
332 if (method == SMP_JUST_WORKS || method == SMP_JUST_CFM)
333 hcon->auth &= ~SMP_AUTH_MITM;
334
335 /* Don't bother confirming unbonded JUST_WORKS */
336 if (!(auth & SMP_AUTH_BONDING) && method == SMP_JUST_CFM) {
337 hcon->tk_valid = TRUE;
338 return 0;
339 } else if (method == SMP_JUST_WORKS) {
340 hcon->tk_valid = TRUE;
341 return 0;
342 } else if (method == SMP_OVERLAP) {
343 if (hcon->link_mode & HCI_LM_MASTER)
344 method = SMP_CFM_PASSKEY;
345 else
346 method = SMP_REQ_PASSKEY;
347 }
348
349 BT_DBG("tk_method-2: %d", method);
350
351 if (method == SMP_CFM_PASSKEY) {
352 u8 key[16];
353 /* Generate a passkey for display. It is not valid until
354 * confirmed.
355 */
356 memset(key, 0, sizeof(key));
357 get_random_bytes(&passkey, sizeof(passkey));
358 passkey %= 1000000;
359 put_unaligned_le32(passkey, key);
360 swap128(key, hcon->tk);
361 BT_DBG("PassKey: %d", passkey);
362 }
363
364agent_request:
Brian Gix3dd70172011-09-16 21:38:54 -0700365 hci_dev_lock(hcon->hdev);
366
Brian Gixa68668b2011-08-11 15:49:36 -0700367 switch (method) {
368 case SMP_REQ_PASSKEY:
Brian Gix3dd70172011-09-16 21:38:54 -0700369 ret = mgmt_user_confirm_request(hcon->hdev->id,
370 HCI_EV_USER_PASSKEY_REQUEST, conn->dst, 0);
371 break;
Brian Gixa68668b2011-08-11 15:49:36 -0700372 case SMP_CFM_PASSKEY:
373 default:
Brian Gix3dd70172011-09-16 21:38:54 -0700374 ret = mgmt_user_confirm_request(hcon->hdev->id,
375 HCI_EV_USER_CONFIRM_REQUEST, conn->dst, passkey);
376 break;
Brian Gixa68668b2011-08-11 15:49:36 -0700377 }
Brian Gix3dd70172011-09-16 21:38:54 -0700378
379 hci_dev_unlock(hcon->hdev);
380
381 return ret;
Brian Gixa68668b2011-08-11 15:49:36 -0700382}
383
384static int send_pairing_confirm(struct l2cap_conn *conn)
385{
386 struct hci_conn *hcon = conn->hcon;
387 struct crypto_blkcipher *tfm = hcon->hdev->tfm;
388 struct smp_cmd_pairing_confirm cp;
389 int ret;
390 u8 res[16];
391
392 if (conn->hcon->out)
393 ret = smp_c1(tfm, hcon->tk, hcon->prnd, hcon->preq, hcon->prsp,
394 0, conn->src, hcon->dst_type, conn->dst, res);
395 else
396 ret = smp_c1(tfm, hcon->tk, hcon->prnd, hcon->preq, hcon->prsp,
397 hcon->dst_type, conn->dst, 0, conn->src, res);
398
399 if (ret)
400 return SMP_CONFIRM_FAILED;
401
402 swap128(res, cp.confirm_val);
403
404 hcon->cfm_pending = FALSE;
405
406 smp_send_cmd(conn, SMP_CMD_PAIRING_CONFIRM, sizeof(cp), &cp);
407
408 return 0;
409}
410
Brian Gix6d5fb8a2011-09-09 14:53:04 -0700411int le_user_confirm_reply(struct hci_conn *hcon, u16 mgmt_op, void *cp)
Brian Gixa68668b2011-08-11 15:49:36 -0700412{
413 struct mgmt_cp_user_passkey_reply *psk_reply = cp;
Brian Gix6d5fb8a2011-09-09 14:53:04 -0700414 struct l2cap_conn *conn = hcon->smp_conn;
Brian Gixa68668b2011-08-11 15:49:36 -0700415 u8 key[16];
416 u8 reason = 0;
417 int ret = 0;
418
419 BT_DBG("");
420
Brian Gix6d5fb8a2011-09-09 14:53:04 -0700421 hcon->tk_valid = TRUE;
Brian Gixa68668b2011-08-11 15:49:36 -0700422
423 switch (mgmt_op) {
424 case MGMT_OP_USER_CONFIRM_NEG_REPLY:
425 reason = SMP_CONFIRM_FAILED;
426 break;
427 case MGMT_OP_USER_CONFIRM_REPLY:
428 break;
429 case MGMT_OP_USER_PASSKEY_REPLY:
430 memset(key, 0, sizeof(key));
431 BT_DBG("PassKey: %d", psk_reply->passkey);
432 put_unaligned_le32(psk_reply->passkey, key);
Brian Gix6d5fb8a2011-09-09 14:53:04 -0700433 swap128(key, hcon->tk);
Brian Gixa68668b2011-08-11 15:49:36 -0700434 break;
435 default:
436 reason = SMP_CONFIRM_FAILED;
437 ret = -EOPNOTSUPP;
438 break;
439 }
440
441 if (reason) {
442 BT_DBG("smp_send_cmd: SMP_CMD_PAIRING_FAIL");
443 smp_send_cmd(conn, SMP_CMD_PAIRING_FAIL, sizeof(reason),
444 &reason);
Brian Gixe9ceb522011-09-22 10:46:35 -0700445 del_timer(&hcon->smp_timer);
Brian Gix8d0b7d62011-10-12 15:12:42 -0700446 clear_bit(HCI_CONN_ENCRYPT_PEND, &hcon->pend);
Brian Gix58ba0772011-09-23 13:40:16 -0700447 mgmt_auth_failed(hcon->hdev->id, conn->dst, reason);
Brian Gix6d5fb8a2011-09-09 14:53:04 -0700448 hci_conn_put(hcon);
449 } else if (hcon->cfm_pending) {
Brian Gixa68668b2011-08-11 15:49:36 -0700450 BT_DBG("send_pairing_confirm");
451 ret = send_pairing_confirm(conn);
452 }
453
454 return ret;
455}
456
Vinicius Costa Gomes64532ec2011-06-09 18:50:53 -0300457static u8 smp_cmd_pairing_req(struct l2cap_conn *conn, struct sk_buff *skb)
Anderson Briglia13b48392011-06-09 18:50:42 -0300458{
Brian Gixa68668b2011-08-11 15:49:36 -0700459 struct hci_conn *hcon = conn->hcon;
Vinicius Costa Gomes397d9ae2011-06-14 13:37:42 -0300460 struct smp_cmd_pairing rsp, *req = (void *) skb->data;
461 u8 key_size;
Brian Gixa68668b2011-08-11 15:49:36 -0700462 u8 auth = SMP_AUTH_NONE;
463 int ret;
Anderson Briglia13b48392011-06-09 18:50:42 -0300464
465 BT_DBG("conn %p", conn);
466
Brian Gixa68668b2011-08-11 15:49:36 -0700467 hcon->preq[0] = SMP_CMD_PAIRING_REQ;
468 memcpy(&hcon->preq[1], req, sizeof(*req));
Vinicius Costa Gomes397d9ae2011-06-14 13:37:42 -0300469 skb_pull(skb, sizeof(*req));
Anderson Briglia13b48392011-06-09 18:50:42 -0300470
Brian Gixa68668b2011-08-11 15:49:36 -0700471 if (req->oob_flag && hcon->oob) {
472 /* By definition, OOB data pairing will have MITM protection */
473 auth = req->auth_req | SMP_AUTH_MITM;
474 } else if (req->auth_req & SMP_AUTH_BONDING) {
475 /* We will attempt MITM for all Bonding attempts */
476 auth = SMP_AUTH_BONDING | SMP_AUTH_MITM;
477 }
Vinicius Costa Gomes64532ec2011-06-09 18:50:53 -0300478
479 /* We didn't start the pairing, so no requirements */
Brian Gixa68668b2011-08-11 15:49:36 -0700480 build_pairing_cmd(conn, req, &rsp, auth);
Vinicius Costa Gomes397d9ae2011-06-14 13:37:42 -0300481
482 key_size = min(req->max_key_size, rsp.max_key_size);
483 if (check_enc_key_size(conn, key_size))
484 return SMP_ENC_KEY_SIZE;
Anderson Briglia13b48392011-06-09 18:50:42 -0300485
Brian Gixa68668b2011-08-11 15:49:36 -0700486 ret = smp_rand(hcon->prnd);
487 if (ret)
488 return SMP_UNSPECIFIED;
Anderson Briglia21b8a2b2011-06-09 18:50:46 -0300489
Brian Gixa68668b2011-08-11 15:49:36 -0700490 /* Request setup of TK */
491 ret = tk_request(conn, req->oob_flag, auth, rsp.io_capability,
492 req->io_capability);
493 if (ret)
494 return SMP_UNSPECIFIED;
495
496 hcon->prsp[0] = SMP_CMD_PAIRING_RSP;
497 memcpy(&hcon->prsp[1], &rsp, sizeof(rsp));
Anderson Brigliac8e856e2011-06-09 18:50:45 -0300498
Vinicius Costa Gomes397d9ae2011-06-14 13:37:42 -0300499 smp_send_cmd(conn, SMP_CMD_PAIRING_RSP, sizeof(rsp), &rsp);
Vinicius Costa Gomes64532ec2011-06-09 18:50:53 -0300500
Brian Gixe9ceb522011-09-22 10:46:35 -0700501 mod_timer(&hcon->smp_timer, jiffies + msecs_to_jiffies(SMP_TIMEOUT));
Vinicius Costa Gomesb19d5ce2011-06-14 13:37:41 -0300502
Vinicius Costa Gomes64532ec2011-06-09 18:50:53 -0300503 return 0;
Anderson Briglia13b48392011-06-09 18:50:42 -0300504}
505
Vinicius Costa Gomes64532ec2011-06-09 18:50:53 -0300506static u8 smp_cmd_pairing_rsp(struct l2cap_conn *conn, struct sk_buff *skb)
Anderson Briglia13b48392011-06-09 18:50:42 -0300507{
Brian Gixa68668b2011-08-11 15:49:36 -0700508 struct hci_conn *hcon = conn->hcon;
Vinicius Costa Gomes397d9ae2011-06-14 13:37:42 -0300509 struct smp_cmd_pairing *req, *rsp = (void *) skb->data;
Brian Gixa68668b2011-08-11 15:49:36 -0700510 u8 key_size, auth = SMP_AUTH_NONE;
Anderson Briglia21b8a2b2011-06-09 18:50:46 -0300511 int ret;
Anderson Briglia13b48392011-06-09 18:50:42 -0300512
513 BT_DBG("conn %p", conn);
514
Vinicius Costa Gomes397d9ae2011-06-14 13:37:42 -0300515 skb_pull(skb, sizeof(*rsp));
Vinicius Costa Gomes64532ec2011-06-09 18:50:53 -0300516
Brian Gixa68668b2011-08-11 15:49:36 -0700517 req = (void *) &hcon->preq[1];
Vinicius Costa Gomes397d9ae2011-06-14 13:37:42 -0300518
519 key_size = min(req->max_key_size, rsp->max_key_size);
520 if (check_enc_key_size(conn, key_size))
521 return SMP_ENC_KEY_SIZE;
522
Brian Gixa68668b2011-08-11 15:49:36 -0700523 hcon->prsp[0] = SMP_CMD_PAIRING_RSP;
524 memcpy(&hcon->prsp[1], rsp, sizeof(*rsp));
Vinicius Costa Gomes64532ec2011-06-09 18:50:53 -0300525
Brian Gixa68668b2011-08-11 15:49:36 -0700526 ret = smp_rand(hcon->prnd);
Anderson Briglia21b8a2b2011-06-09 18:50:46 -0300527 if (ret)
Vinicius Costa Gomes64532ec2011-06-09 18:50:53 -0300528 return SMP_UNSPECIFIED;
Anderson Briglia21b8a2b2011-06-09 18:50:46 -0300529
Brian Gixa68668b2011-08-11 15:49:36 -0700530 if ((req->auth_req & SMP_AUTH_BONDING) &&
531 (rsp->auth_req & SMP_AUTH_BONDING))
532 auth = SMP_AUTH_BONDING;
533
534 auth |= (req->auth_req | rsp->auth_req) & SMP_AUTH_MITM;
535
536 ret = tk_request(conn, req->oob_flag, auth, rsp->io_capability,
537 req->io_capability);
Anderson Briglia21b8a2b2011-06-09 18:50:46 -0300538 if (ret)
Vinicius Costa Gomes64532ec2011-06-09 18:50:53 -0300539 return SMP_UNSPECIFIED;
Anderson Briglia21b8a2b2011-06-09 18:50:46 -0300540
Brian Gixa68668b2011-08-11 15:49:36 -0700541 hcon->cfm_pending = TRUE;
Anderson Briglia21b8a2b2011-06-09 18:50:46 -0300542
Brian Gixa68668b2011-08-11 15:49:36 -0700543 /* Can't compose response until we have been confirmed */
544 if (!hcon->tk_valid)
545 return 0;
546
547 ret = send_pairing_confirm(conn);
548 if (ret)
549 return SMP_CONFIRM_FAILED;
Vinicius Costa Gomes64532ec2011-06-09 18:50:53 -0300550
551 return 0;
Anderson Briglia13b48392011-06-09 18:50:42 -0300552}
553
Vinicius Costa Gomes64532ec2011-06-09 18:50:53 -0300554static u8 smp_cmd_pairing_confirm(struct l2cap_conn *conn, struct sk_buff *skb)
Anderson Briglia13b48392011-06-09 18:50:42 -0300555{
Brian Gixa68668b2011-08-11 15:49:36 -0700556 struct hci_conn *hcon = conn->hcon;
557 int ret;
Anderson Briglia21b8a2b2011-06-09 18:50:46 -0300558
Anderson Briglia13b48392011-06-09 18:50:42 -0300559 BT_DBG("conn %p %s", conn, conn->hcon->out ? "master" : "slave");
560
Brian Gixa68668b2011-08-11 15:49:36 -0700561 memcpy(hcon->pcnf, skb->data, sizeof(hcon->pcnf));
562 skb_pull(skb, sizeof(hcon->pcnf));
Anderson Briglia21b8a2b2011-06-09 18:50:46 -0300563
Anderson Briglia13b48392011-06-09 18:50:42 -0300564 if (conn->hcon->out) {
Anderson Briglia21b8a2b2011-06-09 18:50:46 -0300565 u8 random[16];
Anderson Briglia13b48392011-06-09 18:50:42 -0300566
Brian Gixa68668b2011-08-11 15:49:36 -0700567 swap128(hcon->prnd, random);
Anderson Briglia13b48392011-06-09 18:50:42 -0300568 smp_send_cmd(conn, SMP_CMD_PAIRING_RANDOM, sizeof(random),
Anderson Briglia21b8a2b2011-06-09 18:50:46 -0300569 random);
Brian Gixa68668b2011-08-11 15:49:36 -0700570 } else if (hcon->tk_valid) {
571 ret = send_pairing_confirm(conn);
Anderson Briglia13b48392011-06-09 18:50:42 -0300572
Anderson Briglia21b8a2b2011-06-09 18:50:46 -0300573 if (ret)
Vinicius Costa Gomes64532ec2011-06-09 18:50:53 -0300574 return SMP_CONFIRM_FAILED;
Brian Gixa68668b2011-08-11 15:49:36 -0700575 } else
576 hcon->cfm_pending = TRUE;
Anderson Briglia21b8a2b2011-06-09 18:50:46 -0300577
Vinicius Costa Gomes64532ec2011-06-09 18:50:53 -0300578
Brian Gixe9ceb522011-09-22 10:46:35 -0700579 mod_timer(&hcon->smp_timer, jiffies + msecs_to_jiffies(SMP_TIMEOUT));
Vinicius Costa Gomesb19d5ce2011-06-14 13:37:41 -0300580
Vinicius Costa Gomes64532ec2011-06-09 18:50:53 -0300581 return 0;
Anderson Briglia13b48392011-06-09 18:50:42 -0300582}
583
Vinicius Costa Gomes64532ec2011-06-09 18:50:53 -0300584static u8 smp_cmd_pairing_random(struct l2cap_conn *conn, struct sk_buff *skb)
Anderson Briglia13b48392011-06-09 18:50:42 -0300585{
Vinicius Costa Gomes735038c2011-06-09 18:50:47 -0300586 struct hci_conn *hcon = conn->hcon;
587 struct crypto_blkcipher *tfm = hcon->hdev->tfm;
Anderson Briglia21b8a2b2011-06-09 18:50:46 -0300588 int ret;
Vinicius Costa Gomesc34e25e2011-06-09 18:50:48 -0300589 u8 key[16], res[16], random[16], confirm[16];
Anderson Briglia21b8a2b2011-06-09 18:50:46 -0300590
591 swap128(skb->data, random);
592 skb_pull(skb, sizeof(random));
593
594 if (conn->hcon->out)
Brian Gixa68668b2011-08-11 15:49:36 -0700595 ret = smp_c1(tfm, hcon->tk, random, hcon->preq, hcon->prsp, 0,
596 conn->src, hcon->dst_type, conn->dst,
Anderson Briglia21b8a2b2011-06-09 18:50:46 -0300597 res);
598 else
Brian Gixa68668b2011-08-11 15:49:36 -0700599 ret = smp_c1(tfm, hcon->tk, random, hcon->preq, hcon->prsp,
600 hcon->dst_type, conn->dst, 0, conn->src,
Anderson Briglia21b8a2b2011-06-09 18:50:46 -0300601 res);
602 if (ret)
Vinicius Costa Gomes64532ec2011-06-09 18:50:53 -0300603 return SMP_UNSPECIFIED;
Anderson Briglia13b48392011-06-09 18:50:42 -0300604
605 BT_DBG("conn %p %s", conn, conn->hcon->out ? "master" : "slave");
606
Anderson Briglia21b8a2b2011-06-09 18:50:46 -0300607 swap128(res, confirm);
608
Brian Gixa68668b2011-08-11 15:49:36 -0700609 if (memcmp(hcon->pcnf, confirm, sizeof(hcon->pcnf)) != 0) {
Anderson Briglia21b8a2b2011-06-09 18:50:46 -0300610 BT_ERR("Pairing failed (confirmation values mismatch)");
Vinicius Costa Gomes64532ec2011-06-09 18:50:53 -0300611 return SMP_CONFIRM_FAILED;
Anderson Briglia21b8a2b2011-06-09 18:50:46 -0300612 }
Anderson Briglia13b48392011-06-09 18:50:42 -0300613
614 if (conn->hcon->out) {
Vinicius Costa Gomesf1b45c52011-07-07 18:59:40 -0300615 u8 stk[16], rand[8];
Vinicius Costa Gomes735038c2011-06-09 18:50:47 -0300616 __le16 ediv;
Vinicius Costa Gomes397d9ae2011-06-14 13:37:42 -0300617
Vinicius Costa Gomes735038c2011-06-09 18:50:47 -0300618 memset(rand, 0, sizeof(rand));
619 ediv = 0;
Vinicius Costa Gomesf1b45c52011-07-07 18:59:40 -0300620
Brian Gixa68668b2011-08-11 15:49:36 -0700621 smp_s1(tfm, hcon->tk, random, hcon->prnd, key);
Vinicius Costa Gomesf1b45c52011-07-07 18:59:40 -0300622 swap128(key, stk);
623
Brian Gixa68668b2011-08-11 15:49:36 -0700624 memset(stk + hcon->smp_key_size, 0,
625 SMP_MAX_ENC_KEY_SIZE - hcon->smp_key_size);
Vinicius Costa Gomesf1b45c52011-07-07 18:59:40 -0300626
627 hci_le_start_enc(hcon, ediv, rand, stk);
Brian Gixa68668b2011-08-11 15:49:36 -0700628 hcon->enc_key_size = hcon->smp_key_size;
Anderson Briglia21b8a2b2011-06-09 18:50:46 -0300629 } else {
Vinicius Costa Gomesf1b45c52011-07-07 18:59:40 -0300630 u8 stk[16], r[16], rand[8];
631 __le16 ediv;
632
633 memset(rand, 0, sizeof(rand));
634 ediv = 0;
Anderson Briglia21b8a2b2011-06-09 18:50:46 -0300635
Brian Gixa68668b2011-08-11 15:49:36 -0700636 swap128(hcon->prnd, r);
Anderson Briglia21b8a2b2011-06-09 18:50:46 -0300637 smp_send_cmd(conn, SMP_CMD_PAIRING_RANDOM, sizeof(r), r);
638
Brian Gixa68668b2011-08-11 15:49:36 -0700639 smp_s1(tfm, hcon->tk, hcon->prnd, random, key);
Vinicius Costa Gomesf1b45c52011-07-07 18:59:40 -0300640 swap128(key, stk);
Vinicius Costa Gomes397d9ae2011-06-14 13:37:42 -0300641
Brian Gixa68668b2011-08-11 15:49:36 -0700642 memset(stk + hcon->smp_key_size, 0,
643 SMP_MAX_ENC_KEY_SIZE - hcon->smp_key_size);
Vinicius Costa Gomesf1b45c52011-07-07 18:59:40 -0300644
Brian Gixcf956772011-10-20 15:18:51 -0700645 hci_add_ltk(conn->hcon->hdev, 0, conn->dst, hcon->dst_type,
646 hcon->smp_key_size, hcon->auth, ediv, rand, stk);
Anderson Briglia13b48392011-06-09 18:50:42 -0300647 }
Vinicius Costa Gomes64532ec2011-06-09 18:50:53 -0300648
649 return 0;
Anderson Briglia13b48392011-06-09 18:50:42 -0300650}
651
Brian Gix372257b2011-10-25 09:06:30 -0700652static int smp_encrypt_link(struct hci_conn *hcon, struct link_key *key)
653{
654 struct key_master_id *master;
Brian Gix80fb3a92012-01-31 13:15:20 -0800655 u8 sec_level;
Brian Gix372257b2011-10-25 09:06:30 -0700656 u8 zerobuf[8];
657
658 if (!hcon || !key || !key->data)
659 return -EINVAL;
660
661 memset(zerobuf, 0, sizeof(zerobuf));
662
663 master = (void *) key->data;
664
665 if (!master->ediv && !memcmp(master->rand, zerobuf, sizeof(zerobuf)))
666 return -EINVAL;
667
668 hcon->enc_key_size = key->pin_len;
669 hcon->sec_req = TRUE;
Brian Gix80fb3a92012-01-31 13:15:20 -0800670 sec_level = authreq_to_seclevel(key->auth);
671
672 BT_DBG("cur %d, req: %d", hcon->sec_level, sec_level);
673
674 if (sec_level > hcon->sec_level)
675 hcon->pending_sec_level = sec_level;
676
677
678 if (!(hcon->link_mode & HCI_LM_ENCRYPT))
679 hci_conn_hold(hcon);
680
Brian Gix372257b2011-10-25 09:06:30 -0700681 hci_le_start_enc(hcon, master->ediv, master->rand, key->val);
682
683 return 0;
684}
685
Vinicius Costa Gomes64532ec2011-06-09 18:50:53 -0300686static u8 smp_cmd_security_req(struct l2cap_conn *conn, struct sk_buff *skb)
Anderson Briglia13b48392011-06-09 18:50:42 -0300687{
Brian Gixa68668b2011-08-11 15:49:36 -0700688 struct hci_conn *hcon = conn->hcon;
Anderson Briglia13b48392011-06-09 18:50:42 -0300689 struct smp_cmd_security_req *rp = (void *) skb->data;
690 struct smp_cmd_pairing cp;
Brian Gixa68668b2011-08-11 15:49:36 -0700691 struct link_key *key;
Anderson Briglia13b48392011-06-09 18:50:42 -0300692
693 BT_DBG("conn %p", conn);
694
Vinicius Costa Gomesa5474a82011-01-26 21:42:57 -0300695 if (test_bit(HCI_CONN_ENCRYPT_PEND, &hcon->pend))
Vinicius Costa Gomes64532ec2011-06-09 18:50:53 -0300696 return 0;
Vinicius Costa Gomesa5474a82011-01-26 21:42:57 -0300697
Brian Gixa68668b2011-08-11 15:49:36 -0700698 key = hci_find_link_key_type(hcon->hdev, conn->dst, KEY_TYPE_LTK);
699 if (key && ((key->auth & SMP_AUTH_MITM) ||
700 !(rp->auth_req & SMP_AUTH_MITM))) {
Brian Gixa68668b2011-08-11 15:49:36 -0700701
Brian Gix372257b2011-10-25 09:06:30 -0700702 if (smp_encrypt_link(hcon, key) < 0)
703 goto invalid_key;
Brian Gixa68668b2011-08-11 15:49:36 -0700704
Brian Gixa68668b2011-08-11 15:49:36 -0700705 return 0;
706 }
707
Brian Gix372257b2011-10-25 09:06:30 -0700708invalid_key:
Brian Gixa68668b2011-08-11 15:49:36 -0700709 hcon->sec_req = FALSE;
710
Brian Gix7f7e16c2011-11-01 16:27:25 -0700711 /* Switch to Pairing Connection Parameters */
712 hci_le_conn_update(hcon, SMP_MIN_CONN_INTERVAL, SMP_MAX_CONN_INTERVAL,
713 SMP_MAX_CONN_LATENCY, SMP_SUPERVISION_TIMEOUT);
714
Anderson Briglia13b48392011-06-09 18:50:42 -0300715 skb_pull(skb, sizeof(*rp));
Anderson Briglia13b48392011-06-09 18:50:42 -0300716
Vinicius Costa Gomes64532ec2011-06-09 18:50:53 -0300717 memset(&cp, 0, sizeof(cp));
Vinicius Costa Gomes10daf972011-07-07 18:59:38 -0300718 build_pairing_cmd(conn, &cp, NULL, rp->auth_req);
Anderson Briglia13b48392011-06-09 18:50:42 -0300719
Brian Gix27a795c2012-04-19 11:05:06 -0700720 hcon->pending_sec_level = authreq_to_seclevel(rp->auth_req);
Brian Gixa68668b2011-08-11 15:49:36 -0700721 hcon->preq[0] = SMP_CMD_PAIRING_REQ;
722 memcpy(&hcon->preq[1], &cp, sizeof(cp));
Anderson Brigliac8e856e2011-06-09 18:50:45 -0300723
Anderson Briglia13b48392011-06-09 18:50:42 -0300724 smp_send_cmd(conn, SMP_CMD_PAIRING_REQ, sizeof(cp), &cp);
Vinicius Costa Gomesa5474a82011-01-26 21:42:57 -0300725
Brian Gixe9ceb522011-09-22 10:46:35 -0700726 mod_timer(&hcon->smp_timer, jiffies + msecs_to_jiffies(SMP_TIMEOUT));
Vinicius Costa Gomesb19d5ce2011-06-14 13:37:41 -0300727
Vinicius Costa Gomesa5474a82011-01-26 21:42:57 -0300728 set_bit(HCI_CONN_ENCRYPT_PEND, &hcon->pend);
Vinicius Costa Gomesa5474a82011-01-26 21:42:57 -0300729
Brian Gix8d0b7d62011-10-12 15:12:42 -0700730 hci_conn_hold(hcon);
731
Vinicius Costa Gomes64532ec2011-06-09 18:50:53 -0300732 return 0;
Anderson Briglia13b48392011-06-09 18:50:42 -0300733}
734
Anderson Briglia133e14c2011-06-09 18:50:40 -0300735int smp_conn_security(struct l2cap_conn *conn, __u8 sec_level)
736{
Vinicius Costa Gomes09fabbc2011-06-09 18:50:43 -0300737 struct hci_conn *hcon = conn->hcon;
Anderson Briglia133e14c2011-06-09 18:50:40 -0300738 __u8 authreq;
739
Brian Gix80fb3a92012-01-31 13:15:20 -0800740 BT_DBG("conn %p hcon %p %d req: %d",
741 conn, hcon, hcon->sec_level, sec_level);
Vinicius Costa Gomes09fabbc2011-06-09 18:50:43 -0300742
Brian Gix80fb3a92012-01-31 13:15:20 -0800743 if (IS_ERR(hcon->hdev->tfm))
Vinicius Costa Gomes09fabbc2011-06-09 18:50:43 -0300744 return 1;
Anderson Briglia133e14c2011-06-09 18:50:40 -0300745
Brian Gix80fb3a92012-01-31 13:15:20 -0800746 if (test_bit(HCI_CONN_ENCRYPT_PEND, &hcon->pend))
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700747 return -EINPROGRESS;
Anderson Briglia133e14c2011-06-09 18:50:40 -0300748
Brian Gix80fb3a92012-01-31 13:15:20 -0800749 if (sec_level == BT_SECURITY_LOW)
Anderson Briglia133e14c2011-06-09 18:50:40 -0300750 return 1;
Vinicius Costa Gomesa5474a82011-01-26 21:42:57 -0300751
Brian Gix80fb3a92012-01-31 13:15:20 -0800752
753 if (hcon->sec_level >= sec_level)
Vinicius Costa Gomesa5474a82011-01-26 21:42:57 -0300754 return 1;
755
756 authreq = seclevel_to_authreq(sec_level);
Anderson Briglia133e14c2011-06-09 18:50:40 -0300757
Brian Gixa68668b2011-08-11 15:49:36 -0700758 hcon->smp_conn = conn;
Brian Gix80fb3a92012-01-31 13:15:20 -0800759 hcon->pending_sec_level = sec_level;
Brian Gixa68668b2011-08-11 15:49:36 -0700760
761 if ((hcon->link_mode & HCI_LM_MASTER) && !hcon->sec_req) {
Vinicius Costa Gomes5d873ca2011-07-07 18:59:41 -0300762 struct link_key *key;
763
764 key = hci_find_link_key_type(hcon->hdev, conn->dst,
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700765 KEY_TYPE_LTK);
Vinicius Costa Gomes5d873ca2011-07-07 18:59:41 -0300766
Brian Gix372257b2011-10-25 09:06:30 -0700767 if (smp_encrypt_link(hcon, key) == 0)
Vinicius Costa Gomes5d873ca2011-07-07 18:59:41 -0300768 goto done;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700769 }
770
Brian Gixa68668b2011-08-11 15:49:36 -0700771 hcon->sec_req = FALSE;
772
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700773 if (hcon->link_mode & HCI_LM_MASTER) {
774 struct smp_cmd_pairing cp;
Anderson Brigliac8e856e2011-06-09 18:50:45 -0300775
Brian Gix7f7e16c2011-11-01 16:27:25 -0700776 /* Switch to Pairing Connection Parameters */
777 hci_le_conn_update(hcon, SMP_MIN_CONN_INTERVAL,
778 SMP_MAX_CONN_INTERVAL, SMP_MAX_CONN_LATENCY,
779 SMP_SUPERVISION_TIMEOUT);
780
Vinicius Costa Gomes10daf972011-07-07 18:59:38 -0300781 build_pairing_cmd(conn, &cp, NULL, authreq);
Brian Gixa68668b2011-08-11 15:49:36 -0700782 hcon->preq[0] = SMP_CMD_PAIRING_REQ;
783 memcpy(&hcon->preq[1], &cp, sizeof(cp));
Anderson Brigliac8e856e2011-06-09 18:50:45 -0300784
Brian Gixe9ceb522011-09-22 10:46:35 -0700785 mod_timer(&hcon->smp_timer, jiffies +
Vinicius Costa Gomesb19d5ce2011-06-14 13:37:41 -0300786 msecs_to_jiffies(SMP_TIMEOUT));
787
Anderson Briglia133e14c2011-06-09 18:50:40 -0300788 smp_send_cmd(conn, SMP_CMD_PAIRING_REQ, sizeof(cp), &cp);
Brian Gix80fb3a92012-01-31 13:15:20 -0800789 hci_conn_hold(hcon);
Anderson Briglia133e14c2011-06-09 18:50:40 -0300790 } else {
791 struct smp_cmd_security_req cp;
792 cp.auth_req = authreq;
793 smp_send_cmd(conn, SMP_CMD_SECURITY_REQ, sizeof(cp), &cp);
794 }
795
Vinicius Costa Gomes5d873ca2011-07-07 18:59:41 -0300796done:
Vinicius Costa Gomesa5474a82011-01-26 21:42:57 -0300797 set_bit(HCI_CONN_ENCRYPT_PEND, &hcon->pend);
798
Anderson Briglia133e14c2011-06-09 18:50:40 -0300799 return 0;
800}
801
Vinicius Costa Gomesc1d5e1d2011-07-07 18:59:34 -0300802static int smp_cmd_encrypt_info(struct l2cap_conn *conn, struct sk_buff *skb)
803{
Brian Gixa68668b2011-08-11 15:49:36 -0700804 struct hci_conn *hcon = conn->hcon;
Vinicius Costa Gomese56cede2011-07-07 18:59:39 -0300805 struct smp_cmd_encrypt_info *rp = (void *) skb->data;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700806 u8 rand[8];
807 int err;
Vinicius Costa Gomese56cede2011-07-07 18:59:39 -0300808
809 skb_pull(skb, sizeof(*rp));
810
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700811 BT_DBG("conn %p", conn);
812
813 memset(rand, 0, sizeof(rand));
814
Brian Gixcf956772011-10-20 15:18:51 -0700815 err = hci_add_ltk(hcon->hdev, 0, conn->dst, hcon->dst_type,
816 0, 0, 0, rand, rp->ltk);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700817 if (err)
818 return SMP_UNSPECIFIED;
Vinicius Costa Gomese56cede2011-07-07 18:59:39 -0300819
Vinicius Costa Gomesc1d5e1d2011-07-07 18:59:34 -0300820 return 0;
821}
822
823static int smp_cmd_master_ident(struct l2cap_conn *conn, struct sk_buff *skb)
824{
Brian Gixa68668b2011-08-11 15:49:36 -0700825 struct hci_conn *hcon = conn->hcon;
Vinicius Costa Gomese56cede2011-07-07 18:59:39 -0300826 struct smp_cmd_master_ident *rp = (void *) skb->data;
Brian Gixa68668b2011-08-11 15:49:36 -0700827 struct smp_cmd_pairing *paircmd = (void *) &hcon->prsp[1];
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700828 struct link_key *key;
Brian Gixa68668b2011-08-11 15:49:36 -0700829 u8 *keydist;
Vinicius Costa Gomesc1d5e1d2011-07-07 18:59:34 -0300830
Vinicius Costa Gomese56cede2011-07-07 18:59:39 -0300831 skb_pull(skb, sizeof(*rp));
832
Brian Gixa68668b2011-08-11 15:49:36 -0700833 key = hci_find_link_key_type(hcon->hdev, conn->dst, KEY_TYPE_LTK);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700834 if (key == NULL)
835 return SMP_UNSPECIFIED;
836
Brian Gixa68668b2011-08-11 15:49:36 -0700837 if (hcon->out)
838 keydist = &paircmd->resp_key_dist;
839 else
840 keydist = &paircmd->init_key_dist;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700841
Brian Gixa68668b2011-08-11 15:49:36 -0700842 BT_DBG("keydist 0x%x", *keydist);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700843
Brian Gixcf956772011-10-20 15:18:51 -0700844 hci_add_ltk(hcon->hdev, 1, conn->dst, hcon->dst_type,
845 hcon->smp_key_size, hcon->auth, rp->ediv,
846 rp->rand, key->val);
Vinicius Costa Gomesc1d5e1d2011-07-07 18:59:34 -0300847
Brian Gixa68668b2011-08-11 15:49:36 -0700848 *keydist &= ~SMP_DIST_ENC_KEY;
849 if (hcon->out) {
850 if (!(*keydist))
851 smp_distribute_keys(conn, 1);
852 }
Vinicius Costa Gomesc1d5e1d2011-07-07 18:59:34 -0300853
854 return 0;
855}
856
Anderson Briglia133e14c2011-06-09 18:50:40 -0300857int smp_sig_channel(struct l2cap_conn *conn, struct sk_buff *skb)
858{
Brian Gixa68668b2011-08-11 15:49:36 -0700859 struct hci_conn *hcon = conn->hcon;
Anderson Briglia133e14c2011-06-09 18:50:40 -0300860 __u8 code = skb->data[0];
861 __u8 reason;
862 int err = 0;
863
Brian Gixa68668b2011-08-11 15:49:36 -0700864 if (IS_ERR(hcon->hdev->tfm)) {
865 err = PTR_ERR(hcon->hdev->tfm);
Vinicius Costa Gomes09fabbc2011-06-09 18:50:43 -0300866 reason = SMP_PAIRING_NOTSUPP;
Brian Gixa68668b2011-08-11 15:49:36 -0700867 BT_ERR("SMP_PAIRING_NOTSUPP %p", hcon->hdev->tfm);
Vinicius Costa Gomes09fabbc2011-06-09 18:50:43 -0300868 goto done;
869 }
870
Brian Gixa68668b2011-08-11 15:49:36 -0700871 hcon->smp_conn = conn;
Anderson Briglia133e14c2011-06-09 18:50:40 -0300872 skb_pull(skb, sizeof(code));
873
874 switch (code) {
875 case SMP_CMD_PAIRING_REQ:
Vinicius Costa Gomes64532ec2011-06-09 18:50:53 -0300876 reason = smp_cmd_pairing_req(conn, skb);
Anderson Briglia133e14c2011-06-09 18:50:40 -0300877 break;
878
879 case SMP_CMD_PAIRING_FAIL:
Vinicius Costa Gomes64532ec2011-06-09 18:50:53 -0300880 reason = 0;
881 err = -EPERM;
Brian Gixe9ceb522011-09-22 10:46:35 -0700882 del_timer(&hcon->smp_timer);
Brian Gix8d0b7d62011-10-12 15:12:42 -0700883 clear_bit(HCI_CONN_ENCRYPT_PEND, &hcon->pend);
Brian Gix570efc92011-10-13 15:59:51 -0700884 mgmt_auth_failed(hcon->hdev->id, conn->dst, skb->data[0]);
Brian Gix6d5fb8a2011-09-09 14:53:04 -0700885 hci_conn_put(hcon);
Anderson Briglia133e14c2011-06-09 18:50:40 -0300886 break;
887
888 case SMP_CMD_PAIRING_RSP:
Vinicius Costa Gomes64532ec2011-06-09 18:50:53 -0300889 reason = smp_cmd_pairing_rsp(conn, skb);
Anderson Briglia13b48392011-06-09 18:50:42 -0300890 break;
891
892 case SMP_CMD_SECURITY_REQ:
Vinicius Costa Gomes64532ec2011-06-09 18:50:53 -0300893 reason = smp_cmd_security_req(conn, skb);
Anderson Briglia13b48392011-06-09 18:50:42 -0300894 break;
895
Anderson Briglia133e14c2011-06-09 18:50:40 -0300896 case SMP_CMD_PAIRING_CONFIRM:
Vinicius Costa Gomes64532ec2011-06-09 18:50:53 -0300897 reason = smp_cmd_pairing_confirm(conn, skb);
Anderson Briglia13b48392011-06-09 18:50:42 -0300898 break;
899
Anderson Briglia133e14c2011-06-09 18:50:40 -0300900 case SMP_CMD_PAIRING_RANDOM:
Vinicius Costa Gomes64532ec2011-06-09 18:50:53 -0300901 reason = smp_cmd_pairing_random(conn, skb);
Anderson Briglia13b48392011-06-09 18:50:42 -0300902 break;
903
Anderson Briglia133e14c2011-06-09 18:50:40 -0300904 case SMP_CMD_ENCRYPT_INFO:
Vinicius Costa Gomesc1d5e1d2011-07-07 18:59:34 -0300905 reason = smp_cmd_encrypt_info(conn, skb);
906 break;
907
Anderson Briglia133e14c2011-06-09 18:50:40 -0300908 case SMP_CMD_MASTER_IDENT:
Vinicius Costa Gomesc1d5e1d2011-07-07 18:59:34 -0300909 reason = smp_cmd_master_ident(conn, skb);
910 break;
911
Anderson Briglia133e14c2011-06-09 18:50:40 -0300912 case SMP_CMD_IDENT_INFO:
913 case SMP_CMD_IDENT_ADDR_INFO:
914 case SMP_CMD_SIGN_INFO:
Vinicius Costa Gomesc1d5e1d2011-07-07 18:59:34 -0300915 /* Just ignored */
916 reason = 0;
917 break;
918
Anderson Briglia133e14c2011-06-09 18:50:40 -0300919 default:
920 BT_DBG("Unknown command code 0x%2.2x", code);
921
922 reason = SMP_CMD_NOTSUPP;
Vinicius Costa Gomes09fabbc2011-06-09 18:50:43 -0300923 err = -EOPNOTSUPP;
924 goto done;
925 }
926
927done:
Brian Gixa68668b2011-08-11 15:49:36 -0700928 if (reason) {
929 BT_ERR("SMP_CMD_PAIRING_FAIL: %d", reason);
Anderson Briglia133e14c2011-06-09 18:50:40 -0300930 smp_send_cmd(conn, SMP_CMD_PAIRING_FAIL, sizeof(reason),
931 &reason);
Brian Gixe9ceb522011-09-22 10:46:35 -0700932 del_timer(&hcon->smp_timer);
Brian Gix8d0b7d62011-10-12 15:12:42 -0700933 clear_bit(HCI_CONN_ENCRYPT_PEND, &hcon->pend);
Brian Gix58ba0772011-09-23 13:40:16 -0700934 mgmt_auth_failed(hcon->hdev->id, conn->dst, reason);
Brian Gix6d5fb8a2011-09-09 14:53:04 -0700935 hci_conn_put(hcon);
Brian Gixa68668b2011-08-11 15:49:36 -0700936 }
Anderson Briglia133e14c2011-06-09 18:50:40 -0300937
938 kfree_skb(skb);
939 return err;
940}
Vinicius Costa Gomesc1d5e1d2011-07-07 18:59:34 -0300941
Brian Gixa68668b2011-08-11 15:49:36 -0700942static int smp_distribute_keys(struct l2cap_conn *conn, __u8 force)
Vinicius Costa Gomesc1d5e1d2011-07-07 18:59:34 -0300943{
Brian Gixa68668b2011-08-11 15:49:36 -0700944 struct hci_conn *hcon = conn->hcon;
Vinicius Costa Gomesc1d5e1d2011-07-07 18:59:34 -0300945 struct smp_cmd_pairing *req, *rsp;
946 __u8 *keydist;
947
948 BT_DBG("conn %p force %d", conn, force);
949
Brian Gixa68668b2011-08-11 15:49:36 -0700950 if (IS_ERR(hcon->hdev->tfm))
951 return PTR_ERR(hcon->hdev->tfm);
Vinicius Costa Gomesc1d5e1d2011-07-07 18:59:34 -0300952
Brian Gixa68668b2011-08-11 15:49:36 -0700953 rsp = (void *) &hcon->prsp[1];
Vinicius Costa Gomesc1d5e1d2011-07-07 18:59:34 -0300954
955 /* The responder sends its keys first */
Brian Gixa68668b2011-08-11 15:49:36 -0700956 if (!force && hcon->out && (rsp->resp_key_dist & 0x07))
Vinicius Costa Gomesc1d5e1d2011-07-07 18:59:34 -0300957 return 0;
958
Brian Gixa68668b2011-08-11 15:49:36 -0700959 req = (void *) &hcon->preq[1];
Vinicius Costa Gomesc1d5e1d2011-07-07 18:59:34 -0300960
Brian Gixa68668b2011-08-11 15:49:36 -0700961 if (hcon->out) {
Vinicius Costa Gomesc1d5e1d2011-07-07 18:59:34 -0300962 keydist = &rsp->init_key_dist;
963 *keydist &= req->init_key_dist;
964 } else {
965 keydist = &rsp->resp_key_dist;
966 *keydist &= req->resp_key_dist;
967 }
968
969
970 BT_DBG("keydist 0x%x", *keydist);
971
972 if (*keydist & SMP_DIST_ENC_KEY) {
973 struct smp_cmd_encrypt_info enc;
974 struct smp_cmd_master_ident ident;
975 __le16 ediv;
976
977 get_random_bytes(enc.ltk, sizeof(enc.ltk));
978 get_random_bytes(&ediv, sizeof(ediv));
979 get_random_bytes(ident.rand, sizeof(ident.rand));
980
981 smp_send_cmd(conn, SMP_CMD_ENCRYPT_INFO, sizeof(enc), &enc);
982
Brian Gixcf956772011-10-20 15:18:51 -0700983 hci_add_ltk(hcon->hdev, 1, conn->dst, hcon->dst_type,
984 hcon->smp_key_size, hcon->auth, ediv,
985 ident.rand, enc.ltk);
Vinicius Costa Gomese56cede2011-07-07 18:59:39 -0300986
Vinicius Costa Gomesc1d5e1d2011-07-07 18:59:34 -0300987 ident.ediv = cpu_to_le16(ediv);
988
989 smp_send_cmd(conn, SMP_CMD_MASTER_IDENT, sizeof(ident), &ident);
990
991 *keydist &= ~SMP_DIST_ENC_KEY;
992 }
993
994 if (*keydist & SMP_DIST_ID_KEY) {
995 struct smp_cmd_ident_addr_info addrinfo;
996 struct smp_cmd_ident_info idinfo;
997
998 /* Send a dummy key */
999 get_random_bytes(idinfo.irk, sizeof(idinfo.irk));
1000
1001 smp_send_cmd(conn, SMP_CMD_IDENT_INFO, sizeof(idinfo), &idinfo);
1002
1003 /* Just public address */
1004 memset(&addrinfo, 0, sizeof(addrinfo));
1005 bacpy(&addrinfo.bdaddr, conn->src);
1006
1007 smp_send_cmd(conn, SMP_CMD_IDENT_ADDR_INFO, sizeof(addrinfo),
1008 &addrinfo);
1009
1010 *keydist &= ~SMP_DIST_ID_KEY;
1011 }
1012
1013 if (*keydist & SMP_DIST_SIGN) {
1014 struct smp_cmd_sign_info sign;
1015
1016 /* Send a dummy key */
1017 get_random_bytes(sign.csrk, sizeof(sign.csrk));
1018
1019 smp_send_cmd(conn, SMP_CMD_SIGN_INFO, sizeof(sign), &sign);
1020
1021 *keydist &= ~SMP_DIST_SIGN;
1022 }
1023
Brian Gix2a335262011-11-17 12:59:23 -08001024 if (hcon->out) {
Brian Gixe57c1672011-09-13 12:34:59 -07001025 if (hcon->disconn_cfm_cb)
1026 hcon->disconn_cfm_cb(hcon, 0);
Brian Gixe9ceb522011-09-22 10:46:35 -07001027 del_timer(&hcon->smp_timer);
Brian Gix8d0b7d62011-10-12 15:12:42 -07001028 clear_bit(HCI_CONN_ENCRYPT_PEND, &hcon->pend);
Brian Gix2a335262011-11-17 12:59:23 -08001029 hci_conn_put(hcon);
1030 } else if (rsp->resp_key_dist) {
1031 if (hcon->disconn_cfm_cb)
1032 hcon->disconn_cfm_cb(hcon, SMP_UNSPECIFIED);
1033 clear_bit(HCI_CONN_ENCRYPT_PEND, &hcon->pend);
Brian Gix58ba0772011-09-23 13:40:16 -07001034 mgmt_auth_failed(hcon->hdev->id, conn->dst, SMP_UNSPECIFIED);
Brian Gix6d5fb8a2011-09-09 14:53:04 -07001035 hci_conn_put(hcon);
1036 }
Brian Gixa68668b2011-08-11 15:49:36 -07001037
1038 return 0;
1039}
1040
1041int smp_link_encrypt_cmplt(struct l2cap_conn *conn, u8 status, u8 encrypt)
1042{
1043 struct hci_conn *hcon = conn->hcon;
1044
1045 BT_DBG("smp: %d %d %d", status, encrypt, hcon->sec_req);
1046
Brian Gix8d0b7d62011-10-12 15:12:42 -07001047 clear_bit(HCI_CONN_ENCRYPT_PEND, &hcon->pend);
1048
Brian Gix80fb3a92012-01-31 13:15:20 -08001049 if (!status && encrypt && hcon->sec_level < hcon->pending_sec_level)
1050 hcon->sec_level = hcon->pending_sec_level;
1051
Brian Gixa68668b2011-08-11 15:49:36 -07001052 if (!status && encrypt && !hcon->sec_req)
Brian Gix80fb3a92012-01-31 13:15:20 -08001053 return smp_distribute_keys(conn, 0);
Brian Gixa68668b2011-08-11 15:49:36 -07001054
1055 /* Fall back to Pairing request if failed a Link Security request */
1056 else if (hcon->sec_req && (status || !encrypt))
Brian Gix80fb3a92012-01-31 13:15:20 -08001057 smp_conn_security(conn, hcon->pending_sec_level);
Brian Gixa68668b2011-08-11 15:49:36 -07001058
Brian Gix80fb3a92012-01-31 13:15:20 -08001059 hci_conn_put(hcon);
Brian Gix8d0b7d62011-10-12 15:12:42 -07001060
Vinicius Costa Gomesc1d5e1d2011-07-07 18:59:34 -03001061 return 0;
1062}
Brian Gixe9ceb522011-09-22 10:46:35 -07001063
1064void smp_timeout(unsigned long arg)
1065{
1066 struct l2cap_conn *conn = (void *) arg;
1067 u8 reason = SMP_UNSPECIFIED;
1068
1069 BT_DBG("%p", conn);
1070
1071 smp_send_cmd(conn, SMP_CMD_PAIRING_FAIL, sizeof(reason), &reason);
Brian Gix8d0b7d62011-10-12 15:12:42 -07001072 clear_bit(HCI_CONN_ENCRYPT_PEND, &conn->hcon->pend);
Brian Gix58ba0772011-09-23 13:40:16 -07001073 mgmt_auth_failed(conn->hcon->hdev->id, conn->dst, SMP_UNSPECIFIED);
Brian Gixe9ceb522011-09-22 10:46:35 -07001074 hci_conn_put(conn->hcon);
1075}