blob: 4b25081fd9fa251cfeffbf05697ddb04918d4489 [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
397int le_user_confirm_reply(struct hci_conn *hdev, u16 mgmt_op, void *cp)
398{
399 struct mgmt_cp_user_passkey_reply *psk_reply = cp;
400 struct l2cap_conn *conn = hdev->smp_conn;
401 u8 key[16];
402 u8 reason = 0;
403 int ret = 0;
404
405 BT_DBG("");
406
407 hdev->tk_valid = TRUE;
408
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);
419 swap128(key, hdev->tk);
420 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);
431 } else if (hdev->cfm_pending) {
432 BT_DBG("send_pairing_confirm");
433 ret = send_pairing_confirm(conn);
434 }
435
436 return ret;
437}
438
Vinicius Costa Gomes64532ec2011-06-09 18:50:53 -0300439static u8 smp_cmd_pairing_req(struct l2cap_conn *conn, struct sk_buff *skb)
Anderson Briglia13b48392011-06-09 18:50:42 -0300440{
Brian Gixa68668b2011-08-11 15:49:36 -0700441 struct hci_conn *hcon = conn->hcon;
Vinicius Costa Gomes397d9ae2011-06-14 13:37:42 -0300442 struct smp_cmd_pairing rsp, *req = (void *) skb->data;
443 u8 key_size;
Brian Gixa68668b2011-08-11 15:49:36 -0700444 u8 auth = SMP_AUTH_NONE;
445 int ret;
Anderson Briglia13b48392011-06-09 18:50:42 -0300446
447 BT_DBG("conn %p", conn);
448
Brian Gixa68668b2011-08-11 15:49:36 -0700449 hcon->preq[0] = SMP_CMD_PAIRING_REQ;
450 memcpy(&hcon->preq[1], req, sizeof(*req));
Vinicius Costa Gomes397d9ae2011-06-14 13:37:42 -0300451 skb_pull(skb, sizeof(*req));
Anderson Briglia13b48392011-06-09 18:50:42 -0300452
Brian Gixa68668b2011-08-11 15:49:36 -0700453 if (req->oob_flag && hcon->oob) {
454 /* By definition, OOB data pairing will have MITM protection */
455 auth = req->auth_req | SMP_AUTH_MITM;
456 } else if (req->auth_req & SMP_AUTH_BONDING) {
457 /* We will attempt MITM for all Bonding attempts */
458 auth = SMP_AUTH_BONDING | SMP_AUTH_MITM;
459 }
Vinicius Costa Gomes64532ec2011-06-09 18:50:53 -0300460
461 /* We didn't start the pairing, so no requirements */
Brian Gixa68668b2011-08-11 15:49:36 -0700462 build_pairing_cmd(conn, req, &rsp, auth);
Vinicius Costa Gomes397d9ae2011-06-14 13:37:42 -0300463
464 key_size = min(req->max_key_size, rsp.max_key_size);
465 if (check_enc_key_size(conn, key_size))
466 return SMP_ENC_KEY_SIZE;
Anderson Briglia13b48392011-06-09 18:50:42 -0300467
Brian Gixa68668b2011-08-11 15:49:36 -0700468 ret = smp_rand(hcon->prnd);
469 if (ret)
470 return SMP_UNSPECIFIED;
Anderson Briglia21b8a2b2011-06-09 18:50:46 -0300471
Brian Gixa68668b2011-08-11 15:49:36 -0700472 /* Request setup of TK */
473 ret = tk_request(conn, req->oob_flag, auth, rsp.io_capability,
474 req->io_capability);
475 if (ret)
476 return SMP_UNSPECIFIED;
477
478 hcon->prsp[0] = SMP_CMD_PAIRING_RSP;
479 memcpy(&hcon->prsp[1], &rsp, sizeof(rsp));
Anderson Brigliac8e856e2011-06-09 18:50:45 -0300480
Vinicius Costa Gomes397d9ae2011-06-14 13:37:42 -0300481 smp_send_cmd(conn, SMP_CMD_PAIRING_RSP, sizeof(rsp), &rsp);
Vinicius Costa Gomes64532ec2011-06-09 18:50:53 -0300482
Vinicius Costa Gomesb19d5ce2011-06-14 13:37:41 -0300483 mod_timer(&conn->security_timer, jiffies +
484 msecs_to_jiffies(SMP_TIMEOUT));
485
Vinicius Costa Gomes64532ec2011-06-09 18:50:53 -0300486 return 0;
Anderson Briglia13b48392011-06-09 18:50:42 -0300487}
488
Vinicius Costa Gomes64532ec2011-06-09 18:50:53 -0300489static u8 smp_cmd_pairing_rsp(struct l2cap_conn *conn, struct sk_buff *skb)
Anderson Briglia13b48392011-06-09 18:50:42 -0300490{
Brian Gixa68668b2011-08-11 15:49:36 -0700491 struct hci_conn *hcon = conn->hcon;
Vinicius Costa Gomes397d9ae2011-06-14 13:37:42 -0300492 struct smp_cmd_pairing *req, *rsp = (void *) skb->data;
Brian Gixa68668b2011-08-11 15:49:36 -0700493 u8 key_size, auth = SMP_AUTH_NONE;
Anderson Briglia21b8a2b2011-06-09 18:50:46 -0300494 int ret;
Anderson Briglia13b48392011-06-09 18:50:42 -0300495
496 BT_DBG("conn %p", conn);
497
Vinicius Costa Gomes397d9ae2011-06-14 13:37:42 -0300498 skb_pull(skb, sizeof(*rsp));
Vinicius Costa Gomes64532ec2011-06-09 18:50:53 -0300499
Brian Gixa68668b2011-08-11 15:49:36 -0700500 req = (void *) &hcon->preq[1];
Vinicius Costa Gomes397d9ae2011-06-14 13:37:42 -0300501
502 key_size = min(req->max_key_size, rsp->max_key_size);
503 if (check_enc_key_size(conn, key_size))
504 return SMP_ENC_KEY_SIZE;
505
Brian Gixa68668b2011-08-11 15:49:36 -0700506 hcon->prsp[0] = SMP_CMD_PAIRING_RSP;
507 memcpy(&hcon->prsp[1], rsp, sizeof(*rsp));
Vinicius Costa Gomes64532ec2011-06-09 18:50:53 -0300508
Brian Gixa68668b2011-08-11 15:49:36 -0700509 ret = smp_rand(hcon->prnd);
Anderson Briglia21b8a2b2011-06-09 18:50:46 -0300510 if (ret)
Vinicius Costa Gomes64532ec2011-06-09 18:50:53 -0300511 return SMP_UNSPECIFIED;
Anderson Briglia21b8a2b2011-06-09 18:50:46 -0300512
Brian Gixa68668b2011-08-11 15:49:36 -0700513 if ((req->auth_req & SMP_AUTH_BONDING) &&
514 (rsp->auth_req & SMP_AUTH_BONDING))
515 auth = SMP_AUTH_BONDING;
516
517 auth |= (req->auth_req | rsp->auth_req) & SMP_AUTH_MITM;
518
519 ret = tk_request(conn, req->oob_flag, auth, rsp->io_capability,
520 req->io_capability);
Anderson Briglia21b8a2b2011-06-09 18:50:46 -0300521 if (ret)
Vinicius Costa Gomes64532ec2011-06-09 18:50:53 -0300522 return SMP_UNSPECIFIED;
Anderson Briglia21b8a2b2011-06-09 18:50:46 -0300523
Brian Gixa68668b2011-08-11 15:49:36 -0700524 hcon->cfm_pending = TRUE;
Anderson Briglia21b8a2b2011-06-09 18:50:46 -0300525
Brian Gixa68668b2011-08-11 15:49:36 -0700526 /* Can't compose response until we have been confirmed */
527 if (!hcon->tk_valid)
528 return 0;
529
530 ret = send_pairing_confirm(conn);
531 if (ret)
532 return SMP_CONFIRM_FAILED;
Vinicius Costa Gomes64532ec2011-06-09 18:50:53 -0300533
534 return 0;
Anderson Briglia13b48392011-06-09 18:50:42 -0300535}
536
Vinicius Costa Gomes64532ec2011-06-09 18:50:53 -0300537static u8 smp_cmd_pairing_confirm(struct l2cap_conn *conn, struct sk_buff *skb)
Anderson Briglia13b48392011-06-09 18:50:42 -0300538{
Brian Gixa68668b2011-08-11 15:49:36 -0700539 struct hci_conn *hcon = conn->hcon;
540 int ret;
Anderson Briglia21b8a2b2011-06-09 18:50:46 -0300541
Anderson Briglia13b48392011-06-09 18:50:42 -0300542 BT_DBG("conn %p %s", conn, conn->hcon->out ? "master" : "slave");
543
Brian Gixa68668b2011-08-11 15:49:36 -0700544 memcpy(hcon->pcnf, skb->data, sizeof(hcon->pcnf));
545 skb_pull(skb, sizeof(hcon->pcnf));
Anderson Briglia21b8a2b2011-06-09 18:50:46 -0300546
Anderson Briglia13b48392011-06-09 18:50:42 -0300547 if (conn->hcon->out) {
Anderson Briglia21b8a2b2011-06-09 18:50:46 -0300548 u8 random[16];
Anderson Briglia13b48392011-06-09 18:50:42 -0300549
Brian Gixa68668b2011-08-11 15:49:36 -0700550 swap128(hcon->prnd, random);
Anderson Briglia13b48392011-06-09 18:50:42 -0300551 smp_send_cmd(conn, SMP_CMD_PAIRING_RANDOM, sizeof(random),
Anderson Briglia21b8a2b2011-06-09 18:50:46 -0300552 random);
Brian Gixa68668b2011-08-11 15:49:36 -0700553 } else if (hcon->tk_valid) {
554 ret = send_pairing_confirm(conn);
Anderson Briglia13b48392011-06-09 18:50:42 -0300555
Anderson Briglia21b8a2b2011-06-09 18:50:46 -0300556 if (ret)
Vinicius Costa Gomes64532ec2011-06-09 18:50:53 -0300557 return SMP_CONFIRM_FAILED;
Brian Gixa68668b2011-08-11 15:49:36 -0700558 } else
559 hcon->cfm_pending = TRUE;
Anderson Briglia21b8a2b2011-06-09 18:50:46 -0300560
Vinicius Costa Gomes64532ec2011-06-09 18:50:53 -0300561
Vinicius Costa Gomesb19d5ce2011-06-14 13:37:41 -0300562 mod_timer(&conn->security_timer, jiffies +
563 msecs_to_jiffies(SMP_TIMEOUT));
564
Vinicius Costa Gomes64532ec2011-06-09 18:50:53 -0300565 return 0;
Anderson Briglia13b48392011-06-09 18:50:42 -0300566}
567
Vinicius Costa Gomes64532ec2011-06-09 18:50:53 -0300568static u8 smp_cmd_pairing_random(struct l2cap_conn *conn, struct sk_buff *skb)
Anderson Briglia13b48392011-06-09 18:50:42 -0300569{
Vinicius Costa Gomes735038c2011-06-09 18:50:47 -0300570 struct hci_conn *hcon = conn->hcon;
571 struct crypto_blkcipher *tfm = hcon->hdev->tfm;
Anderson Briglia21b8a2b2011-06-09 18:50:46 -0300572 int ret;
Vinicius Costa Gomesc34e25e2011-06-09 18:50:48 -0300573 u8 key[16], res[16], random[16], confirm[16];
Anderson Briglia21b8a2b2011-06-09 18:50:46 -0300574
575 swap128(skb->data, random);
576 skb_pull(skb, sizeof(random));
577
578 if (conn->hcon->out)
Brian Gixa68668b2011-08-11 15:49:36 -0700579 ret = smp_c1(tfm, hcon->tk, random, hcon->preq, hcon->prsp, 0,
580 conn->src, hcon->dst_type, conn->dst,
Anderson Briglia21b8a2b2011-06-09 18:50:46 -0300581 res);
582 else
Brian Gixa68668b2011-08-11 15:49:36 -0700583 ret = smp_c1(tfm, hcon->tk, random, hcon->preq, hcon->prsp,
584 hcon->dst_type, conn->dst, 0, conn->src,
Anderson Briglia21b8a2b2011-06-09 18:50:46 -0300585 res);
586 if (ret)
Vinicius Costa Gomes64532ec2011-06-09 18:50:53 -0300587 return SMP_UNSPECIFIED;
Anderson Briglia13b48392011-06-09 18:50:42 -0300588
589 BT_DBG("conn %p %s", conn, conn->hcon->out ? "master" : "slave");
590
Anderson Briglia21b8a2b2011-06-09 18:50:46 -0300591 swap128(res, confirm);
592
Brian Gixa68668b2011-08-11 15:49:36 -0700593 if (memcmp(hcon->pcnf, confirm, sizeof(hcon->pcnf)) != 0) {
Anderson Briglia21b8a2b2011-06-09 18:50:46 -0300594 BT_ERR("Pairing failed (confirmation values mismatch)");
Vinicius Costa Gomes64532ec2011-06-09 18:50:53 -0300595 return SMP_CONFIRM_FAILED;
Anderson Briglia21b8a2b2011-06-09 18:50:46 -0300596 }
Anderson Briglia13b48392011-06-09 18:50:42 -0300597
598 if (conn->hcon->out) {
Vinicius Costa Gomesf1b45c52011-07-07 18:59:40 -0300599 u8 stk[16], rand[8];
Vinicius Costa Gomes735038c2011-06-09 18:50:47 -0300600 __le16 ediv;
Vinicius Costa Gomes397d9ae2011-06-14 13:37:42 -0300601
Vinicius Costa Gomes735038c2011-06-09 18:50:47 -0300602 memset(rand, 0, sizeof(rand));
603 ediv = 0;
Vinicius Costa Gomesf1b45c52011-07-07 18:59:40 -0300604
Brian Gixa68668b2011-08-11 15:49:36 -0700605 smp_s1(tfm, hcon->tk, random, hcon->prnd, key);
Vinicius Costa Gomesf1b45c52011-07-07 18:59:40 -0300606 swap128(key, stk);
607
Brian Gixa68668b2011-08-11 15:49:36 -0700608 memset(stk + hcon->smp_key_size, 0,
609 SMP_MAX_ENC_KEY_SIZE - hcon->smp_key_size);
Vinicius Costa Gomesf1b45c52011-07-07 18:59:40 -0300610
611 hci_le_start_enc(hcon, ediv, rand, stk);
Brian Gixa68668b2011-08-11 15:49:36 -0700612 hcon->enc_key_size = hcon->smp_key_size;
Anderson Briglia21b8a2b2011-06-09 18:50:46 -0300613 } else {
Vinicius Costa Gomesf1b45c52011-07-07 18:59:40 -0300614 u8 stk[16], r[16], rand[8];
615 __le16 ediv;
616
617 memset(rand, 0, sizeof(rand));
618 ediv = 0;
Anderson Briglia21b8a2b2011-06-09 18:50:46 -0300619
Brian Gixa68668b2011-08-11 15:49:36 -0700620 swap128(hcon->prnd, r);
Anderson Briglia21b8a2b2011-06-09 18:50:46 -0300621 smp_send_cmd(conn, SMP_CMD_PAIRING_RANDOM, sizeof(r), r);
622
Brian Gixa68668b2011-08-11 15:49:36 -0700623 smp_s1(tfm, hcon->tk, hcon->prnd, random, key);
Vinicius Costa Gomesf1b45c52011-07-07 18:59:40 -0300624 swap128(key, stk);
Vinicius Costa Gomes397d9ae2011-06-14 13:37:42 -0300625
Brian Gixa68668b2011-08-11 15:49:36 -0700626 memset(stk + hcon->smp_key_size, 0,
627 SMP_MAX_ENC_KEY_SIZE - hcon->smp_key_size);
Vinicius Costa Gomesf1b45c52011-07-07 18:59:40 -0300628
Brian Gixa68668b2011-08-11 15:49:36 -0700629 hci_add_ltk(conn->hcon->hdev, 0, conn->dst, hcon->smp_key_size,
630 hcon->auth, ediv, rand, stk);
Anderson Briglia13b48392011-06-09 18:50:42 -0300631 }
Vinicius Costa Gomes64532ec2011-06-09 18:50:53 -0300632
633 return 0;
Anderson Briglia13b48392011-06-09 18:50:42 -0300634}
635
Vinicius Costa Gomes64532ec2011-06-09 18:50:53 -0300636static u8 smp_cmd_security_req(struct l2cap_conn *conn, struct sk_buff *skb)
Anderson Briglia13b48392011-06-09 18:50:42 -0300637{
Brian Gixa68668b2011-08-11 15:49:36 -0700638 struct hci_conn *hcon = conn->hcon;
Anderson Briglia13b48392011-06-09 18:50:42 -0300639 struct smp_cmd_security_req *rp = (void *) skb->data;
640 struct smp_cmd_pairing cp;
Brian Gixa68668b2011-08-11 15:49:36 -0700641 struct link_key *key;
Anderson Briglia13b48392011-06-09 18:50:42 -0300642
643 BT_DBG("conn %p", conn);
644
Vinicius Costa Gomesa5474a82011-01-26 21:42:57 -0300645 if (test_bit(HCI_CONN_ENCRYPT_PEND, &hcon->pend))
Vinicius Costa Gomes64532ec2011-06-09 18:50:53 -0300646 return 0;
Vinicius Costa Gomesa5474a82011-01-26 21:42:57 -0300647
Brian Gixa68668b2011-08-11 15:49:36 -0700648 key = hci_find_link_key_type(hcon->hdev, conn->dst, KEY_TYPE_LTK);
649 if (key && ((key->auth & SMP_AUTH_MITM) ||
650 !(rp->auth_req & SMP_AUTH_MITM))) {
651 struct key_master_id *master = (void *) key->data;
652
653 hci_le_start_enc(hcon, master->ediv, master->rand,
654 key->val);
655 hcon->enc_key_size = key->pin_len;
656
657 hcon->sec_req = TRUE;
658 hcon->sec_level = authreq_to_seclevel(rp->auth_req);
659
660 return 0;
661 }
662
663 hcon->sec_req = FALSE;
664
Anderson Briglia13b48392011-06-09 18:50:42 -0300665 skb_pull(skb, sizeof(*rp));
Anderson Briglia13b48392011-06-09 18:50:42 -0300666
Vinicius Costa Gomes64532ec2011-06-09 18:50:53 -0300667 memset(&cp, 0, sizeof(cp));
Vinicius Costa Gomes10daf972011-07-07 18:59:38 -0300668 build_pairing_cmd(conn, &cp, NULL, rp->auth_req);
Anderson Briglia13b48392011-06-09 18:50:42 -0300669
Brian Gixa68668b2011-08-11 15:49:36 -0700670 hcon->preq[0] = SMP_CMD_PAIRING_REQ;
671 memcpy(&hcon->preq[1], &cp, sizeof(cp));
Anderson Brigliac8e856e2011-06-09 18:50:45 -0300672
Anderson Briglia13b48392011-06-09 18:50:42 -0300673 smp_send_cmd(conn, SMP_CMD_PAIRING_REQ, sizeof(cp), &cp);
Vinicius Costa Gomesa5474a82011-01-26 21:42:57 -0300674
Vinicius Costa Gomesb19d5ce2011-06-14 13:37:41 -0300675 mod_timer(&conn->security_timer, jiffies +
Brian Gixa68668b2011-08-11 15:49:36 -0700676 msecs_to_jiffies(SMP_TIMEOUT));
Vinicius Costa Gomesb19d5ce2011-06-14 13:37:41 -0300677
Vinicius Costa Gomesa5474a82011-01-26 21:42:57 -0300678 set_bit(HCI_CONN_ENCRYPT_PEND, &hcon->pend);
Vinicius Costa Gomesa5474a82011-01-26 21:42:57 -0300679
Vinicius Costa Gomes64532ec2011-06-09 18:50:53 -0300680 return 0;
Anderson Briglia13b48392011-06-09 18:50:42 -0300681}
682
Anderson Briglia133e14c2011-06-09 18:50:40 -0300683int smp_conn_security(struct l2cap_conn *conn, __u8 sec_level)
684{
Vinicius Costa Gomes09fabbc2011-06-09 18:50:43 -0300685 struct hci_conn *hcon = conn->hcon;
Anderson Briglia133e14c2011-06-09 18:50:40 -0300686 __u8 authreq;
687
Vinicius Costa Gomes09fabbc2011-06-09 18:50:43 -0300688 BT_DBG("conn %p hcon %p level 0x%2.2x", conn, hcon, sec_level);
689
Brian Gixa68668b2011-08-11 15:49:36 -0700690 if (IS_ERR(hcon->hdev->tfm)) {
691 BT_DBG("IS_ERR");
Vinicius Costa Gomes09fabbc2011-06-09 18:50:43 -0300692 return 1;
Brian Gixa68668b2011-08-11 15:49:36 -0700693 }
Anderson Briglia133e14c2011-06-09 18:50:40 -0300694
Brian Gixa68668b2011-08-11 15:49:36 -0700695 if (test_bit(HCI_CONN_ENCRYPT_PEND, &hcon->pend)) {
696 BT_DBG("HCI_CONN_ENCRYPT_PEND");
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700697 return -EINPROGRESS;
Brian Gixa68668b2011-08-11 15:49:36 -0700698 }
Anderson Briglia133e14c2011-06-09 18:50:40 -0300699
Brian Gixa68668b2011-08-11 15:49:36 -0700700 if (sec_level == BT_SECURITY_LOW) {
701 BT_DBG("BT_SECURITY_LOW");
Anderson Briglia133e14c2011-06-09 18:50:40 -0300702 return 1;
Brian Gixa68668b2011-08-11 15:49:36 -0700703 }
Vinicius Costa Gomesa5474a82011-01-26 21:42:57 -0300704
Brian Gixa68668b2011-08-11 15:49:36 -0700705 if (hcon->sec_level > sec_level) {
706 BT_DBG("hcon->sec_level > sec_level");
Vinicius Costa Gomesa5474a82011-01-26 21:42:57 -0300707 return 1;
Brian Gixa68668b2011-08-11 15:49:36 -0700708 }
Vinicius Costa Gomesa5474a82011-01-26 21:42:57 -0300709
710 authreq = seclevel_to_authreq(sec_level);
Anderson Briglia133e14c2011-06-09 18:50:40 -0300711
Brian Gixa68668b2011-08-11 15:49:36 -0700712 BT_ERR("conn = %p, sec: %d", conn, sec_level);
713 hcon->smp_conn = conn;
714 hcon->sec_level = sec_level;
715
716 if ((hcon->link_mode & HCI_LM_MASTER) && !hcon->sec_req) {
Vinicius Costa Gomes5d873ca2011-07-07 18:59:41 -0300717 struct link_key *key;
718
719 key = hci_find_link_key_type(hcon->hdev, conn->dst,
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700720 KEY_TYPE_LTK);
Vinicius Costa Gomes5d873ca2011-07-07 18:59:41 -0300721 if (key) {
722 struct key_master_id *master = (void *) key->data;
723
724 hci_le_start_enc(hcon, master->ediv, master->rand,
725 key->val);
Vinicius Costa Gomes1fa2de32011-07-08 18:31:45 -0300726 hcon->enc_key_size = key->pin_len;
727
Brian Gixa68668b2011-08-11 15:49:36 -0700728 hcon->sec_req = TRUE;
729
Vinicius Costa Gomes5d873ca2011-07-07 18:59:41 -0300730 goto done;
731 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700732 }
733
Brian Gixa68668b2011-08-11 15:49:36 -0700734 hcon->sec_req = FALSE;
735
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700736 if (hcon->link_mode & HCI_LM_MASTER) {
737 struct smp_cmd_pairing cp;
Anderson Brigliac8e856e2011-06-09 18:50:45 -0300738
Vinicius Costa Gomes10daf972011-07-07 18:59:38 -0300739 build_pairing_cmd(conn, &cp, NULL, authreq);
Brian Gixa68668b2011-08-11 15:49:36 -0700740 hcon->preq[0] = SMP_CMD_PAIRING_REQ;
741 memcpy(&hcon->preq[1], &cp, sizeof(cp));
Anderson Brigliac8e856e2011-06-09 18:50:45 -0300742
Vinicius Costa Gomesb19d5ce2011-06-14 13:37:41 -0300743 mod_timer(&conn->security_timer, jiffies +
744 msecs_to_jiffies(SMP_TIMEOUT));
745
Anderson Briglia133e14c2011-06-09 18:50:40 -0300746 smp_send_cmd(conn, SMP_CMD_PAIRING_REQ, sizeof(cp), &cp);
747 } else {
748 struct smp_cmd_security_req cp;
749 cp.auth_req = authreq;
750 smp_send_cmd(conn, SMP_CMD_SECURITY_REQ, sizeof(cp), &cp);
751 }
752
Vinicius Costa Gomes5d873ca2011-07-07 18:59:41 -0300753done:
Vinicius Costa Gomesa5474a82011-01-26 21:42:57 -0300754 hcon->pending_sec_level = sec_level;
755 set_bit(HCI_CONN_ENCRYPT_PEND, &hcon->pend);
756
Anderson Briglia133e14c2011-06-09 18:50:40 -0300757 return 0;
758}
759
Vinicius Costa Gomesc1d5e1d2011-07-07 18:59:34 -0300760static int smp_cmd_encrypt_info(struct l2cap_conn *conn, struct sk_buff *skb)
761{
Brian Gixa68668b2011-08-11 15:49:36 -0700762 struct hci_conn *hcon = conn->hcon;
Vinicius Costa Gomese56cede2011-07-07 18:59:39 -0300763 struct smp_cmd_encrypt_info *rp = (void *) skb->data;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700764 u8 rand[8];
765 int err;
Vinicius Costa Gomese56cede2011-07-07 18:59:39 -0300766
767 skb_pull(skb, sizeof(*rp));
768
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700769 BT_DBG("conn %p", conn);
770
771 memset(rand, 0, sizeof(rand));
772
Brian Gixa68668b2011-08-11 15:49:36 -0700773 err = hci_add_ltk(hcon->hdev, 0, conn->dst, 0, 0, 0,
774 rand, rp->ltk);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700775 if (err)
776 return SMP_UNSPECIFIED;
Vinicius Costa Gomese56cede2011-07-07 18:59:39 -0300777
Vinicius Costa Gomesc1d5e1d2011-07-07 18:59:34 -0300778 return 0;
779}
780
781static int smp_cmd_master_ident(struct l2cap_conn *conn, struct sk_buff *skb)
782{
Brian Gixa68668b2011-08-11 15:49:36 -0700783 struct hci_conn *hcon = conn->hcon;
Vinicius Costa Gomese56cede2011-07-07 18:59:39 -0300784 struct smp_cmd_master_ident *rp = (void *) skb->data;
Brian Gixa68668b2011-08-11 15:49:36 -0700785 struct smp_cmd_pairing *paircmd = (void *) &hcon->prsp[1];
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700786 struct link_key *key;
Brian Gixa68668b2011-08-11 15:49:36 -0700787 u8 *keydist;
Vinicius Costa Gomesc1d5e1d2011-07-07 18:59:34 -0300788
Vinicius Costa Gomese56cede2011-07-07 18:59:39 -0300789 skb_pull(skb, sizeof(*rp));
790
Brian Gixa68668b2011-08-11 15:49:36 -0700791 key = hci_find_link_key_type(hcon->hdev, conn->dst, KEY_TYPE_LTK);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700792 if (key == NULL)
793 return SMP_UNSPECIFIED;
794
Brian Gixa68668b2011-08-11 15:49:36 -0700795 if (hcon->out)
796 keydist = &paircmd->resp_key_dist;
797 else
798 keydist = &paircmd->init_key_dist;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700799
Brian Gixa68668b2011-08-11 15:49:36 -0700800 BT_DBG("keydist 0x%x", *keydist);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700801
Brian Gixa68668b2011-08-11 15:49:36 -0700802 hci_add_ltk(hcon->hdev, 1, conn->dst, hcon->smp_key_size,
803 hcon->auth, rp->ediv, rp->rand, key->val);
Vinicius Costa Gomesc1d5e1d2011-07-07 18:59:34 -0300804
Brian Gixa68668b2011-08-11 15:49:36 -0700805 *keydist &= ~SMP_DIST_ENC_KEY;
806 if (hcon->out) {
807 if (!(*keydist))
808 smp_distribute_keys(conn, 1);
809 }
Vinicius Costa Gomesc1d5e1d2011-07-07 18:59:34 -0300810
811 return 0;
812}
813
Anderson Briglia133e14c2011-06-09 18:50:40 -0300814int smp_sig_channel(struct l2cap_conn *conn, struct sk_buff *skb)
815{
Brian Gixa68668b2011-08-11 15:49:36 -0700816 struct hci_conn *hcon = conn->hcon;
Anderson Briglia133e14c2011-06-09 18:50:40 -0300817 __u8 code = skb->data[0];
818 __u8 reason;
819 int err = 0;
820
Brian Gixa68668b2011-08-11 15:49:36 -0700821 if (IS_ERR(hcon->hdev->tfm)) {
822 err = PTR_ERR(hcon->hdev->tfm);
Vinicius Costa Gomes09fabbc2011-06-09 18:50:43 -0300823 reason = SMP_PAIRING_NOTSUPP;
Brian Gixa68668b2011-08-11 15:49:36 -0700824 BT_ERR("SMP_PAIRING_NOTSUPP %p", hcon->hdev->tfm);
Vinicius Costa Gomes09fabbc2011-06-09 18:50:43 -0300825 goto done;
826 }
827
Brian Gixa68668b2011-08-11 15:49:36 -0700828 hcon->smp_conn = conn;
Anderson Briglia133e14c2011-06-09 18:50:40 -0300829 skb_pull(skb, sizeof(code));
830
831 switch (code) {
832 case SMP_CMD_PAIRING_REQ:
Vinicius Costa Gomes64532ec2011-06-09 18:50:53 -0300833 reason = smp_cmd_pairing_req(conn, skb);
Anderson Briglia133e14c2011-06-09 18:50:40 -0300834 break;
835
836 case SMP_CMD_PAIRING_FAIL:
Vinicius Costa Gomes64532ec2011-06-09 18:50:53 -0300837 reason = 0;
838 err = -EPERM;
Anderson Briglia133e14c2011-06-09 18:50:40 -0300839 break;
840
841 case SMP_CMD_PAIRING_RSP:
Vinicius Costa Gomes64532ec2011-06-09 18:50:53 -0300842 reason = smp_cmd_pairing_rsp(conn, skb);
Anderson Briglia13b48392011-06-09 18:50:42 -0300843 break;
844
845 case SMP_CMD_SECURITY_REQ:
Vinicius Costa Gomes64532ec2011-06-09 18:50:53 -0300846 reason = smp_cmd_security_req(conn, skb);
Anderson Briglia13b48392011-06-09 18:50:42 -0300847 break;
848
Anderson Briglia133e14c2011-06-09 18:50:40 -0300849 case SMP_CMD_PAIRING_CONFIRM:
Vinicius Costa Gomes64532ec2011-06-09 18:50:53 -0300850 reason = smp_cmd_pairing_confirm(conn, skb);
Anderson Briglia13b48392011-06-09 18:50:42 -0300851 break;
852
Anderson Briglia133e14c2011-06-09 18:50:40 -0300853 case SMP_CMD_PAIRING_RANDOM:
Vinicius Costa Gomes64532ec2011-06-09 18:50:53 -0300854 reason = smp_cmd_pairing_random(conn, skb);
Anderson Briglia13b48392011-06-09 18:50:42 -0300855 break;
856
Anderson Briglia133e14c2011-06-09 18:50:40 -0300857 case SMP_CMD_ENCRYPT_INFO:
Vinicius Costa Gomesc1d5e1d2011-07-07 18:59:34 -0300858 reason = smp_cmd_encrypt_info(conn, skb);
859 break;
860
Anderson Briglia133e14c2011-06-09 18:50:40 -0300861 case SMP_CMD_MASTER_IDENT:
Vinicius Costa Gomesc1d5e1d2011-07-07 18:59:34 -0300862 reason = smp_cmd_master_ident(conn, skb);
863 break;
864
Anderson Briglia133e14c2011-06-09 18:50:40 -0300865 case SMP_CMD_IDENT_INFO:
866 case SMP_CMD_IDENT_ADDR_INFO:
867 case SMP_CMD_SIGN_INFO:
Vinicius Costa Gomesc1d5e1d2011-07-07 18:59:34 -0300868 /* Just ignored */
869 reason = 0;
870 break;
871
Anderson Briglia133e14c2011-06-09 18:50:40 -0300872 default:
873 BT_DBG("Unknown command code 0x%2.2x", code);
874
875 reason = SMP_CMD_NOTSUPP;
Vinicius Costa Gomes09fabbc2011-06-09 18:50:43 -0300876 err = -EOPNOTSUPP;
877 goto done;
878 }
879
880done:
Brian Gixa68668b2011-08-11 15:49:36 -0700881 if (reason) {
882 BT_ERR("SMP_CMD_PAIRING_FAIL: %d", reason);
Anderson Briglia133e14c2011-06-09 18:50:40 -0300883 smp_send_cmd(conn, SMP_CMD_PAIRING_FAIL, sizeof(reason),
884 &reason);
Brian Gixa68668b2011-08-11 15:49:36 -0700885 }
Anderson Briglia133e14c2011-06-09 18:50:40 -0300886
887 kfree_skb(skb);
888 return err;
889}
Vinicius Costa Gomesc1d5e1d2011-07-07 18:59:34 -0300890
Brian Gixa68668b2011-08-11 15:49:36 -0700891static int smp_distribute_keys(struct l2cap_conn *conn, __u8 force)
Vinicius Costa Gomesc1d5e1d2011-07-07 18:59:34 -0300892{
Brian Gixa68668b2011-08-11 15:49:36 -0700893 struct hci_conn *hcon = conn->hcon;
Vinicius Costa Gomesc1d5e1d2011-07-07 18:59:34 -0300894 struct smp_cmd_pairing *req, *rsp;
895 __u8 *keydist;
896
897 BT_DBG("conn %p force %d", conn, force);
898
Brian Gixa68668b2011-08-11 15:49:36 -0700899 if (IS_ERR(hcon->hdev->tfm))
900 return PTR_ERR(hcon->hdev->tfm);
Vinicius Costa Gomesc1d5e1d2011-07-07 18:59:34 -0300901
Brian Gixa68668b2011-08-11 15:49:36 -0700902 rsp = (void *) &hcon->prsp[1];
Vinicius Costa Gomesc1d5e1d2011-07-07 18:59:34 -0300903
904 /* The responder sends its keys first */
Brian Gixa68668b2011-08-11 15:49:36 -0700905 if (!force && hcon->out && (rsp->resp_key_dist & 0x07))
Vinicius Costa Gomesc1d5e1d2011-07-07 18:59:34 -0300906 return 0;
907
Brian Gixa68668b2011-08-11 15:49:36 -0700908 req = (void *) &hcon->preq[1];
Vinicius Costa Gomesc1d5e1d2011-07-07 18:59:34 -0300909
Brian Gixa68668b2011-08-11 15:49:36 -0700910 if (hcon->out) {
Vinicius Costa Gomesc1d5e1d2011-07-07 18:59:34 -0300911 keydist = &rsp->init_key_dist;
912 *keydist &= req->init_key_dist;
913 } else {
914 keydist = &rsp->resp_key_dist;
915 *keydist &= req->resp_key_dist;
916 }
917
918
919 BT_DBG("keydist 0x%x", *keydist);
920
921 if (*keydist & SMP_DIST_ENC_KEY) {
922 struct smp_cmd_encrypt_info enc;
923 struct smp_cmd_master_ident ident;
924 __le16 ediv;
925
926 get_random_bytes(enc.ltk, sizeof(enc.ltk));
927 get_random_bytes(&ediv, sizeof(ediv));
928 get_random_bytes(ident.rand, sizeof(ident.rand));
929
930 smp_send_cmd(conn, SMP_CMD_ENCRYPT_INFO, sizeof(enc), &enc);
931
Brian Gixa68668b2011-08-11 15:49:36 -0700932 hci_add_ltk(hcon->hdev, 1, conn->dst, hcon->smp_key_size,
933 hcon->auth, ediv, ident.rand, enc.ltk);
Vinicius Costa Gomese56cede2011-07-07 18:59:39 -0300934
Vinicius Costa Gomesc1d5e1d2011-07-07 18:59:34 -0300935 ident.ediv = cpu_to_le16(ediv);
936
937 smp_send_cmd(conn, SMP_CMD_MASTER_IDENT, sizeof(ident), &ident);
938
939 *keydist &= ~SMP_DIST_ENC_KEY;
940 }
941
942 if (*keydist & SMP_DIST_ID_KEY) {
943 struct smp_cmd_ident_addr_info addrinfo;
944 struct smp_cmd_ident_info idinfo;
945
946 /* Send a dummy key */
947 get_random_bytes(idinfo.irk, sizeof(idinfo.irk));
948
949 smp_send_cmd(conn, SMP_CMD_IDENT_INFO, sizeof(idinfo), &idinfo);
950
951 /* Just public address */
952 memset(&addrinfo, 0, sizeof(addrinfo));
953 bacpy(&addrinfo.bdaddr, conn->src);
954
955 smp_send_cmd(conn, SMP_CMD_IDENT_ADDR_INFO, sizeof(addrinfo),
956 &addrinfo);
957
958 *keydist &= ~SMP_DIST_ID_KEY;
959 }
960
961 if (*keydist & SMP_DIST_SIGN) {
962 struct smp_cmd_sign_info sign;
963
964 /* Send a dummy key */
965 get_random_bytes(sign.csrk, sizeof(sign.csrk));
966
967 smp_send_cmd(conn, SMP_CMD_SIGN_INFO, sizeof(sign), &sign);
968
969 *keydist &= ~SMP_DIST_SIGN;
970 }
971
Brian Gixa68668b2011-08-11 15:49:36 -0700972 if (hcon->out || rsp->resp_key_dist)
973 hcon->disconn_cfm_cb(hcon, 0);
974
975 return 0;
976}
977
978int smp_link_encrypt_cmplt(struct l2cap_conn *conn, u8 status, u8 encrypt)
979{
980 struct hci_conn *hcon = conn->hcon;
981
982 BT_DBG("smp: %d %d %d", status, encrypt, hcon->sec_req);
983
984 if (!status && encrypt && !hcon->sec_req)
985 smp_distribute_keys(conn, 0);
986
987 /* Fall back to Pairing request if failed a Link Security request */
988 else if (hcon->sec_req && (status || !encrypt))
989 smp_conn_security(conn, hcon->sec_level);
990
Vinicius Costa Gomesc1d5e1d2011-07-07 18:59:34 -0300991 return 0;
992}