blob: 8b2a92ea556b8f53c33ee4dfb13908ac27bf5391 [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;
295
296 /* Initialize key to JUST WORKS */
297 memset(hcon->tk, 0, sizeof(hcon->tk));
298 hcon->tk_valid = FALSE;
299 hcon->auth = auth;
300
301 /* By definition, OOB data will be used if both sides have it available
302 */
303 if (remote_oob && hcon->oob) {
304 method = SMP_REQ_OOB;
305 goto agent_request;
306 }
307
308 BT_DBG("tk_request: auth:%d lcl:%d rem:%d", auth, local_io, remote_io);
309
310 /* If neither side wants MITM, use JUST WORKS */
311 /* If either side has unknown io_caps, use JUST_WORKS */
312 if (!(auth & SMP_AUTH_MITM) ||
313 local_io > SMP_IO_KEYBOARD_DISPLAY ||
314 remote_io > SMP_IO_KEYBOARD_DISPLAY) {
315 hcon->auth &= ~SMP_AUTH_MITM;
316 hcon->tk_valid = TRUE;
317 return 0;
318 }
319
320 /* MITM is now officially requested, but not required */
321 /* Determine what we need (if anything) from the agent */
322 method = gen_method[local_io][remote_io];
323
324 BT_DBG("tk_method: %d", method);
325
326 if (method == SMP_JUST_WORKS || method == SMP_JUST_CFM)
327 hcon->auth &= ~SMP_AUTH_MITM;
328
329 /* Don't bother confirming unbonded JUST_WORKS */
330 if (!(auth & SMP_AUTH_BONDING) && method == SMP_JUST_CFM) {
331 hcon->tk_valid = TRUE;
332 return 0;
333 } else if (method == SMP_JUST_WORKS) {
334 hcon->tk_valid = TRUE;
335 return 0;
336 } else if (method == SMP_OVERLAP) {
337 if (hcon->link_mode & HCI_LM_MASTER)
338 method = SMP_CFM_PASSKEY;
339 else
340 method = SMP_REQ_PASSKEY;
341 }
342
343 BT_DBG("tk_method-2: %d", method);
344
345 if (method == SMP_CFM_PASSKEY) {
346 u8 key[16];
347 /* Generate a passkey for display. It is not valid until
348 * confirmed.
349 */
350 memset(key, 0, sizeof(key));
351 get_random_bytes(&passkey, sizeof(passkey));
352 passkey %= 1000000;
353 put_unaligned_le32(passkey, key);
354 swap128(key, hcon->tk);
355 BT_DBG("PassKey: %d", passkey);
356 }
357
358agent_request:
359 switch (method) {
360 case SMP_REQ_PASSKEY:
361 return mgmt_user_confirm_request(0, HCI_EV_USER_PASSKEY_REQUEST,
362 conn->dst, 0);
363 case SMP_CFM_PASSKEY:
364 default:
365 return mgmt_user_confirm_request(0, HCI_EV_USER_CONFIRM_REQUEST,
366 conn->dst, passkey);
367 }
368}
369
370static int send_pairing_confirm(struct l2cap_conn *conn)
371{
372 struct hci_conn *hcon = conn->hcon;
373 struct crypto_blkcipher *tfm = hcon->hdev->tfm;
374 struct smp_cmd_pairing_confirm cp;
375 int ret;
376 u8 res[16];
377
378 if (conn->hcon->out)
379 ret = smp_c1(tfm, hcon->tk, hcon->prnd, hcon->preq, hcon->prsp,
380 0, conn->src, hcon->dst_type, conn->dst, res);
381 else
382 ret = smp_c1(tfm, hcon->tk, hcon->prnd, hcon->preq, hcon->prsp,
383 hcon->dst_type, conn->dst, 0, conn->src, res);
384
385 if (ret)
386 return SMP_CONFIRM_FAILED;
387
388 swap128(res, cp.confirm_val);
389
390 hcon->cfm_pending = FALSE;
391
392 smp_send_cmd(conn, SMP_CMD_PAIRING_CONFIRM, sizeof(cp), &cp);
393
394 return 0;
395}
396
Brian Gix6d5fb8a2011-09-09 14:53:04 -0700397int le_user_confirm_reply(struct hci_conn *hcon, u16 mgmt_op, void *cp)
Brian Gixa68668b2011-08-11 15:49:36 -0700398{
399 struct mgmt_cp_user_passkey_reply *psk_reply = cp;
Brian Gix6d5fb8a2011-09-09 14:53:04 -0700400 struct l2cap_conn *conn = hcon->smp_conn;
Brian Gixa68668b2011-08-11 15:49:36 -0700401 u8 key[16];
402 u8 reason = 0;
403 int ret = 0;
404
405 BT_DBG("");
406
Brian Gix6d5fb8a2011-09-09 14:53:04 -0700407 hcon->tk_valid = TRUE;
Brian Gixa68668b2011-08-11 15:49:36 -0700408
409 switch (mgmt_op) {
410 case MGMT_OP_USER_CONFIRM_NEG_REPLY:
411 reason = SMP_CONFIRM_FAILED;
412 break;
413 case MGMT_OP_USER_CONFIRM_REPLY:
414 break;
415 case MGMT_OP_USER_PASSKEY_REPLY:
416 memset(key, 0, sizeof(key));
417 BT_DBG("PassKey: %d", psk_reply->passkey);
418 put_unaligned_le32(psk_reply->passkey, key);
Brian Gix6d5fb8a2011-09-09 14:53:04 -0700419 swap128(key, hcon->tk);
Brian Gixa68668b2011-08-11 15:49:36 -0700420 break;
421 default:
422 reason = SMP_CONFIRM_FAILED;
423 ret = -EOPNOTSUPP;
424 break;
425 }
426
427 if (reason) {
428 BT_DBG("smp_send_cmd: SMP_CMD_PAIRING_FAIL");
429 smp_send_cmd(conn, SMP_CMD_PAIRING_FAIL, sizeof(reason),
430 &reason);
Brian Gix6d5fb8a2011-09-09 14:53:04 -0700431 hci_conn_put(hcon);
432 } else if (hcon->cfm_pending) {
Brian Gixa68668b2011-08-11 15:49:36 -0700433 BT_DBG("send_pairing_confirm");
434 ret = send_pairing_confirm(conn);
435 }
436
437 return ret;
438}
439
Vinicius Costa Gomes64532ec2011-06-09 18:50:53 -0300440static u8 smp_cmd_pairing_req(struct l2cap_conn *conn, struct sk_buff *skb)
Anderson Briglia13b48392011-06-09 18:50:42 -0300441{
Brian Gixa68668b2011-08-11 15:49:36 -0700442 struct hci_conn *hcon = conn->hcon;
Vinicius Costa Gomes397d9ae2011-06-14 13:37:42 -0300443 struct smp_cmd_pairing rsp, *req = (void *) skb->data;
444 u8 key_size;
Brian Gixa68668b2011-08-11 15:49:36 -0700445 u8 auth = SMP_AUTH_NONE;
446 int ret;
Anderson Briglia13b48392011-06-09 18:50:42 -0300447
448 BT_DBG("conn %p", conn);
449
Brian Gixa68668b2011-08-11 15:49:36 -0700450 hcon->preq[0] = SMP_CMD_PAIRING_REQ;
451 memcpy(&hcon->preq[1], req, sizeof(*req));
Vinicius Costa Gomes397d9ae2011-06-14 13:37:42 -0300452 skb_pull(skb, sizeof(*req));
Anderson Briglia13b48392011-06-09 18:50:42 -0300453
Brian Gixa68668b2011-08-11 15:49:36 -0700454 if (req->oob_flag && hcon->oob) {
455 /* By definition, OOB data pairing will have MITM protection */
456 auth = req->auth_req | SMP_AUTH_MITM;
457 } else if (req->auth_req & SMP_AUTH_BONDING) {
458 /* We will attempt MITM for all Bonding attempts */
459 auth = SMP_AUTH_BONDING | SMP_AUTH_MITM;
460 }
Vinicius Costa Gomes64532ec2011-06-09 18:50:53 -0300461
462 /* We didn't start the pairing, so no requirements */
Brian Gixa68668b2011-08-11 15:49:36 -0700463 build_pairing_cmd(conn, req, &rsp, auth);
Vinicius Costa Gomes397d9ae2011-06-14 13:37:42 -0300464
465 key_size = min(req->max_key_size, rsp.max_key_size);
466 if (check_enc_key_size(conn, key_size))
467 return SMP_ENC_KEY_SIZE;
Anderson Briglia13b48392011-06-09 18:50:42 -0300468
Brian Gixa68668b2011-08-11 15:49:36 -0700469 ret = smp_rand(hcon->prnd);
470 if (ret)
471 return SMP_UNSPECIFIED;
Anderson Briglia21b8a2b2011-06-09 18:50:46 -0300472
Brian Gixa68668b2011-08-11 15:49:36 -0700473 /* Request setup of TK */
474 ret = tk_request(conn, req->oob_flag, auth, rsp.io_capability,
475 req->io_capability);
476 if (ret)
477 return SMP_UNSPECIFIED;
478
479 hcon->prsp[0] = SMP_CMD_PAIRING_RSP;
480 memcpy(&hcon->prsp[1], &rsp, sizeof(rsp));
Anderson Brigliac8e856e2011-06-09 18:50:45 -0300481
Vinicius Costa Gomes397d9ae2011-06-14 13:37:42 -0300482 smp_send_cmd(conn, SMP_CMD_PAIRING_RSP, sizeof(rsp), &rsp);
Vinicius Costa Gomes64532ec2011-06-09 18:50:53 -0300483
Vinicius Costa Gomesb19d5ce2011-06-14 13:37:41 -0300484 mod_timer(&conn->security_timer, jiffies +
485 msecs_to_jiffies(SMP_TIMEOUT));
486
Vinicius Costa Gomes64532ec2011-06-09 18:50:53 -0300487 return 0;
Anderson Briglia13b48392011-06-09 18:50:42 -0300488}
489
Vinicius Costa Gomes64532ec2011-06-09 18:50:53 -0300490static u8 smp_cmd_pairing_rsp(struct l2cap_conn *conn, struct sk_buff *skb)
Anderson Briglia13b48392011-06-09 18:50:42 -0300491{
Brian Gixa68668b2011-08-11 15:49:36 -0700492 struct hci_conn *hcon = conn->hcon;
Vinicius Costa Gomes397d9ae2011-06-14 13:37:42 -0300493 struct smp_cmd_pairing *req, *rsp = (void *) skb->data;
Brian Gixa68668b2011-08-11 15:49:36 -0700494 u8 key_size, auth = SMP_AUTH_NONE;
Anderson Briglia21b8a2b2011-06-09 18:50:46 -0300495 int ret;
Anderson Briglia13b48392011-06-09 18:50:42 -0300496
497 BT_DBG("conn %p", conn);
498
Vinicius Costa Gomes397d9ae2011-06-14 13:37:42 -0300499 skb_pull(skb, sizeof(*rsp));
Vinicius Costa Gomes64532ec2011-06-09 18:50:53 -0300500
Brian Gixa68668b2011-08-11 15:49:36 -0700501 req = (void *) &hcon->preq[1];
Vinicius Costa Gomes397d9ae2011-06-14 13:37:42 -0300502
503 key_size = min(req->max_key_size, rsp->max_key_size);
504 if (check_enc_key_size(conn, key_size))
505 return SMP_ENC_KEY_SIZE;
506
Brian Gixa68668b2011-08-11 15:49:36 -0700507 hcon->prsp[0] = SMP_CMD_PAIRING_RSP;
508 memcpy(&hcon->prsp[1], rsp, sizeof(*rsp));
Vinicius Costa Gomes64532ec2011-06-09 18:50:53 -0300509
Brian Gixa68668b2011-08-11 15:49:36 -0700510 ret = smp_rand(hcon->prnd);
Anderson Briglia21b8a2b2011-06-09 18:50:46 -0300511 if (ret)
Vinicius Costa Gomes64532ec2011-06-09 18:50:53 -0300512 return SMP_UNSPECIFIED;
Anderson Briglia21b8a2b2011-06-09 18:50:46 -0300513
Brian Gixa68668b2011-08-11 15:49:36 -0700514 if ((req->auth_req & SMP_AUTH_BONDING) &&
515 (rsp->auth_req & SMP_AUTH_BONDING))
516 auth = SMP_AUTH_BONDING;
517
518 auth |= (req->auth_req | rsp->auth_req) & SMP_AUTH_MITM;
519
520 ret = tk_request(conn, req->oob_flag, auth, rsp->io_capability,
521 req->io_capability);
Anderson Briglia21b8a2b2011-06-09 18:50:46 -0300522 if (ret)
Vinicius Costa Gomes64532ec2011-06-09 18:50:53 -0300523 return SMP_UNSPECIFIED;
Anderson Briglia21b8a2b2011-06-09 18:50:46 -0300524
Brian Gixa68668b2011-08-11 15:49:36 -0700525 hcon->cfm_pending = TRUE;
Anderson Briglia21b8a2b2011-06-09 18:50:46 -0300526
Brian Gixa68668b2011-08-11 15:49:36 -0700527 /* Can't compose response until we have been confirmed */
528 if (!hcon->tk_valid)
529 return 0;
530
531 ret = send_pairing_confirm(conn);
532 if (ret)
533 return SMP_CONFIRM_FAILED;
Vinicius Costa Gomes64532ec2011-06-09 18:50:53 -0300534
535 return 0;
Anderson Briglia13b48392011-06-09 18:50:42 -0300536}
537
Vinicius Costa Gomes64532ec2011-06-09 18:50:53 -0300538static u8 smp_cmd_pairing_confirm(struct l2cap_conn *conn, struct sk_buff *skb)
Anderson Briglia13b48392011-06-09 18:50:42 -0300539{
Brian Gixa68668b2011-08-11 15:49:36 -0700540 struct hci_conn *hcon = conn->hcon;
541 int ret;
Anderson Briglia21b8a2b2011-06-09 18:50:46 -0300542
Anderson Briglia13b48392011-06-09 18:50:42 -0300543 BT_DBG("conn %p %s", conn, conn->hcon->out ? "master" : "slave");
544
Brian Gixa68668b2011-08-11 15:49:36 -0700545 memcpy(hcon->pcnf, skb->data, sizeof(hcon->pcnf));
546 skb_pull(skb, sizeof(hcon->pcnf));
Anderson Briglia21b8a2b2011-06-09 18:50:46 -0300547
Anderson Briglia13b48392011-06-09 18:50:42 -0300548 if (conn->hcon->out) {
Anderson Briglia21b8a2b2011-06-09 18:50:46 -0300549 u8 random[16];
Anderson Briglia13b48392011-06-09 18:50:42 -0300550
Brian Gixa68668b2011-08-11 15:49:36 -0700551 swap128(hcon->prnd, random);
Anderson Briglia13b48392011-06-09 18:50:42 -0300552 smp_send_cmd(conn, SMP_CMD_PAIRING_RANDOM, sizeof(random),
Anderson Briglia21b8a2b2011-06-09 18:50:46 -0300553 random);
Brian Gixa68668b2011-08-11 15:49:36 -0700554 } else if (hcon->tk_valid) {
555 ret = send_pairing_confirm(conn);
Anderson Briglia13b48392011-06-09 18:50:42 -0300556
Anderson Briglia21b8a2b2011-06-09 18:50:46 -0300557 if (ret)
Vinicius Costa Gomes64532ec2011-06-09 18:50:53 -0300558 return SMP_CONFIRM_FAILED;
Brian Gixa68668b2011-08-11 15:49:36 -0700559 } else
560 hcon->cfm_pending = TRUE;
Anderson Briglia21b8a2b2011-06-09 18:50:46 -0300561
Vinicius Costa Gomes64532ec2011-06-09 18:50:53 -0300562
Vinicius Costa Gomesb19d5ce2011-06-14 13:37:41 -0300563 mod_timer(&conn->security_timer, jiffies +
564 msecs_to_jiffies(SMP_TIMEOUT));
565
Vinicius Costa Gomes64532ec2011-06-09 18:50:53 -0300566 return 0;
Anderson Briglia13b48392011-06-09 18:50:42 -0300567}
568
Vinicius Costa Gomes64532ec2011-06-09 18:50:53 -0300569static u8 smp_cmd_pairing_random(struct l2cap_conn *conn, struct sk_buff *skb)
Anderson Briglia13b48392011-06-09 18:50:42 -0300570{
Vinicius Costa Gomes735038c2011-06-09 18:50:47 -0300571 struct hci_conn *hcon = conn->hcon;
572 struct crypto_blkcipher *tfm = hcon->hdev->tfm;
Anderson Briglia21b8a2b2011-06-09 18:50:46 -0300573 int ret;
Vinicius Costa Gomesc34e25e2011-06-09 18:50:48 -0300574 u8 key[16], res[16], random[16], confirm[16];
Anderson Briglia21b8a2b2011-06-09 18:50:46 -0300575
576 swap128(skb->data, random);
577 skb_pull(skb, sizeof(random));
578
579 if (conn->hcon->out)
Brian Gixa68668b2011-08-11 15:49:36 -0700580 ret = smp_c1(tfm, hcon->tk, random, hcon->preq, hcon->prsp, 0,
581 conn->src, hcon->dst_type, conn->dst,
Anderson Briglia21b8a2b2011-06-09 18:50:46 -0300582 res);
583 else
Brian Gixa68668b2011-08-11 15:49:36 -0700584 ret = smp_c1(tfm, hcon->tk, random, hcon->preq, hcon->prsp,
585 hcon->dst_type, conn->dst, 0, conn->src,
Anderson Briglia21b8a2b2011-06-09 18:50:46 -0300586 res);
587 if (ret)
Vinicius Costa Gomes64532ec2011-06-09 18:50:53 -0300588 return SMP_UNSPECIFIED;
Anderson Briglia13b48392011-06-09 18:50:42 -0300589
590 BT_DBG("conn %p %s", conn, conn->hcon->out ? "master" : "slave");
591
Anderson Briglia21b8a2b2011-06-09 18:50:46 -0300592 swap128(res, confirm);
593
Brian Gixa68668b2011-08-11 15:49:36 -0700594 if (memcmp(hcon->pcnf, confirm, sizeof(hcon->pcnf)) != 0) {
Anderson Briglia21b8a2b2011-06-09 18:50:46 -0300595 BT_ERR("Pairing failed (confirmation values mismatch)");
Vinicius Costa Gomes64532ec2011-06-09 18:50:53 -0300596 return SMP_CONFIRM_FAILED;
Anderson Briglia21b8a2b2011-06-09 18:50:46 -0300597 }
Anderson Briglia13b48392011-06-09 18:50:42 -0300598
599 if (conn->hcon->out) {
Vinicius Costa Gomesf1b45c52011-07-07 18:59:40 -0300600 u8 stk[16], rand[8];
Vinicius Costa Gomes735038c2011-06-09 18:50:47 -0300601 __le16 ediv;
Vinicius Costa Gomes397d9ae2011-06-14 13:37:42 -0300602
Vinicius Costa Gomes735038c2011-06-09 18:50:47 -0300603 memset(rand, 0, sizeof(rand));
604 ediv = 0;
Vinicius Costa Gomesf1b45c52011-07-07 18:59:40 -0300605
Brian Gixa68668b2011-08-11 15:49:36 -0700606 smp_s1(tfm, hcon->tk, random, hcon->prnd, key);
Vinicius Costa Gomesf1b45c52011-07-07 18:59:40 -0300607 swap128(key, stk);
608
Brian Gixa68668b2011-08-11 15:49:36 -0700609 memset(stk + hcon->smp_key_size, 0,
610 SMP_MAX_ENC_KEY_SIZE - hcon->smp_key_size);
Vinicius Costa Gomesf1b45c52011-07-07 18:59:40 -0300611
612 hci_le_start_enc(hcon, ediv, rand, stk);
Brian Gixa68668b2011-08-11 15:49:36 -0700613 hcon->enc_key_size = hcon->smp_key_size;
Anderson Briglia21b8a2b2011-06-09 18:50:46 -0300614 } else {
Vinicius Costa Gomesf1b45c52011-07-07 18:59:40 -0300615 u8 stk[16], r[16], rand[8];
616 __le16 ediv;
617
618 memset(rand, 0, sizeof(rand));
619 ediv = 0;
Anderson Briglia21b8a2b2011-06-09 18:50:46 -0300620
Brian Gixa68668b2011-08-11 15:49:36 -0700621 swap128(hcon->prnd, r);
Anderson Briglia21b8a2b2011-06-09 18:50:46 -0300622 smp_send_cmd(conn, SMP_CMD_PAIRING_RANDOM, sizeof(r), r);
623
Brian Gixa68668b2011-08-11 15:49:36 -0700624 smp_s1(tfm, hcon->tk, hcon->prnd, random, key);
Vinicius Costa Gomesf1b45c52011-07-07 18:59:40 -0300625 swap128(key, stk);
Vinicius Costa Gomes397d9ae2011-06-14 13:37:42 -0300626
Brian Gixa68668b2011-08-11 15:49:36 -0700627 memset(stk + hcon->smp_key_size, 0,
628 SMP_MAX_ENC_KEY_SIZE - hcon->smp_key_size);
Vinicius Costa Gomesf1b45c52011-07-07 18:59:40 -0300629
Brian Gixa68668b2011-08-11 15:49:36 -0700630 hci_add_ltk(conn->hcon->hdev, 0, conn->dst, hcon->smp_key_size,
631 hcon->auth, ediv, rand, stk);
Anderson Briglia13b48392011-06-09 18:50:42 -0300632 }
Vinicius Costa Gomes64532ec2011-06-09 18:50:53 -0300633
634 return 0;
Anderson Briglia13b48392011-06-09 18:50:42 -0300635}
636
Vinicius Costa Gomes64532ec2011-06-09 18:50:53 -0300637static u8 smp_cmd_security_req(struct l2cap_conn *conn, struct sk_buff *skb)
Anderson Briglia13b48392011-06-09 18:50:42 -0300638{
Brian Gixa68668b2011-08-11 15:49:36 -0700639 struct hci_conn *hcon = conn->hcon;
Anderson Briglia13b48392011-06-09 18:50:42 -0300640 struct smp_cmd_security_req *rp = (void *) skb->data;
641 struct smp_cmd_pairing cp;
Brian Gixa68668b2011-08-11 15:49:36 -0700642 struct link_key *key;
Anderson Briglia13b48392011-06-09 18:50:42 -0300643
644 BT_DBG("conn %p", conn);
645
Vinicius Costa Gomesa5474a82011-01-26 21:42:57 -0300646 if (test_bit(HCI_CONN_ENCRYPT_PEND, &hcon->pend))
Vinicius Costa Gomes64532ec2011-06-09 18:50:53 -0300647 return 0;
Vinicius Costa Gomesa5474a82011-01-26 21:42:57 -0300648
Brian Gixa68668b2011-08-11 15:49:36 -0700649 key = hci_find_link_key_type(hcon->hdev, conn->dst, KEY_TYPE_LTK);
650 if (key && ((key->auth & SMP_AUTH_MITM) ||
651 !(rp->auth_req & SMP_AUTH_MITM))) {
652 struct key_master_id *master = (void *) key->data;
653
654 hci_le_start_enc(hcon, master->ediv, master->rand,
655 key->val);
656 hcon->enc_key_size = key->pin_len;
657
658 hcon->sec_req = TRUE;
659 hcon->sec_level = authreq_to_seclevel(rp->auth_req);
660
661 return 0;
662 }
663
664 hcon->sec_req = FALSE;
665
Anderson Briglia13b48392011-06-09 18:50:42 -0300666 skb_pull(skb, sizeof(*rp));
Anderson Briglia13b48392011-06-09 18:50:42 -0300667
Vinicius Costa Gomes64532ec2011-06-09 18:50:53 -0300668 memset(&cp, 0, sizeof(cp));
Vinicius Costa Gomes10daf972011-07-07 18:59:38 -0300669 build_pairing_cmd(conn, &cp, NULL, rp->auth_req);
Anderson Briglia13b48392011-06-09 18:50:42 -0300670
Brian Gixa68668b2011-08-11 15:49:36 -0700671 hcon->preq[0] = SMP_CMD_PAIRING_REQ;
672 memcpy(&hcon->preq[1], &cp, sizeof(cp));
Anderson Brigliac8e856e2011-06-09 18:50:45 -0300673
Anderson Briglia13b48392011-06-09 18:50:42 -0300674 smp_send_cmd(conn, SMP_CMD_PAIRING_REQ, sizeof(cp), &cp);
Vinicius Costa Gomesa5474a82011-01-26 21:42:57 -0300675
Vinicius Costa Gomesb19d5ce2011-06-14 13:37:41 -0300676 mod_timer(&conn->security_timer, jiffies +
Brian Gixa68668b2011-08-11 15:49:36 -0700677 msecs_to_jiffies(SMP_TIMEOUT));
Vinicius Costa Gomesb19d5ce2011-06-14 13:37:41 -0300678
Vinicius Costa Gomesa5474a82011-01-26 21:42:57 -0300679 set_bit(HCI_CONN_ENCRYPT_PEND, &hcon->pend);
Vinicius Costa Gomesa5474a82011-01-26 21:42:57 -0300680
Vinicius Costa Gomes64532ec2011-06-09 18:50:53 -0300681 return 0;
Anderson Briglia13b48392011-06-09 18:50:42 -0300682}
683
Anderson Briglia133e14c2011-06-09 18:50:40 -0300684int smp_conn_security(struct l2cap_conn *conn, __u8 sec_level)
685{
Vinicius Costa Gomes09fabbc2011-06-09 18:50:43 -0300686 struct hci_conn *hcon = conn->hcon;
Anderson Briglia133e14c2011-06-09 18:50:40 -0300687 __u8 authreq;
688
Vinicius Costa Gomes09fabbc2011-06-09 18:50:43 -0300689 BT_DBG("conn %p hcon %p level 0x%2.2x", conn, hcon, sec_level);
690
Brian Gixa68668b2011-08-11 15:49:36 -0700691 if (IS_ERR(hcon->hdev->tfm)) {
692 BT_DBG("IS_ERR");
Vinicius Costa Gomes09fabbc2011-06-09 18:50:43 -0300693 return 1;
Brian Gixa68668b2011-08-11 15:49:36 -0700694 }
Anderson Briglia133e14c2011-06-09 18:50:40 -0300695
Brian Gixa68668b2011-08-11 15:49:36 -0700696 if (test_bit(HCI_CONN_ENCRYPT_PEND, &hcon->pend)) {
697 BT_DBG("HCI_CONN_ENCRYPT_PEND");
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700698 return -EINPROGRESS;
Brian Gixa68668b2011-08-11 15:49:36 -0700699 }
Anderson Briglia133e14c2011-06-09 18:50:40 -0300700
Brian Gixa68668b2011-08-11 15:49:36 -0700701 if (sec_level == BT_SECURITY_LOW) {
702 BT_DBG("BT_SECURITY_LOW");
Anderson Briglia133e14c2011-06-09 18:50:40 -0300703 return 1;
Brian Gixa68668b2011-08-11 15:49:36 -0700704 }
Vinicius Costa Gomesa5474a82011-01-26 21:42:57 -0300705
Brian Gixa68668b2011-08-11 15:49:36 -0700706 if (hcon->sec_level > sec_level) {
707 BT_DBG("hcon->sec_level > sec_level");
Vinicius Costa Gomesa5474a82011-01-26 21:42:57 -0300708 return 1;
Brian Gixa68668b2011-08-11 15:49:36 -0700709 }
Vinicius Costa Gomesa5474a82011-01-26 21:42:57 -0300710
711 authreq = seclevel_to_authreq(sec_level);
Anderson Briglia133e14c2011-06-09 18:50:40 -0300712
Brian Gixa68668b2011-08-11 15:49:36 -0700713 BT_ERR("conn = %p, sec: %d", conn, sec_level);
714 hcon->smp_conn = conn;
715 hcon->sec_level = sec_level;
716
717 if ((hcon->link_mode & HCI_LM_MASTER) && !hcon->sec_req) {
Vinicius Costa Gomes5d873ca2011-07-07 18:59:41 -0300718 struct link_key *key;
719
720 key = hci_find_link_key_type(hcon->hdev, conn->dst,
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700721 KEY_TYPE_LTK);
Vinicius Costa Gomes5d873ca2011-07-07 18:59:41 -0300722 if (key) {
723 struct key_master_id *master = (void *) key->data;
724
725 hci_le_start_enc(hcon, master->ediv, master->rand,
726 key->val);
Vinicius Costa Gomes1fa2de32011-07-08 18:31:45 -0300727 hcon->enc_key_size = key->pin_len;
728
Brian Gixa68668b2011-08-11 15:49:36 -0700729 hcon->sec_req = TRUE;
730
Vinicius Costa Gomes5d873ca2011-07-07 18:59:41 -0300731 goto done;
732 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700733 }
734
Brian Gixa68668b2011-08-11 15:49:36 -0700735 hcon->sec_req = FALSE;
736
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700737 if (hcon->link_mode & HCI_LM_MASTER) {
738 struct smp_cmd_pairing cp;
Anderson Brigliac8e856e2011-06-09 18:50:45 -0300739
Vinicius Costa Gomes10daf972011-07-07 18:59:38 -0300740 build_pairing_cmd(conn, &cp, NULL, authreq);
Brian Gixa68668b2011-08-11 15:49:36 -0700741 hcon->preq[0] = SMP_CMD_PAIRING_REQ;
742 memcpy(&hcon->preq[1], &cp, sizeof(cp));
Anderson Brigliac8e856e2011-06-09 18:50:45 -0300743
Vinicius Costa Gomesb19d5ce2011-06-14 13:37:41 -0300744 mod_timer(&conn->security_timer, jiffies +
745 msecs_to_jiffies(SMP_TIMEOUT));
746
Anderson Briglia133e14c2011-06-09 18:50:40 -0300747 smp_send_cmd(conn, SMP_CMD_PAIRING_REQ, sizeof(cp), &cp);
748 } else {
749 struct smp_cmd_security_req cp;
750 cp.auth_req = authreq;
751 smp_send_cmd(conn, SMP_CMD_SECURITY_REQ, sizeof(cp), &cp);
752 }
753
Vinicius Costa Gomes5d873ca2011-07-07 18:59:41 -0300754done:
Vinicius Costa Gomesa5474a82011-01-26 21:42:57 -0300755 hcon->pending_sec_level = sec_level;
756 set_bit(HCI_CONN_ENCRYPT_PEND, &hcon->pend);
757
Anderson Briglia133e14c2011-06-09 18:50:40 -0300758 return 0;
759}
760
Vinicius Costa Gomesc1d5e1d2011-07-07 18:59:34 -0300761static int smp_cmd_encrypt_info(struct l2cap_conn *conn, struct sk_buff *skb)
762{
Brian Gixa68668b2011-08-11 15:49:36 -0700763 struct hci_conn *hcon = conn->hcon;
Vinicius Costa Gomese56cede2011-07-07 18:59:39 -0300764 struct smp_cmd_encrypt_info *rp = (void *) skb->data;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700765 u8 rand[8];
766 int err;
Vinicius Costa Gomese56cede2011-07-07 18:59:39 -0300767
768 skb_pull(skb, sizeof(*rp));
769
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700770 BT_DBG("conn %p", conn);
771
772 memset(rand, 0, sizeof(rand));
773
Brian Gixa68668b2011-08-11 15:49:36 -0700774 err = hci_add_ltk(hcon->hdev, 0, conn->dst, 0, 0, 0,
775 rand, rp->ltk);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700776 if (err)
777 return SMP_UNSPECIFIED;
Vinicius Costa Gomese56cede2011-07-07 18:59:39 -0300778
Vinicius Costa Gomesc1d5e1d2011-07-07 18:59:34 -0300779 return 0;
780}
781
782static int smp_cmd_master_ident(struct l2cap_conn *conn, struct sk_buff *skb)
783{
Brian Gixa68668b2011-08-11 15:49:36 -0700784 struct hci_conn *hcon = conn->hcon;
Vinicius Costa Gomese56cede2011-07-07 18:59:39 -0300785 struct smp_cmd_master_ident *rp = (void *) skb->data;
Brian Gixa68668b2011-08-11 15:49:36 -0700786 struct smp_cmd_pairing *paircmd = (void *) &hcon->prsp[1];
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700787 struct link_key *key;
Brian Gixa68668b2011-08-11 15:49:36 -0700788 u8 *keydist;
Vinicius Costa Gomesc1d5e1d2011-07-07 18:59:34 -0300789
Vinicius Costa Gomese56cede2011-07-07 18:59:39 -0300790 skb_pull(skb, sizeof(*rp));
791
Brian Gixa68668b2011-08-11 15:49:36 -0700792 key = hci_find_link_key_type(hcon->hdev, conn->dst, KEY_TYPE_LTK);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700793 if (key == NULL)
794 return SMP_UNSPECIFIED;
795
Brian Gixa68668b2011-08-11 15:49:36 -0700796 if (hcon->out)
797 keydist = &paircmd->resp_key_dist;
798 else
799 keydist = &paircmd->init_key_dist;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700800
Brian Gixa68668b2011-08-11 15:49:36 -0700801 BT_DBG("keydist 0x%x", *keydist);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700802
Brian Gixa68668b2011-08-11 15:49:36 -0700803 hci_add_ltk(hcon->hdev, 1, conn->dst, hcon->smp_key_size,
804 hcon->auth, rp->ediv, rp->rand, key->val);
Vinicius Costa Gomesc1d5e1d2011-07-07 18:59:34 -0300805
Brian Gixa68668b2011-08-11 15:49:36 -0700806 *keydist &= ~SMP_DIST_ENC_KEY;
807 if (hcon->out) {
808 if (!(*keydist))
809 smp_distribute_keys(conn, 1);
810 }
Vinicius Costa Gomesc1d5e1d2011-07-07 18:59:34 -0300811
812 return 0;
813}
814
Anderson Briglia133e14c2011-06-09 18:50:40 -0300815int smp_sig_channel(struct l2cap_conn *conn, struct sk_buff *skb)
816{
Brian Gixa68668b2011-08-11 15:49:36 -0700817 struct hci_conn *hcon = conn->hcon;
Anderson Briglia133e14c2011-06-09 18:50:40 -0300818 __u8 code = skb->data[0];
819 __u8 reason;
820 int err = 0;
821
Brian Gixa68668b2011-08-11 15:49:36 -0700822 if (IS_ERR(hcon->hdev->tfm)) {
823 err = PTR_ERR(hcon->hdev->tfm);
Vinicius Costa Gomes09fabbc2011-06-09 18:50:43 -0300824 reason = SMP_PAIRING_NOTSUPP;
Brian Gixa68668b2011-08-11 15:49:36 -0700825 BT_ERR("SMP_PAIRING_NOTSUPP %p", hcon->hdev->tfm);
Vinicius Costa Gomes09fabbc2011-06-09 18:50:43 -0300826 goto done;
827 }
828
Brian Gixa68668b2011-08-11 15:49:36 -0700829 hcon->smp_conn = conn;
Anderson Briglia133e14c2011-06-09 18:50:40 -0300830 skb_pull(skb, sizeof(code));
831
832 switch (code) {
833 case SMP_CMD_PAIRING_REQ:
Vinicius Costa Gomes64532ec2011-06-09 18:50:53 -0300834 reason = smp_cmd_pairing_req(conn, skb);
Anderson Briglia133e14c2011-06-09 18:50:40 -0300835 break;
836
837 case SMP_CMD_PAIRING_FAIL:
Vinicius Costa Gomes64532ec2011-06-09 18:50:53 -0300838 reason = 0;
839 err = -EPERM;
Brian Gix6d5fb8a2011-09-09 14:53:04 -0700840 hci_conn_put(hcon);
Anderson Briglia133e14c2011-06-09 18:50:40 -0300841 break;
842
843 case SMP_CMD_PAIRING_RSP:
Vinicius Costa Gomes64532ec2011-06-09 18:50:53 -0300844 reason = smp_cmd_pairing_rsp(conn, skb);
Anderson Briglia13b48392011-06-09 18:50:42 -0300845 break;
846
847 case SMP_CMD_SECURITY_REQ:
Vinicius Costa Gomes64532ec2011-06-09 18:50:53 -0300848 reason = smp_cmd_security_req(conn, skb);
Anderson Briglia13b48392011-06-09 18:50:42 -0300849 break;
850
Anderson Briglia133e14c2011-06-09 18:50:40 -0300851 case SMP_CMD_PAIRING_CONFIRM:
Vinicius Costa Gomes64532ec2011-06-09 18:50:53 -0300852 reason = smp_cmd_pairing_confirm(conn, skb);
Anderson Briglia13b48392011-06-09 18:50:42 -0300853 break;
854
Anderson Briglia133e14c2011-06-09 18:50:40 -0300855 case SMP_CMD_PAIRING_RANDOM:
Vinicius Costa Gomes64532ec2011-06-09 18:50:53 -0300856 reason = smp_cmd_pairing_random(conn, skb);
Anderson Briglia13b48392011-06-09 18:50:42 -0300857 break;
858
Anderson Briglia133e14c2011-06-09 18:50:40 -0300859 case SMP_CMD_ENCRYPT_INFO:
Vinicius Costa Gomesc1d5e1d2011-07-07 18:59:34 -0300860 reason = smp_cmd_encrypt_info(conn, skb);
861 break;
862
Anderson Briglia133e14c2011-06-09 18:50:40 -0300863 case SMP_CMD_MASTER_IDENT:
Vinicius Costa Gomesc1d5e1d2011-07-07 18:59:34 -0300864 reason = smp_cmd_master_ident(conn, skb);
865 break;
866
Anderson Briglia133e14c2011-06-09 18:50:40 -0300867 case SMP_CMD_IDENT_INFO:
868 case SMP_CMD_IDENT_ADDR_INFO:
869 case SMP_CMD_SIGN_INFO:
Vinicius Costa Gomesc1d5e1d2011-07-07 18:59:34 -0300870 /* Just ignored */
871 reason = 0;
872 break;
873
Anderson Briglia133e14c2011-06-09 18:50:40 -0300874 default:
875 BT_DBG("Unknown command code 0x%2.2x", code);
876
877 reason = SMP_CMD_NOTSUPP;
Vinicius Costa Gomes09fabbc2011-06-09 18:50:43 -0300878 err = -EOPNOTSUPP;
879 goto done;
880 }
881
882done:
Brian Gixa68668b2011-08-11 15:49:36 -0700883 if (reason) {
884 BT_ERR("SMP_CMD_PAIRING_FAIL: %d", reason);
Anderson Briglia133e14c2011-06-09 18:50:40 -0300885 smp_send_cmd(conn, SMP_CMD_PAIRING_FAIL, sizeof(reason),
886 &reason);
Brian Gix6d5fb8a2011-09-09 14:53:04 -0700887 hci_conn_put(hcon);
Brian Gixa68668b2011-08-11 15:49:36 -0700888 }
Anderson Briglia133e14c2011-06-09 18:50:40 -0300889
890 kfree_skb(skb);
891 return err;
892}
Vinicius Costa Gomesc1d5e1d2011-07-07 18:59:34 -0300893
Brian Gixa68668b2011-08-11 15:49:36 -0700894static int smp_distribute_keys(struct l2cap_conn *conn, __u8 force)
Vinicius Costa Gomesc1d5e1d2011-07-07 18:59:34 -0300895{
Brian Gixa68668b2011-08-11 15:49:36 -0700896 struct hci_conn *hcon = conn->hcon;
Vinicius Costa Gomesc1d5e1d2011-07-07 18:59:34 -0300897 struct smp_cmd_pairing *req, *rsp;
898 __u8 *keydist;
899
900 BT_DBG("conn %p force %d", conn, force);
901
Brian Gixa68668b2011-08-11 15:49:36 -0700902 if (IS_ERR(hcon->hdev->tfm))
903 return PTR_ERR(hcon->hdev->tfm);
Vinicius Costa Gomesc1d5e1d2011-07-07 18:59:34 -0300904
Brian Gixa68668b2011-08-11 15:49:36 -0700905 rsp = (void *) &hcon->prsp[1];
Vinicius Costa Gomesc1d5e1d2011-07-07 18:59:34 -0300906
907 /* The responder sends its keys first */
Brian Gixa68668b2011-08-11 15:49:36 -0700908 if (!force && hcon->out && (rsp->resp_key_dist & 0x07))
Vinicius Costa Gomesc1d5e1d2011-07-07 18:59:34 -0300909 return 0;
910
Brian Gixa68668b2011-08-11 15:49:36 -0700911 req = (void *) &hcon->preq[1];
Vinicius Costa Gomesc1d5e1d2011-07-07 18:59:34 -0300912
Brian Gixa68668b2011-08-11 15:49:36 -0700913 if (hcon->out) {
Vinicius Costa Gomesc1d5e1d2011-07-07 18:59:34 -0300914 keydist = &rsp->init_key_dist;
915 *keydist &= req->init_key_dist;
916 } else {
917 keydist = &rsp->resp_key_dist;
918 *keydist &= req->resp_key_dist;
919 }
920
921
922 BT_DBG("keydist 0x%x", *keydist);
923
924 if (*keydist & SMP_DIST_ENC_KEY) {
925 struct smp_cmd_encrypt_info enc;
926 struct smp_cmd_master_ident ident;
927 __le16 ediv;
928
929 get_random_bytes(enc.ltk, sizeof(enc.ltk));
930 get_random_bytes(&ediv, sizeof(ediv));
931 get_random_bytes(ident.rand, sizeof(ident.rand));
932
933 smp_send_cmd(conn, SMP_CMD_ENCRYPT_INFO, sizeof(enc), &enc);
934
Brian Gixa68668b2011-08-11 15:49:36 -0700935 hci_add_ltk(hcon->hdev, 1, conn->dst, hcon->smp_key_size,
936 hcon->auth, ediv, ident.rand, enc.ltk);
Vinicius Costa Gomese56cede2011-07-07 18:59:39 -0300937
Vinicius Costa Gomesc1d5e1d2011-07-07 18:59:34 -0300938 ident.ediv = cpu_to_le16(ediv);
939
940 smp_send_cmd(conn, SMP_CMD_MASTER_IDENT, sizeof(ident), &ident);
941
942 *keydist &= ~SMP_DIST_ENC_KEY;
943 }
944
945 if (*keydist & SMP_DIST_ID_KEY) {
946 struct smp_cmd_ident_addr_info addrinfo;
947 struct smp_cmd_ident_info idinfo;
948
949 /* Send a dummy key */
950 get_random_bytes(idinfo.irk, sizeof(idinfo.irk));
951
952 smp_send_cmd(conn, SMP_CMD_IDENT_INFO, sizeof(idinfo), &idinfo);
953
954 /* Just public address */
955 memset(&addrinfo, 0, sizeof(addrinfo));
956 bacpy(&addrinfo.bdaddr, conn->src);
957
958 smp_send_cmd(conn, SMP_CMD_IDENT_ADDR_INFO, sizeof(addrinfo),
959 &addrinfo);
960
961 *keydist &= ~SMP_DIST_ID_KEY;
962 }
963
964 if (*keydist & SMP_DIST_SIGN) {
965 struct smp_cmd_sign_info sign;
966
967 /* Send a dummy key */
968 get_random_bytes(sign.csrk, sizeof(sign.csrk));
969
970 smp_send_cmd(conn, SMP_CMD_SIGN_INFO, sizeof(sign), &sign);
971
972 *keydist &= ~SMP_DIST_SIGN;
973 }
974
Brian Gix6d5fb8a2011-09-09 14:53:04 -0700975 if (hcon->out || rsp->resp_key_dist) {
Brian Gixa68668b2011-08-11 15:49:36 -0700976 hcon->disconn_cfm_cb(hcon, 0);
Brian Gix6d5fb8a2011-09-09 14:53:04 -0700977 hci_conn_put(hcon);
978 }
Brian Gixa68668b2011-08-11 15:49:36 -0700979
980 return 0;
981}
982
983int smp_link_encrypt_cmplt(struct l2cap_conn *conn, u8 status, u8 encrypt)
984{
985 struct hci_conn *hcon = conn->hcon;
986
987 BT_DBG("smp: %d %d %d", status, encrypt, hcon->sec_req);
988
989 if (!status && encrypt && !hcon->sec_req)
990 smp_distribute_keys(conn, 0);
991
992 /* Fall back to Pairing request if failed a Link Security request */
993 else if (hcon->sec_req && (status || !encrypt))
994 smp_conn_security(conn, hcon->sec_level);
995
Vinicius Costa Gomesc1d5e1d2011-07-07 18:59:34 -0300996 return 0;
997}