blob: 2484a9a4f55830b3840a3f8f2e44ca07113ffd3a [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 Gixa68668b2011-08-11 15:49:36 -0700720 hcon->preq[0] = SMP_CMD_PAIRING_REQ;
721 memcpy(&hcon->preq[1], &cp, sizeof(cp));
Anderson Brigliac8e856e2011-06-09 18:50:45 -0300722
Anderson Briglia13b48392011-06-09 18:50:42 -0300723 smp_send_cmd(conn, SMP_CMD_PAIRING_REQ, sizeof(cp), &cp);
Vinicius Costa Gomesa5474a82011-01-26 21:42:57 -0300724
Brian Gixe9ceb522011-09-22 10:46:35 -0700725 mod_timer(&hcon->smp_timer, jiffies + msecs_to_jiffies(SMP_TIMEOUT));
Vinicius Costa Gomesb19d5ce2011-06-14 13:37:41 -0300726
Vinicius Costa Gomesa5474a82011-01-26 21:42:57 -0300727 set_bit(HCI_CONN_ENCRYPT_PEND, &hcon->pend);
Vinicius Costa Gomesa5474a82011-01-26 21:42:57 -0300728
Brian Gix8d0b7d62011-10-12 15:12:42 -0700729 hci_conn_hold(hcon);
730
Vinicius Costa Gomes64532ec2011-06-09 18:50:53 -0300731 return 0;
Anderson Briglia13b48392011-06-09 18:50:42 -0300732}
733
Anderson Briglia133e14c2011-06-09 18:50:40 -0300734int smp_conn_security(struct l2cap_conn *conn, __u8 sec_level)
735{
Vinicius Costa Gomes09fabbc2011-06-09 18:50:43 -0300736 struct hci_conn *hcon = conn->hcon;
Anderson Briglia133e14c2011-06-09 18:50:40 -0300737 __u8 authreq;
738
Brian Gix80fb3a92012-01-31 13:15:20 -0800739 BT_DBG("conn %p hcon %p %d req: %d",
740 conn, hcon, hcon->sec_level, sec_level);
Vinicius Costa Gomes09fabbc2011-06-09 18:50:43 -0300741
Brian Gix80fb3a92012-01-31 13:15:20 -0800742 if (IS_ERR(hcon->hdev->tfm))
Vinicius Costa Gomes09fabbc2011-06-09 18:50:43 -0300743 return 1;
Anderson Briglia133e14c2011-06-09 18:50:40 -0300744
Brian Gix80fb3a92012-01-31 13:15:20 -0800745 if (test_bit(HCI_CONN_ENCRYPT_PEND, &hcon->pend))
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700746 return -EINPROGRESS;
Anderson Briglia133e14c2011-06-09 18:50:40 -0300747
Brian Gix80fb3a92012-01-31 13:15:20 -0800748 if (sec_level == BT_SECURITY_LOW)
Anderson Briglia133e14c2011-06-09 18:50:40 -0300749 return 1;
Vinicius Costa Gomesa5474a82011-01-26 21:42:57 -0300750
Brian Gix80fb3a92012-01-31 13:15:20 -0800751
752 if (hcon->sec_level >= sec_level)
Vinicius Costa Gomesa5474a82011-01-26 21:42:57 -0300753 return 1;
754
755 authreq = seclevel_to_authreq(sec_level);
Anderson Briglia133e14c2011-06-09 18:50:40 -0300756
Brian Gixa68668b2011-08-11 15:49:36 -0700757 hcon->smp_conn = conn;
Brian Gix80fb3a92012-01-31 13:15:20 -0800758 hcon->pending_sec_level = sec_level;
Brian Gixa68668b2011-08-11 15:49:36 -0700759
760 if ((hcon->link_mode & HCI_LM_MASTER) && !hcon->sec_req) {
Vinicius Costa Gomes5d873ca2011-07-07 18:59:41 -0300761 struct link_key *key;
762
763 key = hci_find_link_key_type(hcon->hdev, conn->dst,
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700764 KEY_TYPE_LTK);
Vinicius Costa Gomes5d873ca2011-07-07 18:59:41 -0300765
Brian Gix372257b2011-10-25 09:06:30 -0700766 if (smp_encrypt_link(hcon, key) == 0)
Vinicius Costa Gomes5d873ca2011-07-07 18:59:41 -0300767 goto done;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700768 }
769
Brian Gixa68668b2011-08-11 15:49:36 -0700770 hcon->sec_req = FALSE;
771
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700772 if (hcon->link_mode & HCI_LM_MASTER) {
773 struct smp_cmd_pairing cp;
Anderson Brigliac8e856e2011-06-09 18:50:45 -0300774
Brian Gix7f7e16c2011-11-01 16:27:25 -0700775 /* Switch to Pairing Connection Parameters */
776 hci_le_conn_update(hcon, SMP_MIN_CONN_INTERVAL,
777 SMP_MAX_CONN_INTERVAL, SMP_MAX_CONN_LATENCY,
778 SMP_SUPERVISION_TIMEOUT);
779
Vinicius Costa Gomes10daf972011-07-07 18:59:38 -0300780 build_pairing_cmd(conn, &cp, NULL, authreq);
Brian Gixa68668b2011-08-11 15:49:36 -0700781 hcon->preq[0] = SMP_CMD_PAIRING_REQ;
782 memcpy(&hcon->preq[1], &cp, sizeof(cp));
Anderson Brigliac8e856e2011-06-09 18:50:45 -0300783
Brian Gixe9ceb522011-09-22 10:46:35 -0700784 mod_timer(&hcon->smp_timer, jiffies +
Vinicius Costa Gomesb19d5ce2011-06-14 13:37:41 -0300785 msecs_to_jiffies(SMP_TIMEOUT));
786
Anderson Briglia133e14c2011-06-09 18:50:40 -0300787 smp_send_cmd(conn, SMP_CMD_PAIRING_REQ, sizeof(cp), &cp);
Brian Gix80fb3a92012-01-31 13:15:20 -0800788 hci_conn_hold(hcon);
Anderson Briglia133e14c2011-06-09 18:50:40 -0300789 } else {
790 struct smp_cmd_security_req cp;
791 cp.auth_req = authreq;
792 smp_send_cmd(conn, SMP_CMD_SECURITY_REQ, sizeof(cp), &cp);
793 }
794
Vinicius Costa Gomes5d873ca2011-07-07 18:59:41 -0300795done:
Vinicius Costa Gomesa5474a82011-01-26 21:42:57 -0300796 set_bit(HCI_CONN_ENCRYPT_PEND, &hcon->pend);
797
Anderson Briglia133e14c2011-06-09 18:50:40 -0300798 return 0;
799}
800
Vinicius Costa Gomesc1d5e1d2011-07-07 18:59:34 -0300801static int smp_cmd_encrypt_info(struct l2cap_conn *conn, struct sk_buff *skb)
802{
Brian Gixa68668b2011-08-11 15:49:36 -0700803 struct hci_conn *hcon = conn->hcon;
Vinicius Costa Gomese56cede2011-07-07 18:59:39 -0300804 struct smp_cmd_encrypt_info *rp = (void *) skb->data;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700805 u8 rand[8];
806 int err;
Vinicius Costa Gomese56cede2011-07-07 18:59:39 -0300807
808 skb_pull(skb, sizeof(*rp));
809
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700810 BT_DBG("conn %p", conn);
811
812 memset(rand, 0, sizeof(rand));
813
Brian Gixcf956772011-10-20 15:18:51 -0700814 err = hci_add_ltk(hcon->hdev, 0, conn->dst, hcon->dst_type,
815 0, 0, 0, rand, rp->ltk);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700816 if (err)
817 return SMP_UNSPECIFIED;
Vinicius Costa Gomese56cede2011-07-07 18:59:39 -0300818
Vinicius Costa Gomesc1d5e1d2011-07-07 18:59:34 -0300819 return 0;
820}
821
822static int smp_cmd_master_ident(struct l2cap_conn *conn, struct sk_buff *skb)
823{
Brian Gixa68668b2011-08-11 15:49:36 -0700824 struct hci_conn *hcon = conn->hcon;
Vinicius Costa Gomese56cede2011-07-07 18:59:39 -0300825 struct smp_cmd_master_ident *rp = (void *) skb->data;
Brian Gixa68668b2011-08-11 15:49:36 -0700826 struct smp_cmd_pairing *paircmd = (void *) &hcon->prsp[1];
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700827 struct link_key *key;
Brian Gixa68668b2011-08-11 15:49:36 -0700828 u8 *keydist;
Vinicius Costa Gomesc1d5e1d2011-07-07 18:59:34 -0300829
Vinicius Costa Gomese56cede2011-07-07 18:59:39 -0300830 skb_pull(skb, sizeof(*rp));
831
Brian Gixa68668b2011-08-11 15:49:36 -0700832 key = hci_find_link_key_type(hcon->hdev, conn->dst, KEY_TYPE_LTK);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700833 if (key == NULL)
834 return SMP_UNSPECIFIED;
835
Brian Gixa68668b2011-08-11 15:49:36 -0700836 if (hcon->out)
837 keydist = &paircmd->resp_key_dist;
838 else
839 keydist = &paircmd->init_key_dist;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700840
Brian Gixa68668b2011-08-11 15:49:36 -0700841 BT_DBG("keydist 0x%x", *keydist);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700842
Brian Gixcf956772011-10-20 15:18:51 -0700843 hci_add_ltk(hcon->hdev, 1, conn->dst, hcon->dst_type,
844 hcon->smp_key_size, hcon->auth, rp->ediv,
845 rp->rand, key->val);
Vinicius Costa Gomesc1d5e1d2011-07-07 18:59:34 -0300846
Brian Gixa68668b2011-08-11 15:49:36 -0700847 *keydist &= ~SMP_DIST_ENC_KEY;
848 if (hcon->out) {
849 if (!(*keydist))
850 smp_distribute_keys(conn, 1);
851 }
Vinicius Costa Gomesc1d5e1d2011-07-07 18:59:34 -0300852
853 return 0;
854}
855
Anderson Briglia133e14c2011-06-09 18:50:40 -0300856int smp_sig_channel(struct l2cap_conn *conn, struct sk_buff *skb)
857{
Brian Gixa68668b2011-08-11 15:49:36 -0700858 struct hci_conn *hcon = conn->hcon;
Anderson Briglia133e14c2011-06-09 18:50:40 -0300859 __u8 code = skb->data[0];
860 __u8 reason;
861 int err = 0;
862
Brian Gixa68668b2011-08-11 15:49:36 -0700863 if (IS_ERR(hcon->hdev->tfm)) {
864 err = PTR_ERR(hcon->hdev->tfm);
Vinicius Costa Gomes09fabbc2011-06-09 18:50:43 -0300865 reason = SMP_PAIRING_NOTSUPP;
Brian Gixa68668b2011-08-11 15:49:36 -0700866 BT_ERR("SMP_PAIRING_NOTSUPP %p", hcon->hdev->tfm);
Vinicius Costa Gomes09fabbc2011-06-09 18:50:43 -0300867 goto done;
868 }
869
Brian Gixa68668b2011-08-11 15:49:36 -0700870 hcon->smp_conn = conn;
Anderson Briglia133e14c2011-06-09 18:50:40 -0300871 skb_pull(skb, sizeof(code));
872
873 switch (code) {
874 case SMP_CMD_PAIRING_REQ:
Vinicius Costa Gomes64532ec2011-06-09 18:50:53 -0300875 reason = smp_cmd_pairing_req(conn, skb);
Anderson Briglia133e14c2011-06-09 18:50:40 -0300876 break;
877
878 case SMP_CMD_PAIRING_FAIL:
Vinicius Costa Gomes64532ec2011-06-09 18:50:53 -0300879 reason = 0;
880 err = -EPERM;
Brian Gixe9ceb522011-09-22 10:46:35 -0700881 del_timer(&hcon->smp_timer);
Brian Gix8d0b7d62011-10-12 15:12:42 -0700882 clear_bit(HCI_CONN_ENCRYPT_PEND, &hcon->pend);
Brian Gix570efc92011-10-13 15:59:51 -0700883 mgmt_auth_failed(hcon->hdev->id, conn->dst, skb->data[0]);
Brian Gix6d5fb8a2011-09-09 14:53:04 -0700884 hci_conn_put(hcon);
Anderson Briglia133e14c2011-06-09 18:50:40 -0300885 break;
886
887 case SMP_CMD_PAIRING_RSP:
Vinicius Costa Gomes64532ec2011-06-09 18:50:53 -0300888 reason = smp_cmd_pairing_rsp(conn, skb);
Anderson Briglia13b48392011-06-09 18:50:42 -0300889 break;
890
891 case SMP_CMD_SECURITY_REQ:
Vinicius Costa Gomes64532ec2011-06-09 18:50:53 -0300892 reason = smp_cmd_security_req(conn, skb);
Anderson Briglia13b48392011-06-09 18:50:42 -0300893 break;
894
Anderson Briglia133e14c2011-06-09 18:50:40 -0300895 case SMP_CMD_PAIRING_CONFIRM:
Vinicius Costa Gomes64532ec2011-06-09 18:50:53 -0300896 reason = smp_cmd_pairing_confirm(conn, skb);
Anderson Briglia13b48392011-06-09 18:50:42 -0300897 break;
898
Anderson Briglia133e14c2011-06-09 18:50:40 -0300899 case SMP_CMD_PAIRING_RANDOM:
Vinicius Costa Gomes64532ec2011-06-09 18:50:53 -0300900 reason = smp_cmd_pairing_random(conn, skb);
Anderson Briglia13b48392011-06-09 18:50:42 -0300901 break;
902
Anderson Briglia133e14c2011-06-09 18:50:40 -0300903 case SMP_CMD_ENCRYPT_INFO:
Vinicius Costa Gomesc1d5e1d2011-07-07 18:59:34 -0300904 reason = smp_cmd_encrypt_info(conn, skb);
905 break;
906
Anderson Briglia133e14c2011-06-09 18:50:40 -0300907 case SMP_CMD_MASTER_IDENT:
Vinicius Costa Gomesc1d5e1d2011-07-07 18:59:34 -0300908 reason = smp_cmd_master_ident(conn, skb);
909 break;
910
Anderson Briglia133e14c2011-06-09 18:50:40 -0300911 case SMP_CMD_IDENT_INFO:
912 case SMP_CMD_IDENT_ADDR_INFO:
913 case SMP_CMD_SIGN_INFO:
Vinicius Costa Gomesc1d5e1d2011-07-07 18:59:34 -0300914 /* Just ignored */
915 reason = 0;
916 break;
917
Anderson Briglia133e14c2011-06-09 18:50:40 -0300918 default:
919 BT_DBG("Unknown command code 0x%2.2x", code);
920
921 reason = SMP_CMD_NOTSUPP;
Vinicius Costa Gomes09fabbc2011-06-09 18:50:43 -0300922 err = -EOPNOTSUPP;
923 goto done;
924 }
925
926done:
Brian Gixa68668b2011-08-11 15:49:36 -0700927 if (reason) {
928 BT_ERR("SMP_CMD_PAIRING_FAIL: %d", reason);
Anderson Briglia133e14c2011-06-09 18:50:40 -0300929 smp_send_cmd(conn, SMP_CMD_PAIRING_FAIL, sizeof(reason),
930 &reason);
Brian Gixe9ceb522011-09-22 10:46:35 -0700931 del_timer(&hcon->smp_timer);
Brian Gix8d0b7d62011-10-12 15:12:42 -0700932 clear_bit(HCI_CONN_ENCRYPT_PEND, &hcon->pend);
Brian Gix58ba0772011-09-23 13:40:16 -0700933 mgmt_auth_failed(hcon->hdev->id, conn->dst, reason);
Brian Gix6d5fb8a2011-09-09 14:53:04 -0700934 hci_conn_put(hcon);
Brian Gixa68668b2011-08-11 15:49:36 -0700935 }
Anderson Briglia133e14c2011-06-09 18:50:40 -0300936
937 kfree_skb(skb);
938 return err;
939}
Vinicius Costa Gomesc1d5e1d2011-07-07 18:59:34 -0300940
Brian Gixa68668b2011-08-11 15:49:36 -0700941static int smp_distribute_keys(struct l2cap_conn *conn, __u8 force)
Vinicius Costa Gomesc1d5e1d2011-07-07 18:59:34 -0300942{
Brian Gixa68668b2011-08-11 15:49:36 -0700943 struct hci_conn *hcon = conn->hcon;
Vinicius Costa Gomesc1d5e1d2011-07-07 18:59:34 -0300944 struct smp_cmd_pairing *req, *rsp;
945 __u8 *keydist;
946
947 BT_DBG("conn %p force %d", conn, force);
948
Brian Gixa68668b2011-08-11 15:49:36 -0700949 if (IS_ERR(hcon->hdev->tfm))
950 return PTR_ERR(hcon->hdev->tfm);
Vinicius Costa Gomesc1d5e1d2011-07-07 18:59:34 -0300951
Brian Gixa68668b2011-08-11 15:49:36 -0700952 rsp = (void *) &hcon->prsp[1];
Vinicius Costa Gomesc1d5e1d2011-07-07 18:59:34 -0300953
954 /* The responder sends its keys first */
Brian Gixa68668b2011-08-11 15:49:36 -0700955 if (!force && hcon->out && (rsp->resp_key_dist & 0x07))
Vinicius Costa Gomesc1d5e1d2011-07-07 18:59:34 -0300956 return 0;
957
Brian Gixa68668b2011-08-11 15:49:36 -0700958 req = (void *) &hcon->preq[1];
Vinicius Costa Gomesc1d5e1d2011-07-07 18:59:34 -0300959
Brian Gixa68668b2011-08-11 15:49:36 -0700960 if (hcon->out) {
Vinicius Costa Gomesc1d5e1d2011-07-07 18:59:34 -0300961 keydist = &rsp->init_key_dist;
962 *keydist &= req->init_key_dist;
963 } else {
964 keydist = &rsp->resp_key_dist;
965 *keydist &= req->resp_key_dist;
966 }
967
968
969 BT_DBG("keydist 0x%x", *keydist);
970
971 if (*keydist & SMP_DIST_ENC_KEY) {
972 struct smp_cmd_encrypt_info enc;
973 struct smp_cmd_master_ident ident;
974 __le16 ediv;
975
976 get_random_bytes(enc.ltk, sizeof(enc.ltk));
977 get_random_bytes(&ediv, sizeof(ediv));
978 get_random_bytes(ident.rand, sizeof(ident.rand));
979
980 smp_send_cmd(conn, SMP_CMD_ENCRYPT_INFO, sizeof(enc), &enc);
981
Brian Gixcf956772011-10-20 15:18:51 -0700982 hci_add_ltk(hcon->hdev, 1, conn->dst, hcon->dst_type,
983 hcon->smp_key_size, hcon->auth, ediv,
984 ident.rand, enc.ltk);
Vinicius Costa Gomese56cede2011-07-07 18:59:39 -0300985
Vinicius Costa Gomesc1d5e1d2011-07-07 18:59:34 -0300986 ident.ediv = cpu_to_le16(ediv);
987
988 smp_send_cmd(conn, SMP_CMD_MASTER_IDENT, sizeof(ident), &ident);
989
990 *keydist &= ~SMP_DIST_ENC_KEY;
991 }
992
993 if (*keydist & SMP_DIST_ID_KEY) {
994 struct smp_cmd_ident_addr_info addrinfo;
995 struct smp_cmd_ident_info idinfo;
996
997 /* Send a dummy key */
998 get_random_bytes(idinfo.irk, sizeof(idinfo.irk));
999
1000 smp_send_cmd(conn, SMP_CMD_IDENT_INFO, sizeof(idinfo), &idinfo);
1001
1002 /* Just public address */
1003 memset(&addrinfo, 0, sizeof(addrinfo));
1004 bacpy(&addrinfo.bdaddr, conn->src);
1005
1006 smp_send_cmd(conn, SMP_CMD_IDENT_ADDR_INFO, sizeof(addrinfo),
1007 &addrinfo);
1008
1009 *keydist &= ~SMP_DIST_ID_KEY;
1010 }
1011
1012 if (*keydist & SMP_DIST_SIGN) {
1013 struct smp_cmd_sign_info sign;
1014
1015 /* Send a dummy key */
1016 get_random_bytes(sign.csrk, sizeof(sign.csrk));
1017
1018 smp_send_cmd(conn, SMP_CMD_SIGN_INFO, sizeof(sign), &sign);
1019
1020 *keydist &= ~SMP_DIST_SIGN;
1021 }
1022
Brian Gix2a335262011-11-17 12:59:23 -08001023 if (hcon->out) {
Brian Gixe57c1672011-09-13 12:34:59 -07001024 if (hcon->disconn_cfm_cb)
1025 hcon->disconn_cfm_cb(hcon, 0);
Brian Gixe9ceb522011-09-22 10:46:35 -07001026 del_timer(&hcon->smp_timer);
Brian Gix8d0b7d62011-10-12 15:12:42 -07001027 clear_bit(HCI_CONN_ENCRYPT_PEND, &hcon->pend);
Brian Gix2a335262011-11-17 12:59:23 -08001028 hci_conn_put(hcon);
1029 } else if (rsp->resp_key_dist) {
1030 if (hcon->disconn_cfm_cb)
1031 hcon->disconn_cfm_cb(hcon, SMP_UNSPECIFIED);
1032 clear_bit(HCI_CONN_ENCRYPT_PEND, &hcon->pend);
Brian Gix58ba0772011-09-23 13:40:16 -07001033 mgmt_auth_failed(hcon->hdev->id, conn->dst, SMP_UNSPECIFIED);
Brian Gix6d5fb8a2011-09-09 14:53:04 -07001034 hci_conn_put(hcon);
1035 }
Brian Gixa68668b2011-08-11 15:49:36 -07001036
1037 return 0;
1038}
1039
1040int smp_link_encrypt_cmplt(struct l2cap_conn *conn, u8 status, u8 encrypt)
1041{
1042 struct hci_conn *hcon = conn->hcon;
1043
1044 BT_DBG("smp: %d %d %d", status, encrypt, hcon->sec_req);
1045
Brian Gix8d0b7d62011-10-12 15:12:42 -07001046 clear_bit(HCI_CONN_ENCRYPT_PEND, &hcon->pend);
1047
Brian Gix80fb3a92012-01-31 13:15:20 -08001048 if (!status && encrypt && hcon->sec_level < hcon->pending_sec_level)
1049 hcon->sec_level = hcon->pending_sec_level;
1050
Brian Gixa68668b2011-08-11 15:49:36 -07001051 if (!status && encrypt && !hcon->sec_req)
Brian Gix80fb3a92012-01-31 13:15:20 -08001052 return smp_distribute_keys(conn, 0);
Brian Gixa68668b2011-08-11 15:49:36 -07001053
1054 /* Fall back to Pairing request if failed a Link Security request */
1055 else if (hcon->sec_req && (status || !encrypt))
Brian Gix80fb3a92012-01-31 13:15:20 -08001056 smp_conn_security(conn, hcon->pending_sec_level);
Brian Gixa68668b2011-08-11 15:49:36 -07001057
Brian Gix80fb3a92012-01-31 13:15:20 -08001058 hci_conn_put(hcon);
Brian Gix8d0b7d62011-10-12 15:12:42 -07001059
Vinicius Costa Gomesc1d5e1d2011-07-07 18:59:34 -03001060 return 0;
1061}
Brian Gixe9ceb522011-09-22 10:46:35 -07001062
1063void smp_timeout(unsigned long arg)
1064{
1065 struct l2cap_conn *conn = (void *) arg;
1066 u8 reason = SMP_UNSPECIFIED;
1067
1068 BT_DBG("%p", conn);
1069
1070 smp_send_cmd(conn, SMP_CMD_PAIRING_FAIL, sizeof(reason), &reason);
Brian Gix8d0b7d62011-10-12 15:12:42 -07001071 clear_bit(HCI_CONN_ENCRYPT_PEND, &conn->hcon->pend);
Brian Gix58ba0772011-09-23 13:40:16 -07001072 mgmt_auth_failed(conn->hcon->hdev->id, conn->dst, SMP_UNSPECIFIED);
Brian Gixe9ceb522011-09-22 10:46:35 -07001073 hci_conn_put(conn->hcon);
1074}