blob: 6d0658212a9961a064bac8ed624751bdc8adb721 [file] [log] [blame]
Anderson Brigliaeb492e02011-06-09 18:50:40 -03001/*
2 BlueZ - Bluetooth protocol stack for Linux
Bhakthavatsala Raghavendra2738eec2013-02-12 19:44:47 +05303 Copyright (c) 2013 The Linux Foundation. All rights reserved.
Anderson Brigliaeb492e02011-06-09 18:50:40 -03004 Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
5
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License version 2 as
8 published by the Free Software Foundation;
9
10 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
11 OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
12 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF THIRD PARTY RIGHTS.
13 IN NO EVENT SHALL THE COPYRIGHT HOLDER(S) AND AUTHOR(S) BE LIABLE FOR ANY
14 CLAIM, OR ANY SPECIAL INDIRECT OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES
15 WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
16 ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
17 OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
18
19 ALL LIABILITY, INCLUDING LIABILITY FOR INFRINGEMENT OF ANY PATENTS,
20 COPYRIGHTS, TRADEMARKS OR OTHER RIGHTS, RELATING TO USE OF THIS
21 SOFTWARE IS DISCLAIMED.
22*/
23
Steve Mucklef132c6c2012-06-06 18:30:57 -070024#include <linux/interrupt.h>
25#include <linux/module.h>
26
Anderson Brigliaeb492e02011-06-09 18:50:40 -030027#include <net/bluetooth/bluetooth.h>
28#include <net/bluetooth/hci_core.h>
29#include <net/bluetooth/l2cap.h>
Brian Gix2b64d152011-12-21 16:12:12 -080030#include <net/bluetooth/mgmt.h>
Anderson Brigliaeb492e02011-06-09 18:50:40 -030031#include <net/bluetooth/smp.h>
Anderson Brigliad22ef0b2011-06-09 18:50:44 -030032#include <linux/crypto.h>
33#include <crypto/b128ops.h>
Brian Gixa68668b2011-08-11 15:49:36 -070034#include <asm/unaligned.h>
Anderson Brigliad22ef0b2011-06-09 18:50:44 -030035
Vinicius Costa Gomesb19d5ce2011-06-14 13:37:41 -030036#define SMP_TIMEOUT 30000 /* 30 seconds */
37
Brian Gix7f7e16c2011-11-01 16:27:25 -070038#define SMP_MIN_CONN_INTERVAL 40 /* 50ms (40 * 1.25ms) */
39#define SMP_MAX_CONN_INTERVAL 56 /* 70ms (56 * 1.25ms) */
40#define SMP_MAX_CONN_LATENCY 0 /* 0ms (0 * 1.25ms) */
41#define SMP_SUPERVISION_TIMEOUT 500 /* 5 seconds (500 * 10ms) */
42
Brian Gixa68668b2011-08-11 15:49:36 -070043#ifndef FALSE
44#define FALSE 0
45#define TRUE (!FALSE)
46#endif
47
48static int smp_distribute_keys(struct l2cap_conn *conn, __u8 force);
Vinicius Costa Gomes5d3de7d2011-06-14 13:37:41 -030049
Anderson Brigliad22ef0b2011-06-09 18:50:44 -030050static inline void swap128(u8 src[16], u8 dst[16])
51{
52 int i;
53 for (i = 0; i < 16; i++)
54 dst[15 - i] = src[i];
55}
56
57static inline void swap56(u8 src[7], u8 dst[7])
58{
59 int i;
60 for (i = 0; i < 7; i++)
61 dst[6 - i] = src[i];
62}
63
64static int smp_e(struct crypto_blkcipher *tfm, const u8 *k, u8 *r)
65{
66 struct blkcipher_desc desc;
67 struct scatterlist sg;
68 int err, iv_len;
69 unsigned char iv[128];
70
71 if (tfm == NULL) {
72 BT_ERR("tfm %p", tfm);
73 return -EINVAL;
74 }
75
76 desc.tfm = tfm;
77 desc.flags = 0;
78
79 err = crypto_blkcipher_setkey(tfm, k, 16);
80 if (err) {
81 BT_ERR("cipher setkey failed: %d", err);
82 return err;
83 }
84
85 sg_init_one(&sg, r, 16);
86
87 iv_len = crypto_blkcipher_ivsize(tfm);
88 if (iv_len) {
89 memset(&iv, 0xff, iv_len);
90 crypto_blkcipher_set_iv(tfm, iv, iv_len);
91 }
92
93 err = crypto_blkcipher_encrypt(&desc, &sg, &sg, 16);
94 if (err)
95 BT_ERR("Encrypt data error %d", err);
96
97 return err;
98}
99
100static int smp_c1(struct crypto_blkcipher *tfm, u8 k[16], u8 r[16],
101 u8 preq[7], u8 pres[7], u8 _iat, bdaddr_t *ia,
102 u8 _rat, bdaddr_t *ra, u8 res[16])
103{
104 u8 p1[16], p2[16];
105 int err;
106
107 memset(p1, 0, 16);
108
109 /* p1 = pres || preq || _rat || _iat */
110 swap56(pres, p1);
111 swap56(preq, p1 + 7);
112 p1[14] = _rat;
113 p1[15] = _iat;
114
115 memset(p2, 0, 16);
116
117 /* p2 = padding || ia || ra */
118 baswap((bdaddr_t *) (p2 + 4), ia);
119 baswap((bdaddr_t *) (p2 + 10), ra);
120
121 /* res = r XOR p1 */
122 u128_xor((u128 *) res, (u128 *) r, (u128 *) p1);
123
124 /* res = e(k, res) */
125 err = smp_e(tfm, k, res);
126 if (err) {
127 BT_ERR("Encrypt data error");
128 return err;
129 }
130
131 /* res = res XOR p2 */
132 u128_xor((u128 *) res, (u128 *) res, (u128 *) p2);
133
134 /* res = e(k, res) */
135 err = smp_e(tfm, k, res);
136 if (err)
137 BT_ERR("Encrypt data error");
138
139 return err;
140}
141
142static int smp_s1(struct crypto_blkcipher *tfm, u8 k[16],
143 u8 r1[16], u8 r2[16], u8 _r[16])
144{
145 int err;
146
147 /* Just least significant octets from r1 and r2 are considered */
148 memcpy(_r, r1 + 8, 8);
149 memcpy(_r + 8, r2 + 8, 8);
150
151 err = smp_e(tfm, k, _r);
152 if (err)
153 BT_ERR("Encrypt data error");
154
155 return err;
156}
157
158static int smp_rand(u8 *buf)
159{
160 get_random_bytes(buf, 16);
161
162 return 0;
163}
Anderson Brigliaeb492e02011-06-09 18:50:40 -0300164
165static struct sk_buff *smp_build_cmd(struct l2cap_conn *conn, u8 code,
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700166 u16 dlen, void *data)
Anderson Brigliaeb492e02011-06-09 18:50:40 -0300167{
168 struct sk_buff *skb;
169 struct l2cap_hdr *lh;
170 int len;
171
172 len = L2CAP_HDR_SIZE + sizeof(code) + dlen;
173
174 if (len > conn->mtu)
175 return NULL;
176
177 skb = bt_skb_alloc(len, GFP_ATOMIC);
178 if (!skb)
179 return NULL;
180
181 lh = (struct l2cap_hdr *) skb_put(skb, L2CAP_HDR_SIZE);
182 lh->len = cpu_to_le16(sizeof(code) + dlen);
183 lh->cid = cpu_to_le16(L2CAP_CID_SMP);
184
185 memcpy(skb_put(skb, sizeof(code)), &code, sizeof(code));
186
187 memcpy(skb_put(skb, dlen), data, dlen);
188
189 return skb;
190}
191
192static void smp_send_cmd(struct l2cap_conn *conn, u8 code, u16 len, void *data)
193{
194 struct sk_buff *skb = smp_build_cmd(conn, code, len, data);
195
196 BT_DBG("code 0x%2.2x", code);
197
198 if (!skb)
199 return;
200
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700201 hci_send_acl(conn->hcon, NULL, skb, 0);
Anderson Brigliaeb492e02011-06-09 18:50:40 -0300202}
203
Brian Gix2b64d152011-12-21 16:12:12 -0800204static __u8 authreq_to_seclevel(__u8 authreq)
205{
206 if (authreq & SMP_AUTH_MITM)
207 return BT_SECURITY_HIGH;
Brian Gixa68668b2011-08-11 15:49:36 -0700208 else if (authreq & SMP_AUTH_BONDING)
Brian Gix2b64d152011-12-21 16:12:12 -0800209 return BT_SECURITY_MEDIUM;
Brian Gixa68668b2011-08-11 15:49:36 -0700210 else
211 return BT_SECURITY_LOW;
Brian Gix2b64d152011-12-21 16:12:12 -0800212}
213
Vinicius Costa Gomes64532ec2011-06-09 18:50:53 -0300214static __u8 seclevel_to_authreq(__u8 level)
Brian Gix2b64d152011-12-21 16:12:12 -0800215{
Vinicius Costa Gomes64532ec2011-06-09 18:50:53 -0300216 switch (level) {
Bhakthavatsala Raghavendra2738eec2013-02-12 19:44:47 +0530217 case BT_SECURITY_VERY_HIGH:
Brian Gix2b64d152011-12-21 16:12:12 -0800218 case BT_SECURITY_HIGH:
219 return SMP_AUTH_MITM | SMP_AUTH_BONDING;
Vinicius Costa Gomes64532ec2011-06-09 18:50:53 -0300220
Brian Gix2b64d152011-12-21 16:12:12 -0800221 default:
222 return SMP_AUTH_NONE;
223 }
224}
225
Vinicius Costa Gomesb8e66ea2011-06-09 18:50:52 -0300226static void build_pairing_cmd(struct l2cap_conn *conn,
Vinicius Costa Gomes54790f72011-07-07 18:59:38 -0300227 struct smp_cmd_pairing *req,
228 struct smp_cmd_pairing *rsp,
229 __u8 authreq)
Vinicius Costa Gomesb8e66ea2011-06-09 18:50:52 -0300230{
Brian Gixa68668b2011-08-11 15:49:36 -0700231 struct hci_conn *hcon = conn->hcon;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700232 u8 all_keys = 0;
Brian Gix2b64d152011-12-21 16:12:12 -0800233 u8 dist_keys = 0;
Vinicius Costa Gomes54790f72011-07-07 18:59:38 -0300234
Brian Gixa68668b2011-08-11 15:49:36 -0700235 dist_keys = SMP_DIST_ENC_KEY;
236 authreq |= SMP_AUTH_BONDING;
237
238 BT_DBG("conn->hcon->io_capability:%d", conn->hcon->io_capability);
Vinicius Costa Gomes54790f72011-07-07 18:59:38 -0300239
240 if (rsp == NULL) {
241 req->io_capability = conn->hcon->io_capability;
Brian Gixa68668b2011-08-11 15:49:36 -0700242 req->oob_flag = hcon->oob ? SMP_OOB_PRESENT :
243 SMP_OOB_NOT_PRESENT;
Vinicius Costa Gomes54790f72011-07-07 18:59:38 -0300244 req->max_key_size = SMP_MAX_ENC_KEY_SIZE;
Brian Gixa68668b2011-08-11 15:49:36 -0700245 req->init_key_dist = all_keys;
Vinicius Costa Gomes54790f72011-07-07 18:59:38 -0300246 req->resp_key_dist = dist_keys;
247 req->auth_req = authreq;
Brian Gixa68668b2011-08-11 15:49:36 -0700248 BT_DBG("SMP_CMD_PAIRING_REQ %d %d %d %d %2.2x %2.2x",
249 req->io_capability, req->oob_flag,
250 req->auth_req, req->max_key_size,
251 req->init_key_dist, req->resp_key_dist);
Vinicius Costa Gomes54790f72011-07-07 18:59:38 -0300252 return;
253 }
254
Brian Gixa68668b2011-08-11 15:49:36 -0700255 /* Only request OOB if remote AND we support it */
256 if (req->oob_flag)
257 rsp->oob_flag = hcon->oob ? SMP_OOB_PRESENT :
258 SMP_OOB_NOT_PRESENT;
259 else
260 rsp->oob_flag = SMP_OOB_NOT_PRESENT;
261
Vinicius Costa Gomes54790f72011-07-07 18:59:38 -0300262 rsp->io_capability = conn->hcon->io_capability;
Vinicius Costa Gomes54790f72011-07-07 18:59:38 -0300263 rsp->max_key_size = SMP_MAX_ENC_KEY_SIZE;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700264 rsp->init_key_dist = req->init_key_dist & all_keys;
Vinicius Costa Gomes54790f72011-07-07 18:59:38 -0300265 rsp->resp_key_dist = req->resp_key_dist & dist_keys;
266 rsp->auth_req = authreq;
Brian Gixa68668b2011-08-11 15:49:36 -0700267 BT_DBG("SMP_CMD_PAIRING_RSP %d %d %d %d %2.2x %2.2x",
268 req->io_capability, req->oob_flag, req->auth_req,
269 req->max_key_size, req->init_key_dist,
270 req->resp_key_dist);
Vinicius Costa Gomesb8e66ea2011-06-09 18:50:52 -0300271}
272
Vinicius Costa Gomes3158c502011-06-14 13:37:42 -0300273static u8 check_enc_key_size(struct l2cap_conn *conn, __u8 max_key_size)
274{
Brian Gixa68668b2011-08-11 15:49:36 -0700275 struct hci_conn *hcon = conn->hcon;
Vinicius Costa Gomes1c1def02011-09-05 14:31:30 -0300276
Vinicius Costa Gomes3158c502011-06-14 13:37:42 -0300277 if ((max_key_size > SMP_MAX_ENC_KEY_SIZE) ||
278 (max_key_size < SMP_MIN_ENC_KEY_SIZE))
279 return SMP_ENC_KEY_SIZE;
280
Brian Gixa68668b2011-08-11 15:49:36 -0700281 hcon->smp_key_size = max_key_size;
Vinicius Costa Gomes3158c502011-06-14 13:37:42 -0300282
283 return 0;
284}
285
Brian Gixa68668b2011-08-11 15:49:36 -0700286#define JUST_WORKS SMP_JUST_WORKS
287#define REQ_PASSKEY SMP_REQ_PASSKEY
288#define CFM_PASSKEY SMP_CFM_PASSKEY
289#define JUST_CFM SMP_JUST_CFM
290#define OVERLAP SMP_OVERLAP
291static const u8 gen_method[5][5] = {
292 {JUST_WORKS, JUST_CFM, REQ_PASSKEY, JUST_WORKS, REQ_PASSKEY},
293 {JUST_WORKS, JUST_CFM, REQ_PASSKEY, JUST_WORKS, REQ_PASSKEY},
294 {CFM_PASSKEY, CFM_PASSKEY, REQ_PASSKEY, JUST_WORKS, CFM_PASSKEY},
295 {JUST_WORKS, JUST_CFM, JUST_WORKS, JUST_WORKS, JUST_CFM},
296 {CFM_PASSKEY, CFM_PASSKEY, REQ_PASSKEY, JUST_WORKS, OVERLAP}
Brian Gix2b64d152011-12-21 16:12:12 -0800297};
298
299static int tk_request(struct l2cap_conn *conn, u8 remote_oob, u8 auth,
300 u8 local_io, u8 remote_io)
301{
302 struct hci_conn *hcon = conn->hcon;
Brian Gix2b64d152011-12-21 16:12:12 -0800303 u8 method;
304 u32 passkey = 0;
305 int ret = 0;
306
Brian Gixa68668b2011-08-11 15:49:36 -0700307 /* Initialize key to JUST WORKS */
308 memset(hcon->tk, 0, sizeof(hcon->tk));
309 hcon->tk_valid = FALSE;
310 hcon->auth = auth;
311
312 /* By definition, OOB data will be used if both sides have it available
313 */
314 if (remote_oob && hcon->oob) {
315 method = SMP_REQ_OOB;
316 goto agent_request;
317 }
Brian Gix2b64d152011-12-21 16:12:12 -0800318
319 BT_DBG("tk_request: auth:%d lcl:%d rem:%d", auth, local_io, remote_io);
320
321 /* If neither side wants MITM, use JUST WORKS */
Brian Gixa68668b2011-08-11 15:49:36 -0700322 /* If either side has unknown io_caps, use JUST_WORKS */
Brian Gix2b64d152011-12-21 16:12:12 -0800323 if (!(auth & SMP_AUTH_MITM) ||
324 local_io > SMP_IO_KEYBOARD_DISPLAY ||
Brian Gixa68668b2011-08-11 15:49:36 -0700325 remote_io > SMP_IO_KEYBOARD_DISPLAY) {
326 hcon->auth &= ~SMP_AUTH_MITM;
327 hcon->tk_valid = TRUE;
Brian Gix2b64d152011-12-21 16:12:12 -0800328 return 0;
329 }
330
Brian Gixa68668b2011-08-11 15:49:36 -0700331 /* MITM is now officially requested, but not required */
332 /* Determine what we need (if anything) from the agent */
333 method = gen_method[local_io][remote_io];
Brian Gix2b64d152011-12-21 16:12:12 -0800334
Brian Gixa68668b2011-08-11 15:49:36 -0700335 BT_DBG("tk_method: %d", method);
336
337 if (method == SMP_JUST_WORKS || method == SMP_JUST_CFM)
338 hcon->auth &= ~SMP_AUTH_MITM;
339
340 /* Don't bother confirming unbonded JUST_WORKS */
341 if (!(auth & SMP_AUTH_BONDING) && method == SMP_JUST_CFM) {
342 hcon->tk_valid = TRUE;
343 return 0;
344 } else if (method == SMP_JUST_WORKS) {
345 hcon->tk_valid = TRUE;
346 return 0;
347 } else if (method == SMP_OVERLAP) {
Brian Gix2b64d152011-12-21 16:12:12 -0800348 if (hcon->link_mode & HCI_LM_MASTER)
Brian Gixa68668b2011-08-11 15:49:36 -0700349 method = SMP_CFM_PASSKEY;
Brian Gix2b64d152011-12-21 16:12:12 -0800350 else
Brian Gixa68668b2011-08-11 15:49:36 -0700351 method = SMP_REQ_PASSKEY;
Brian Gix2b64d152011-12-21 16:12:12 -0800352 }
353
Brian Gixa68668b2011-08-11 15:49:36 -0700354 BT_DBG("tk_method-2: %d", method);
Brian Gix2b64d152011-12-21 16:12:12 -0800355
Brian Gixa68668b2011-08-11 15:49:36 -0700356 if (method == SMP_CFM_PASSKEY) {
357 u8 key[16];
358 /* Generate a passkey for display. It is not valid until
359 * confirmed.
360 */
Brian Gix2b64d152011-12-21 16:12:12 -0800361 memset(key, 0, sizeof(key));
362 get_random_bytes(&passkey, sizeof(passkey));
363 passkey %= 1000000;
364 put_unaligned_le32(passkey, key);
Brian Gixa68668b2011-08-11 15:49:36 -0700365 swap128(key, hcon->tk);
Brian Gix2b64d152011-12-21 16:12:12 -0800366 BT_DBG("PassKey: %d", passkey);
367 }
368
Brian Gixa68668b2011-08-11 15:49:36 -0700369agent_request:
Brian Gix2b64d152011-12-21 16:12:12 -0800370 hci_dev_lock(hcon->hdev);
371
Brian Gixa68668b2011-08-11 15:49:36 -0700372 switch (method) {
373 case SMP_REQ_PASSKEY:
Brian Gix3dd70172011-09-16 21:38:54 -0700374 ret = mgmt_user_confirm_request(hcon->hdev->id,
375 HCI_EV_USER_PASSKEY_REQUEST, conn->dst, 0);
376 break;
Brian Gixa68668b2011-08-11 15:49:36 -0700377 case SMP_CFM_PASSKEY:
378 default:
Brian Gix3dd70172011-09-16 21:38:54 -0700379 ret = mgmt_user_confirm_request(hcon->hdev->id,
380 HCI_EV_USER_CONFIRM_REQUEST, conn->dst, passkey);
381 break;
Brian Gixa68668b2011-08-11 15:49:36 -0700382 }
Brian Gix2b64d152011-12-21 16:12:12 -0800383
384 hci_dev_unlock(hcon->hdev);
385
386 return ret;
387}
388
Brian Gixa68668b2011-08-11 15:49:36 -0700389static int send_pairing_confirm(struct l2cap_conn *conn)
Vinicius Costa Gomes8aab4752011-09-05 14:31:31 -0300390{
Brian Gixa68668b2011-08-11 15:49:36 -0700391 struct hci_conn *hcon = conn->hcon;
392 struct crypto_blkcipher *tfm = hcon->hdev->tfm;
Vinicius Costa Gomes8aab4752011-09-05 14:31:31 -0300393 struct smp_cmd_pairing_confirm cp;
394 int ret;
Brian Gixa68668b2011-08-11 15:49:36 -0700395 u8 res[16];
Vinicius Costa Gomes8aab4752011-09-05 14:31:31 -0300396
397 if (conn->hcon->out)
Brian Gixa68668b2011-08-11 15:49:36 -0700398 ret = smp_c1(tfm, hcon->tk, hcon->prnd, hcon->preq, hcon->prsp,
399 0, conn->src, hcon->dst_type, conn->dst, res);
Vinicius Costa Gomes8aab4752011-09-05 14:31:31 -0300400 else
Brian Gixa68668b2011-08-11 15:49:36 -0700401 ret = smp_c1(tfm, hcon->tk, hcon->prnd, hcon->preq, hcon->prsp,
402 hcon->dst_type, conn->dst, 0, conn->src, res);
Vinicius Costa Gomes8aab4752011-09-05 14:31:31 -0300403
Brian Gixa68668b2011-08-11 15:49:36 -0700404 if (ret)
405 return SMP_CONFIRM_FAILED;
Brian Gix2b64d152011-12-21 16:12:12 -0800406
Vinicius Costa Gomes8aab4752011-09-05 14:31:31 -0300407 swap128(res, cp.confirm_val);
Vinicius Costa Gomes8aab4752011-09-05 14:31:31 -0300408
Brian Gixa68668b2011-08-11 15:49:36 -0700409 hcon->cfm_pending = FALSE;
Vinicius Costa Gomes8aab4752011-09-05 14:31:31 -0300410
Brian Gixa68668b2011-08-11 15:49:36 -0700411 smp_send_cmd(conn, SMP_CMD_PAIRING_CONFIRM, sizeof(cp), &cp);
Brian Gix2b64d152011-12-21 16:12:12 -0800412
413 return 0;
414}
415
Brian Gix6d5fb8a2011-09-09 14:53:04 -0700416int le_user_confirm_reply(struct hci_conn *hcon, u16 mgmt_op, void *cp)
Brian Gixa68668b2011-08-11 15:49:36 -0700417{
418 struct mgmt_cp_user_passkey_reply *psk_reply = cp;
Brian Gix6d5fb8a2011-09-09 14:53:04 -0700419 struct l2cap_conn *conn = hcon->smp_conn;
Brian Gixa68668b2011-08-11 15:49:36 -0700420 u8 key[16];
421 u8 reason = 0;
422 int ret = 0;
423
424 BT_DBG("");
425
Brian Gix6d5fb8a2011-09-09 14:53:04 -0700426 hcon->tk_valid = TRUE;
Brian Gixa68668b2011-08-11 15:49:36 -0700427
428 switch (mgmt_op) {
429 case MGMT_OP_USER_CONFIRM_NEG_REPLY:
430 reason = SMP_CONFIRM_FAILED;
431 break;
432 case MGMT_OP_USER_CONFIRM_REPLY:
433 break;
434 case MGMT_OP_USER_PASSKEY_REPLY:
435 memset(key, 0, sizeof(key));
436 BT_DBG("PassKey: %d", psk_reply->passkey);
437 put_unaligned_le32(psk_reply->passkey, key);
Brian Gix6d5fb8a2011-09-09 14:53:04 -0700438 swap128(key, hcon->tk);
Brian Gixa68668b2011-08-11 15:49:36 -0700439 break;
440 default:
441 reason = SMP_CONFIRM_FAILED;
442 ret = -EOPNOTSUPP;
443 break;
444 }
445
446 if (reason) {
447 BT_DBG("smp_send_cmd: SMP_CMD_PAIRING_FAIL");
448 smp_send_cmd(conn, SMP_CMD_PAIRING_FAIL, sizeof(reason),
449 &reason);
Brian Gixe9ceb522011-09-22 10:46:35 -0700450 del_timer(&hcon->smp_timer);
Archana Ramachandrand96001b2012-11-14 11:00:48 -0800451 if (hcon->disconn_cfm_cb)
452 hcon->disconn_cfm_cb(hcon, SMP_UNSPECIFIED);
Brian Gix8d0b7d62011-10-12 15:12:42 -0700453 clear_bit(HCI_CONN_ENCRYPT_PEND, &hcon->pend);
Brian Gix58ba0772011-09-23 13:40:16 -0700454 mgmt_auth_failed(hcon->hdev->id, conn->dst, reason);
Brian Gix6d5fb8a2011-09-09 14:53:04 -0700455 hci_conn_put(hcon);
Subramanian Srinivasan6e9f2b02013-05-21 15:42:28 -0700456 l2cap_conn_del(hcon, EACCES, 0);
Brian Gix6d5fb8a2011-09-09 14:53:04 -0700457 } else if (hcon->cfm_pending) {
Brian Gixa68668b2011-08-11 15:49:36 -0700458 BT_DBG("send_pairing_confirm");
459 ret = send_pairing_confirm(conn);
460 }
461
462 return ret;
463}
464
Vinicius Costa Gomesda85e5e2011-06-09 18:50:53 -0300465static u8 smp_cmd_pairing_req(struct l2cap_conn *conn, struct sk_buff *skb)
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300466{
Brian Gixa68668b2011-08-11 15:49:36 -0700467 struct hci_conn *hcon = conn->hcon;
Vinicius Costa Gomes3158c502011-06-14 13:37:42 -0300468 struct smp_cmd_pairing rsp, *req = (void *) skb->data;
469 u8 key_size;
Brian Gix2b64d152011-12-21 16:12:12 -0800470 u8 auth = SMP_AUTH_NONE;
Vinicius Costa Gomes8aab4752011-09-05 14:31:31 -0300471 int ret;
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300472
473 BT_DBG("conn %p", conn);
474
Brian Gixa68668b2011-08-11 15:49:36 -0700475 hcon->preq[0] = SMP_CMD_PAIRING_REQ;
476 memcpy(&hcon->preq[1], req, sizeof(*req));
Vinicius Costa Gomes3158c502011-06-14 13:37:42 -0300477 skb_pull(skb, sizeof(*req));
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300478
Brian Gixa68668b2011-08-11 15:49:36 -0700479 if (req->oob_flag && hcon->oob) {
480 /* By definition, OOB data pairing will have MITM protection */
481 auth = req->auth_req | SMP_AUTH_MITM;
482 } else if (req->auth_req & SMP_AUTH_BONDING) {
483 /* We will attempt MITM for all Bonding attempts */
484 auth = SMP_AUTH_BONDING | SMP_AUTH_MITM;
485 }
Vinicius Costa Gomesda85e5e2011-06-09 18:50:53 -0300486
Vinicius Costa Gomes64532ec2011-06-09 18:50:53 -0300487 /* We didn't start the pairing, so no requirements */
Brian Gix2b64d152011-12-21 16:12:12 -0800488 build_pairing_cmd(conn, req, &rsp, auth);
Vinicius Costa Gomes3158c502011-06-14 13:37:42 -0300489
490 key_size = min(req->max_key_size, rsp.max_key_size);
491 if (check_enc_key_size(conn, key_size))
492 return SMP_ENC_KEY_SIZE;
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300493
Brian Gixa68668b2011-08-11 15:49:36 -0700494 ret = smp_rand(hcon->prnd);
Vinicius Costa Gomes8aab4752011-09-05 14:31:31 -0300495 if (ret)
496 return SMP_UNSPECIFIED;
497
Brian Gixa68668b2011-08-11 15:49:36 -0700498 /* Request setup of TK */
499 ret = tk_request(conn, req->oob_flag, auth, rsp.io_capability,
500 req->io_capability);
501 if (ret)
502 return SMP_UNSPECIFIED;
503
504 hcon->prsp[0] = SMP_CMD_PAIRING_RSP;
505 memcpy(&hcon->prsp[1], &rsp, sizeof(rsp));
Anderson Brigliaf01ead32011-06-09 18:50:45 -0300506
Vinicius Costa Gomes3158c502011-06-14 13:37:42 -0300507 smp_send_cmd(conn, SMP_CMD_PAIRING_RSP, sizeof(rsp), &rsp);
Vinicius Costa Gomesda85e5e2011-06-09 18:50:53 -0300508
Brian Gixe9ceb522011-09-22 10:46:35 -0700509 mod_timer(&hcon->smp_timer, jiffies + msecs_to_jiffies(SMP_TIMEOUT));
Brian Gix2b64d152011-12-21 16:12:12 -0800510
Vinicius Costa Gomesda85e5e2011-06-09 18:50:53 -0300511 return 0;
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300512}
513
Vinicius Costa Gomesda85e5e2011-06-09 18:50:53 -0300514static u8 smp_cmd_pairing_rsp(struct l2cap_conn *conn, struct sk_buff *skb)
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300515{
Brian Gixa68668b2011-08-11 15:49:36 -0700516 struct hci_conn *hcon = conn->hcon;
Vinicius Costa Gomes3158c502011-06-14 13:37:42 -0300517 struct smp_cmd_pairing *req, *rsp = (void *) skb->data;
Brian Gix2b64d152011-12-21 16:12:12 -0800518 u8 key_size, auth = SMP_AUTH_NONE;
Anderson Briglia7d24ddc2011-06-09 18:50:46 -0300519 int ret;
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300520
521 BT_DBG("conn %p", conn);
522
Vinicius Costa Gomes3158c502011-06-14 13:37:42 -0300523 skb_pull(skb, sizeof(*rsp));
Vinicius Costa Gomesda85e5e2011-06-09 18:50:53 -0300524
Brian Gixa68668b2011-08-11 15:49:36 -0700525 req = (void *) &hcon->preq[1];
Vinicius Costa Gomes3158c502011-06-14 13:37:42 -0300526
527 key_size = min(req->max_key_size, rsp->max_key_size);
528 if (check_enc_key_size(conn, key_size))
529 return SMP_ENC_KEY_SIZE;
530
Brian Gixa68668b2011-08-11 15:49:36 -0700531 hcon->prsp[0] = SMP_CMD_PAIRING_RSP;
532 memcpy(&hcon->prsp[1], rsp, sizeof(*rsp));
Vinicius Costa Gomes64532ec2011-06-09 18:50:53 -0300533
Brian Gixa68668b2011-08-11 15:49:36 -0700534 ret = smp_rand(hcon->prnd);
Anderson Briglia7d24ddc2011-06-09 18:50:46 -0300535 if (ret)
Vinicius Costa Gomesda85e5e2011-06-09 18:50:53 -0300536 return SMP_UNSPECIFIED;
Anderson Briglia7d24ddc2011-06-09 18:50:46 -0300537
Brian Gix2b64d152011-12-21 16:12:12 -0800538 if ((req->auth_req & SMP_AUTH_BONDING) &&
539 (rsp->auth_req & SMP_AUTH_BONDING))
540 auth = SMP_AUTH_BONDING;
541
542 auth |= (req->auth_req | rsp->auth_req) & SMP_AUTH_MITM;
543
Brian Gixa68668b2011-08-11 15:49:36 -0700544 ret = tk_request(conn, req->oob_flag, auth, rsp->io_capability,
545 req->io_capability);
Brian Gix2b64d152011-12-21 16:12:12 -0800546 if (ret)
547 return SMP_UNSPECIFIED;
548
Brian Gixa68668b2011-08-11 15:49:36 -0700549 hcon->cfm_pending = TRUE;
Brian Gix2b64d152011-12-21 16:12:12 -0800550
551 /* Can't compose response until we have been confirmed */
Brian Gixa68668b2011-08-11 15:49:36 -0700552 if (!hcon->tk_valid)
Brian Gix2b64d152011-12-21 16:12:12 -0800553 return 0;
554
Brian Gixa68668b2011-08-11 15:49:36 -0700555 ret = send_pairing_confirm(conn);
556 if (ret)
557 return SMP_CONFIRM_FAILED;
Vinicius Costa Gomesda85e5e2011-06-09 18:50:53 -0300558
559 return 0;
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300560}
561
Vinicius Costa Gomesda85e5e2011-06-09 18:50:53 -0300562static u8 smp_cmd_pairing_confirm(struct l2cap_conn *conn, struct sk_buff *skb)
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300563{
Brian Gixa68668b2011-08-11 15:49:36 -0700564 struct hci_conn *hcon = conn->hcon;
565 int ret;
Anderson Briglia7d24ddc2011-06-09 18:50:46 -0300566
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300567 BT_DBG("conn %p %s", conn, conn->hcon->out ? "master" : "slave");
568
Brian Gixa68668b2011-08-11 15:49:36 -0700569 memcpy(hcon->pcnf, skb->data, sizeof(hcon->pcnf));
570 skb_pull(skb, sizeof(hcon->pcnf));
Anderson Briglia7d24ddc2011-06-09 18:50:46 -0300571
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300572 if (conn->hcon->out) {
Anderson Briglia7d24ddc2011-06-09 18:50:46 -0300573 u8 random[16];
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300574
Brian Gixa68668b2011-08-11 15:49:36 -0700575 swap128(hcon->prnd, random);
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300576 smp_send_cmd(conn, SMP_CMD_PAIRING_RANDOM, sizeof(random),
Anderson Briglia7d24ddc2011-06-09 18:50:46 -0300577 random);
Brian Gixa68668b2011-08-11 15:49:36 -0700578 } else if (hcon->tk_valid) {
579 ret = send_pairing_confirm(conn);
Anderson Briglia13b48392011-06-09 18:50:42 -0300580
Anderson Briglia21b8a2b2011-06-09 18:50:46 -0300581 if (ret)
Vinicius Costa Gomes64532ec2011-06-09 18:50:53 -0300582 return SMP_CONFIRM_FAILED;
Brian Gixa68668b2011-08-11 15:49:36 -0700583 } else
584 hcon->cfm_pending = TRUE;
Anderson Briglia21b8a2b2011-06-09 18:50:46 -0300585
Vinicius Costa Gomes64532ec2011-06-09 18:50:53 -0300586
Brian Gixe9ceb522011-09-22 10:46:35 -0700587 mod_timer(&hcon->smp_timer, jiffies + msecs_to_jiffies(SMP_TIMEOUT));
Vinicius Costa Gomesda85e5e2011-06-09 18:50:53 -0300588
589 return 0;
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300590}
591
Vinicius Costa Gomesda85e5e2011-06-09 18:50:53 -0300592static u8 smp_cmd_pairing_random(struct l2cap_conn *conn, struct sk_buff *skb)
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300593{
Vinicius Costa Gomes735038c2011-06-09 18:50:47 -0300594 struct hci_conn *hcon = conn->hcon;
595 struct crypto_blkcipher *tfm = hcon->hdev->tfm;
Anderson Briglia21b8a2b2011-06-09 18:50:46 -0300596 int ret;
Vinicius Costa Gomesc34e25e2011-06-09 18:50:48 -0300597 u8 key[16], res[16], random[16], confirm[16];
Anderson Briglia7d24ddc2011-06-09 18:50:46 -0300598
Anderson Briglia21b8a2b2011-06-09 18:50:46 -0300599 swap128(skb->data, random);
600 skb_pull(skb, sizeof(random));
Anderson Briglia7d24ddc2011-06-09 18:50:46 -0300601
Anderson Briglia21b8a2b2011-06-09 18:50:46 -0300602 if (conn->hcon->out)
Brian Gixa68668b2011-08-11 15:49:36 -0700603 ret = smp_c1(tfm, hcon->tk, random, hcon->preq, hcon->prsp, 0,
604 conn->src, hcon->dst_type, conn->dst,
Anderson Briglia21b8a2b2011-06-09 18:50:46 -0300605 res);
606 else
Brian Gixa68668b2011-08-11 15:49:36 -0700607 ret = smp_c1(tfm, hcon->tk, random, hcon->preq, hcon->prsp,
608 hcon->dst_type, conn->dst, 0, conn->src,
Anderson Briglia21b8a2b2011-06-09 18:50:46 -0300609 res);
610 if (ret)
Vinicius Costa Gomes64532ec2011-06-09 18:50:53 -0300611 return SMP_UNSPECIFIED;
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300612
Anderson Briglia13b48392011-06-09 18:50:42 -0300613 BT_DBG("conn %p %s", conn, conn->hcon->out ? "master" : "slave");
614
Anderson Briglia21b8a2b2011-06-09 18:50:46 -0300615 swap128(res, confirm);
616
Brian Gixa68668b2011-08-11 15:49:36 -0700617 if (memcmp(hcon->pcnf, confirm, sizeof(hcon->pcnf)) != 0) {
Anderson Briglia21b8a2b2011-06-09 18:50:46 -0300618 BT_ERR("Pairing failed (confirmation values mismatch)");
Vinicius Costa Gomes64532ec2011-06-09 18:50:53 -0300619 return SMP_CONFIRM_FAILED;
Anderson Briglia21b8a2b2011-06-09 18:50:46 -0300620 }
Anderson Briglia13b48392011-06-09 18:50:42 -0300621
622 if (conn->hcon->out) {
Vinicius Costa Gomesf1b45c52011-07-07 18:59:40 -0300623 u8 stk[16], rand[8];
Vinicius Costa Gomes735038c2011-06-09 18:50:47 -0300624 __le16 ediv;
Vinicius Costa Gomes397d9ae2011-06-14 13:37:42 -0300625
Vinicius Costa Gomes735038c2011-06-09 18:50:47 -0300626 memset(rand, 0, sizeof(rand));
627 ediv = 0;
Vinicius Costa Gomesf1b45c52011-07-07 18:59:40 -0300628
Brian Gixa68668b2011-08-11 15:49:36 -0700629 smp_s1(tfm, hcon->tk, random, hcon->prnd, key);
Vinicius Costa Gomesf1b45c52011-07-07 18:59:40 -0300630 swap128(key, stk);
631
Brian Gixa68668b2011-08-11 15:49:36 -0700632 memset(stk + hcon->smp_key_size, 0,
633 SMP_MAX_ENC_KEY_SIZE - hcon->smp_key_size);
Vinicius Costa Gomesf1b45c52011-07-07 18:59:40 -0300634
635 hci_le_start_enc(hcon, ediv, rand, stk);
Brian Gixa68668b2011-08-11 15:49:36 -0700636 hcon->enc_key_size = hcon->smp_key_size;
Anderson Briglia21b8a2b2011-06-09 18:50:46 -0300637 } else {
Vinicius Costa Gomesf1b45c52011-07-07 18:59:40 -0300638 u8 stk[16], r[16], rand[8];
639 __le16 ediv;
640
641 memset(rand, 0, sizeof(rand));
642 ediv = 0;
Anderson Briglia21b8a2b2011-06-09 18:50:46 -0300643
Brian Gixa68668b2011-08-11 15:49:36 -0700644 swap128(hcon->prnd, r);
Anderson Briglia21b8a2b2011-06-09 18:50:46 -0300645 smp_send_cmd(conn, SMP_CMD_PAIRING_RANDOM, sizeof(r), r);
646
Brian Gixa68668b2011-08-11 15:49:36 -0700647 smp_s1(tfm, hcon->tk, hcon->prnd, random, key);
Vinicius Costa Gomesf1b45c52011-07-07 18:59:40 -0300648 swap128(key, stk);
Vinicius Costa Gomes397d9ae2011-06-14 13:37:42 -0300649
Brian Gixa68668b2011-08-11 15:49:36 -0700650 memset(stk + hcon->smp_key_size, 0,
651 SMP_MAX_ENC_KEY_SIZE - hcon->smp_key_size);
Vinicius Costa Gomesf1b45c52011-07-07 18:59:40 -0300652
Brian Gixcf956772011-10-20 15:18:51 -0700653 hci_add_ltk(conn->hcon->hdev, 0, conn->dst, hcon->dst_type,
654 hcon->smp_key_size, hcon->auth, ediv, rand, stk);
Anderson Briglia13b48392011-06-09 18:50:42 -0300655 }
Vinicius Costa Gomesda85e5e2011-06-09 18:50:53 -0300656
657 return 0;
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300658}
659
Brian Gix372257b2011-10-25 09:06:30 -0700660static int smp_encrypt_link(struct hci_conn *hcon, struct link_key *key)
Vinicius Costa Gomes988c5992011-08-25 20:02:28 -0300661{
Brian Gix372257b2011-10-25 09:06:30 -0700662 struct key_master_id *master;
Brian Gix80fb3a92012-01-31 13:15:20 -0800663 u8 sec_level;
Brian Gix372257b2011-10-25 09:06:30 -0700664 u8 zerobuf[8];
Vinicius Costa Gomes988c5992011-08-25 20:02:28 -0300665
Brian Gix372257b2011-10-25 09:06:30 -0700666 if (!hcon || !key || !key->data)
667 return -EINVAL;
Vinicius Costa Gomes988c5992011-08-25 20:02:28 -0300668
Brian Gix372257b2011-10-25 09:06:30 -0700669 memset(zerobuf, 0, sizeof(zerobuf));
Vinicius Costa Gomes988c5992011-08-25 20:02:28 -0300670
Brian Gix372257b2011-10-25 09:06:30 -0700671 master = (void *) key->data;
Vinicius Costa Gomes988c5992011-08-25 20:02:28 -0300672
Brian Gix372257b2011-10-25 09:06:30 -0700673 if (!master->ediv && !memcmp(master->rand, zerobuf, sizeof(zerobuf)))
674 return -EINVAL;
Vinicius Costa Gomes988c5992011-08-25 20:02:28 -0300675
Brian Gix372257b2011-10-25 09:06:30 -0700676 hcon->enc_key_size = key->pin_len;
677 hcon->sec_req = TRUE;
Brian Gix80fb3a92012-01-31 13:15:20 -0800678 sec_level = authreq_to_seclevel(key->auth);
679
680 BT_DBG("cur %d, req: %d", hcon->sec_level, sec_level);
681
682 if (sec_level > hcon->sec_level)
683 hcon->pending_sec_level = sec_level;
684
685
686 if (!(hcon->link_mode & HCI_LM_ENCRYPT))
687 hci_conn_hold(hcon);
688
Brian Gix372257b2011-10-25 09:06:30 -0700689 hci_le_start_enc(hcon, master->ediv, master->rand, key->val);
690
691 return 0;
Vinicius Costa Gomes988c5992011-08-25 20:02:28 -0300692}
Brian Gix372257b2011-10-25 09:06:30 -0700693
Vinicius Costa Gomesda85e5e2011-06-09 18:50:53 -0300694static u8 smp_cmd_security_req(struct l2cap_conn *conn, struct sk_buff *skb)
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300695{
Brian Gixa68668b2011-08-11 15:49:36 -0700696 struct hci_conn *hcon = conn->hcon;
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300697 struct smp_cmd_security_req *rp = (void *) skb->data;
698 struct smp_cmd_pairing cp;
Brian Gixa68668b2011-08-11 15:49:36 -0700699 struct link_key *key;
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300700
701 BT_DBG("conn %p", conn);
702
Vinicius Costa Gomesa5474a82011-01-26 21:42:57 -0300703 if (test_bit(HCI_CONN_ENCRYPT_PEND, &hcon->pend))
Vinicius Costa Gomes988c5992011-08-25 20:02:28 -0300704 return 0;
705
Brian Gixa68668b2011-08-11 15:49:36 -0700706 key = hci_find_link_key_type(hcon->hdev, conn->dst, KEY_TYPE_LTK);
707 if (key && ((key->auth & SMP_AUTH_MITM) ||
708 !(rp->auth_req & SMP_AUTH_MITM))) {
Vinicius Costa Gomesf1cb9af2011-01-26 21:42:57 -0300709
Brian Gix372257b2011-10-25 09:06:30 -0700710 if (smp_encrypt_link(hcon, key) < 0)
711 goto invalid_key;
Brian Gixa68668b2011-08-11 15:49:36 -0700712
Brian Gixa68668b2011-08-11 15:49:36 -0700713 return 0;
714 }
715
Brian Gix372257b2011-10-25 09:06:30 -0700716invalid_key:
Brian Gixa68668b2011-08-11 15:49:36 -0700717 hcon->sec_req = FALSE;
718
Archana Ramachandran82dac162013-03-04 17:45:22 -0800719 /* Switch to Pairing Connection Parameters */
720 hci_le_conn_update(hcon, SMP_MIN_CONN_INTERVAL, SMP_MAX_CONN_INTERVAL,
721 SMP_MAX_CONN_LATENCY, SMP_SUPERVISION_TIMEOUT);
722
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300723 skb_pull(skb, sizeof(*rp));
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300724
Vinicius Costa Gomesda85e5e2011-06-09 18:50:53 -0300725 memset(&cp, 0, sizeof(cp));
Vinicius Costa Gomes54790f72011-07-07 18:59:38 -0300726 build_pairing_cmd(conn, &cp, NULL, rp->auth_req);
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300727
Brian Gix27a795c2012-04-19 11:05:06 -0700728 hcon->pending_sec_level = authreq_to_seclevel(rp->auth_req);
Brian Gixa68668b2011-08-11 15:49:36 -0700729 hcon->preq[0] = SMP_CMD_PAIRING_REQ;
730 memcpy(&hcon->preq[1], &cp, sizeof(cp));
Anderson Brigliaf01ead32011-06-09 18:50:45 -0300731
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300732 smp_send_cmd(conn, SMP_CMD_PAIRING_REQ, sizeof(cp), &cp);
Vinicius Costa Gomesf1cb9af2011-01-26 21:42:57 -0300733
Brian Gixe9ceb522011-09-22 10:46:35 -0700734 mod_timer(&hcon->smp_timer, jiffies + msecs_to_jiffies(SMP_TIMEOUT));
Vinicius Costa Gomesb19d5ce2011-06-14 13:37:41 -0300735
Vinicius Costa Gomesa5474a82011-01-26 21:42:57 -0300736 set_bit(HCI_CONN_ENCRYPT_PEND, &hcon->pend);
Vinicius Costa Gomesa5474a82011-01-26 21:42:57 -0300737
Brian Gix8d0b7d62011-10-12 15:12:42 -0700738 hci_conn_hold(hcon);
739
Vinicius Costa Gomesda85e5e2011-06-09 18:50:53 -0300740 return 0;
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300741}
742
Anderson Brigliaeb492e02011-06-09 18:50:40 -0300743int smp_conn_security(struct l2cap_conn *conn, __u8 sec_level)
744{
Vinicius Costa Gomes3a0259b2011-06-09 18:50:43 -0300745 struct hci_conn *hcon = conn->hcon;
Brian Gix2b64d152011-12-21 16:12:12 -0800746 __u8 authreq;
Anderson Brigliaeb492e02011-06-09 18:50:40 -0300747
Brian Gix80fb3a92012-01-31 13:15:20 -0800748 BT_DBG("conn %p hcon %p %d req: %d",
749 conn, hcon, hcon->sec_level, sec_level);
Vinicius Costa Gomes3a0259b2011-06-09 18:50:43 -0300750
Brian Gix80fb3a92012-01-31 13:15:20 -0800751 if (IS_ERR(hcon->hdev->tfm))
Andre Guedes2e65c9d2011-06-30 19:20:56 -0300752 return 1;
753
Brian Gix80fb3a92012-01-31 13:15:20 -0800754 if (test_bit(HCI_CONN_ENCRYPT_PEND, &hcon->pend))
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700755 return -EINPROGRESS;
Anderson Briglia133e14c2011-06-09 18:50:40 -0300756
Vinicius Costa Gomesf1cb9af2011-01-26 21:42:57 -0300757 if (sec_level == BT_SECURITY_LOW)
Anderson Brigliaeb492e02011-06-09 18:50:40 -0300758 return 1;
Vinicius Costa Gomesf1cb9af2011-01-26 21:42:57 -0300759
Brian Gix80fb3a92012-01-31 13:15:20 -0800760
Vinicius Costa Gomesf1cb9af2011-01-26 21:42:57 -0300761 if (hcon->sec_level >= sec_level)
762 return 1;
763
Brian Gix2b64d152011-12-21 16:12:12 -0800764 authreq = seclevel_to_authreq(sec_level);
Vinicius Costa Gomesd26a2342011-08-19 21:06:51 -0300765
Brian Gixa68668b2011-08-11 15:49:36 -0700766 hcon->smp_conn = conn;
Brian Gix80fb3a92012-01-31 13:15:20 -0800767 hcon->pending_sec_level = sec_level;
Subramanian Srinivasan311eac42012-10-08 17:22:43 -0700768 if (hcon->link_mode & HCI_LM_MASTER) {
Vinicius Costa Gomes5d873ca2011-07-07 18:59:41 -0300769 struct link_key *key;
770
771 key = hci_find_link_key_type(hcon->hdev, conn->dst,
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700772 KEY_TYPE_LTK);
Vinicius Costa Gomes5d873ca2011-07-07 18:59:41 -0300773
Brian Gix372257b2011-10-25 09:06:30 -0700774 if (smp_encrypt_link(hcon, key) == 0)
Vinicius Costa Gomes5d873ca2011-07-07 18:59:41 -0300775 goto done;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700776 }
777
Brian Gixa68668b2011-08-11 15:49:36 -0700778 hcon->sec_req = FALSE;
779
Vinicius Costa Gomesd26a2342011-08-19 21:06:51 -0300780 if (hcon->link_mode & HCI_LM_MASTER) {
781 struct smp_cmd_pairing cp;
Anderson Brigliaf01ead32011-06-09 18:50:45 -0300782
Archana Ramachandran82dac162013-03-04 17:45:22 -0800783 /* Switch to Pairing Connection Parameters */
784 hci_le_conn_update(hcon, SMP_MIN_CONN_INTERVAL,
785 SMP_MAX_CONN_INTERVAL, SMP_MAX_CONN_LATENCY,
786 SMP_SUPERVISION_TIMEOUT);
787
Brian Gix2b64d152011-12-21 16:12:12 -0800788 build_pairing_cmd(conn, &cp, NULL, authreq);
Brian Gixa68668b2011-08-11 15:49:36 -0700789 hcon->preq[0] = SMP_CMD_PAIRING_REQ;
790 memcpy(&hcon->preq[1], &cp, sizeof(cp));
Anderson Brigliac8e856e2011-06-09 18:50:45 -0300791
Brian Gixe9ceb522011-09-22 10:46:35 -0700792 mod_timer(&hcon->smp_timer, jiffies +
Vinicius Costa Gomesb19d5ce2011-06-14 13:37:41 -0300793 msecs_to_jiffies(SMP_TIMEOUT));
Anderson Brigliaf01ead32011-06-09 18:50:45 -0300794
Anderson Brigliaeb492e02011-06-09 18:50:40 -0300795 smp_send_cmd(conn, SMP_CMD_PAIRING_REQ, sizeof(cp), &cp);
Brian Gix80fb3a92012-01-31 13:15:20 -0800796 hci_conn_hold(hcon);
Anderson Brigliaeb492e02011-06-09 18:50:40 -0300797 } else {
798 struct smp_cmd_security_req cp;
Brian Gix2b64d152011-12-21 16:12:12 -0800799 cp.auth_req = authreq;
Anderson Brigliaeb492e02011-06-09 18:50:40 -0300800 smp_send_cmd(conn, SMP_CMD_SECURITY_REQ, sizeof(cp), &cp);
801 }
802
Vinicius Costa Gomes02bc7452011-07-07 18:59:41 -0300803done:
Vinicius Costa Gomesa5474a82011-01-26 21:42:57 -0300804 set_bit(HCI_CONN_ENCRYPT_PEND, &hcon->pend);
Vinicius Costa Gomesf1cb9af2011-01-26 21:42:57 -0300805
Anderson Brigliaeb492e02011-06-09 18:50:40 -0300806 return 0;
807}
808
Vinicius Costa Gomes7034b912011-07-07 18:59:34 -0300809static int smp_cmd_encrypt_info(struct l2cap_conn *conn, struct sk_buff *skb)
810{
Brian Gixa68668b2011-08-11 15:49:36 -0700811 struct hci_conn *hcon = conn->hcon;
Vinicius Costa Gomes16b90832011-07-07 18:59:39 -0300812 struct smp_cmd_encrypt_info *rp = (void *) skb->data;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700813 u8 rand[8];
814 int err;
Vinicius Costa Gomes16b90832011-07-07 18:59:39 -0300815
816 skb_pull(skb, sizeof(*rp));
817
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700818 BT_DBG("conn %p", conn);
819
820 memset(rand, 0, sizeof(rand));
821
Brian Gixcf956772011-10-20 15:18:51 -0700822 err = hci_add_ltk(hcon->hdev, 0, conn->dst, hcon->dst_type,
823 0, 0, 0, rand, rp->ltk);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700824 if (err)
825 return SMP_UNSPECIFIED;
Vinicius Costa Gomes16b90832011-07-07 18:59:39 -0300826
Vinicius Costa Gomes7034b912011-07-07 18:59:34 -0300827 return 0;
828}
829
830static int smp_cmd_master_ident(struct l2cap_conn *conn, struct sk_buff *skb)
831{
Vinicius Costa Gomesc9839a12012-02-02 21:08:01 -0300832 struct hci_conn *hcon = conn->hcon;
Vinicius Costa Gomese56cede2011-07-07 18:59:39 -0300833 struct smp_cmd_master_ident *rp = (void *) skb->data;
Brian Gixa68668b2011-08-11 15:49:36 -0700834 struct smp_cmd_pairing *paircmd = (void *) &hcon->prsp[1];
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700835 struct link_key *key;
Brian Gixa68668b2011-08-11 15:49:36 -0700836 u8 *keydist;
Vinicius Costa Gomes7034b912011-07-07 18:59:34 -0300837
Vinicius Costa Gomes16b90832011-07-07 18:59:39 -0300838 skb_pull(skb, sizeof(*rp));
839
Brian Gixa68668b2011-08-11 15:49:36 -0700840 key = hci_find_link_key_type(hcon->hdev, conn->dst, KEY_TYPE_LTK);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700841 if (key == NULL)
842 return SMP_UNSPECIFIED;
843
Brian Gixa68668b2011-08-11 15:49:36 -0700844 if (hcon->out)
845 keydist = &paircmd->resp_key_dist;
846 else
847 keydist = &paircmd->init_key_dist;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700848
Brian Gixa68668b2011-08-11 15:49:36 -0700849 BT_DBG("keydist 0x%x", *keydist);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700850
Brian Gixcf956772011-10-20 15:18:51 -0700851 hci_add_ltk(hcon->hdev, 1, conn->dst, hcon->dst_type,
852 hcon->smp_key_size, hcon->auth, rp->ediv,
853 rp->rand, key->val);
Vinicius Costa Gomesc1d5e1d2011-07-07 18:59:34 -0300854
Brian Gixa68668b2011-08-11 15:49:36 -0700855 *keydist &= ~SMP_DIST_ENC_KEY;
856 if (hcon->out) {
857 if (!(*keydist))
858 smp_distribute_keys(conn, 1);
859 }
Vinicius Costa Gomes7034b912011-07-07 18:59:34 -0300860
861 return 0;
862}
863
Anderson Brigliaeb492e02011-06-09 18:50:40 -0300864int smp_sig_channel(struct l2cap_conn *conn, struct sk_buff *skb)
865{
Brian Gixa68668b2011-08-11 15:49:36 -0700866 struct hci_conn *hcon = conn->hcon;
Anderson Brigliaeb492e02011-06-09 18:50:40 -0300867 __u8 code = skb->data[0];
868 __u8 reason;
869 int err = 0;
870
Brian Gixa68668b2011-08-11 15:49:36 -0700871 if (IS_ERR(hcon->hdev->tfm)) {
872 err = PTR_ERR(hcon->hdev->tfm);
Andre Guedes2e65c9d2011-06-30 19:20:56 -0300873 reason = SMP_PAIRING_NOTSUPP;
Brian Gixa68668b2011-08-11 15:49:36 -0700874 BT_ERR("SMP_PAIRING_NOTSUPP %p", hcon->hdev->tfm);
Andre Guedes2e65c9d2011-06-30 19:20:56 -0300875 goto done;
876 }
877
Brian Gixa68668b2011-08-11 15:49:36 -0700878 hcon->smp_conn = conn;
Anderson Brigliaeb492e02011-06-09 18:50:40 -0300879 skb_pull(skb, sizeof(code));
880
881 switch (code) {
882 case SMP_CMD_PAIRING_REQ:
Vinicius Costa Gomesda85e5e2011-06-09 18:50:53 -0300883 reason = smp_cmd_pairing_req(conn, skb);
Anderson Brigliaeb492e02011-06-09 18:50:40 -0300884 break;
885
886 case SMP_CMD_PAIRING_FAIL:
Vinicius Costa Gomesda85e5e2011-06-09 18:50:53 -0300887 reason = 0;
888 err = -EPERM;
Brian Gixe9ceb522011-09-22 10:46:35 -0700889 del_timer(&hcon->smp_timer);
Brian Gix8d0b7d62011-10-12 15:12:42 -0700890 clear_bit(HCI_CONN_ENCRYPT_PEND, &hcon->pend);
Brian Gix570efc92011-10-13 15:59:51 -0700891 mgmt_auth_failed(hcon->hdev->id, conn->dst, skb->data[0]);
Brian Gix6d5fb8a2011-09-09 14:53:04 -0700892 hci_conn_put(hcon);
Anderson Brigliaeb492e02011-06-09 18:50:40 -0300893 break;
894
895 case SMP_CMD_PAIRING_RSP:
Vinicius Costa Gomesda85e5e2011-06-09 18:50:53 -0300896 reason = smp_cmd_pairing_rsp(conn, skb);
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300897 break;
898
899 case SMP_CMD_SECURITY_REQ:
Vinicius Costa Gomesda85e5e2011-06-09 18:50:53 -0300900 reason = smp_cmd_security_req(conn, skb);
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300901 break;
902
Anderson Brigliaeb492e02011-06-09 18:50:40 -0300903 case SMP_CMD_PAIRING_CONFIRM:
Vinicius Costa Gomesda85e5e2011-06-09 18:50:53 -0300904 reason = smp_cmd_pairing_confirm(conn, skb);
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300905 break;
906
Anderson Brigliaeb492e02011-06-09 18:50:40 -0300907 case SMP_CMD_PAIRING_RANDOM:
Vinicius Costa Gomesda85e5e2011-06-09 18:50:53 -0300908 reason = smp_cmd_pairing_random(conn, skb);
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300909 break;
910
Anderson Brigliaeb492e02011-06-09 18:50:40 -0300911 case SMP_CMD_ENCRYPT_INFO:
Vinicius Costa Gomes7034b912011-07-07 18:59:34 -0300912 reason = smp_cmd_encrypt_info(conn, skb);
913 break;
914
Anderson Brigliaeb492e02011-06-09 18:50:40 -0300915 case SMP_CMD_MASTER_IDENT:
Vinicius Costa Gomes7034b912011-07-07 18:59:34 -0300916 reason = smp_cmd_master_ident(conn, skb);
917 break;
918
Anderson Brigliaeb492e02011-06-09 18:50:40 -0300919 case SMP_CMD_IDENT_INFO:
920 case SMP_CMD_IDENT_ADDR_INFO:
921 case SMP_CMD_SIGN_INFO:
Vinicius Costa Gomes7034b912011-07-07 18:59:34 -0300922 /* Just ignored */
923 reason = 0;
924 break;
925
Anderson Brigliaeb492e02011-06-09 18:50:40 -0300926 default:
927 BT_DBG("Unknown command code 0x%2.2x", code);
928
929 reason = SMP_CMD_NOTSUPP;
Vinicius Costa Gomes3a0259b2011-06-09 18:50:43 -0300930 err = -EOPNOTSUPP;
931 goto done;
932 }
933
934done:
Brian Gixa68668b2011-08-11 15:49:36 -0700935 if (reason) {
936 BT_ERR("SMP_CMD_PAIRING_FAIL: %d", reason);
Anderson Briglia133e14c2011-06-09 18:50:40 -0300937 smp_send_cmd(conn, SMP_CMD_PAIRING_FAIL, sizeof(reason),
938 &reason);
Brian Gixe9ceb522011-09-22 10:46:35 -0700939 del_timer(&hcon->smp_timer);
Brian Gix8d0b7d62011-10-12 15:12:42 -0700940 clear_bit(HCI_CONN_ENCRYPT_PEND, &hcon->pend);
Brian Gix58ba0772011-09-23 13:40:16 -0700941 mgmt_auth_failed(hcon->hdev->id, conn->dst, reason);
Brian Gix6d5fb8a2011-09-09 14:53:04 -0700942 hci_conn_put(hcon);
Brian Gixa68668b2011-08-11 15:49:36 -0700943 }
Anderson Brigliaeb492e02011-06-09 18:50:40 -0300944
945 kfree_skb(skb);
946 return err;
947}
Vinicius Costa Gomes7034b912011-07-07 18:59:34 -0300948
Brian Gixa68668b2011-08-11 15:49:36 -0700949static int smp_distribute_keys(struct l2cap_conn *conn, __u8 force)
Vinicius Costa Gomes7034b912011-07-07 18:59:34 -0300950{
Brian Gixa68668b2011-08-11 15:49:36 -0700951 struct hci_conn *hcon = conn->hcon;
Vinicius Costa Gomes7034b912011-07-07 18:59:34 -0300952 struct smp_cmd_pairing *req, *rsp;
953 __u8 *keydist;
954
955 BT_DBG("conn %p force %d", conn, force);
956
Brian Gixa68668b2011-08-11 15:49:36 -0700957 if (IS_ERR(hcon->hdev->tfm))
958 return PTR_ERR(hcon->hdev->tfm);
Vinicius Costa Gomesd26a2342011-08-19 21:06:51 -0300959
Brian Gixa68668b2011-08-11 15:49:36 -0700960 rsp = (void *) &hcon->prsp[1];
Vinicius Costa Gomes7034b912011-07-07 18:59:34 -0300961
962 /* The responder sends its keys first */
Brian Gixa68668b2011-08-11 15:49:36 -0700963 if (!force && hcon->out && (rsp->resp_key_dist & 0x07))
Vinicius Costa Gomes7034b912011-07-07 18:59:34 -0300964 return 0;
965
Brian Gixa68668b2011-08-11 15:49:36 -0700966 req = (void *) &hcon->preq[1];
Vinicius Costa Gomes7034b912011-07-07 18:59:34 -0300967
Brian Gixa68668b2011-08-11 15:49:36 -0700968 if (hcon->out) {
Vinicius Costa Gomes7034b912011-07-07 18:59:34 -0300969 keydist = &rsp->init_key_dist;
970 *keydist &= req->init_key_dist;
971 } else {
972 keydist = &rsp->resp_key_dist;
973 *keydist &= req->resp_key_dist;
974 }
975
976
977 BT_DBG("keydist 0x%x", *keydist);
978
979 if (*keydist & SMP_DIST_ENC_KEY) {
980 struct smp_cmd_encrypt_info enc;
981 struct smp_cmd_master_ident ident;
982 __le16 ediv;
983
984 get_random_bytes(enc.ltk, sizeof(enc.ltk));
985 get_random_bytes(&ediv, sizeof(ediv));
986 get_random_bytes(ident.rand, sizeof(ident.rand));
987
988 smp_send_cmd(conn, SMP_CMD_ENCRYPT_INFO, sizeof(enc), &enc);
989
Brian Gixcf956772011-10-20 15:18:51 -0700990 hci_add_ltk(hcon->hdev, 1, conn->dst, hcon->dst_type,
991 hcon->smp_key_size, hcon->auth, ediv,
992 ident.rand, enc.ltk);
Vinicius Costa Gomes16b90832011-07-07 18:59:39 -0300993
Vinicius Costa Gomes7034b912011-07-07 18:59:34 -0300994 ident.ediv = cpu_to_le16(ediv);
995
996 smp_send_cmd(conn, SMP_CMD_MASTER_IDENT, sizeof(ident), &ident);
997
998 *keydist &= ~SMP_DIST_ENC_KEY;
999 }
1000
1001 if (*keydist & SMP_DIST_ID_KEY) {
1002 struct smp_cmd_ident_addr_info addrinfo;
1003 struct smp_cmd_ident_info idinfo;
1004
1005 /* Send a dummy key */
1006 get_random_bytes(idinfo.irk, sizeof(idinfo.irk));
1007
1008 smp_send_cmd(conn, SMP_CMD_IDENT_INFO, sizeof(idinfo), &idinfo);
1009
1010 /* Just public address */
1011 memset(&addrinfo, 0, sizeof(addrinfo));
1012 bacpy(&addrinfo.bdaddr, conn->src);
1013
1014 smp_send_cmd(conn, SMP_CMD_IDENT_ADDR_INFO, sizeof(addrinfo),
1015 &addrinfo);
1016
1017 *keydist &= ~SMP_DIST_ID_KEY;
1018 }
1019
1020 if (*keydist & SMP_DIST_SIGN) {
1021 struct smp_cmd_sign_info sign;
1022
1023 /* Send a dummy key */
1024 get_random_bytes(sign.csrk, sizeof(sign.csrk));
1025
1026 smp_send_cmd(conn, SMP_CMD_SIGN_INFO, sizeof(sign), &sign);
1027
1028 *keydist &= ~SMP_DIST_SIGN;
1029 }
1030
Brian Gix2a335262011-11-17 12:59:23 -08001031 if (hcon->out) {
Brian Gixe57c1672011-09-13 12:34:59 -07001032 if (hcon->disconn_cfm_cb)
1033 hcon->disconn_cfm_cb(hcon, 0);
Brian Gixe9ceb522011-09-22 10:46:35 -07001034 del_timer(&hcon->smp_timer);
Brian Gix8d0b7d62011-10-12 15:12:42 -07001035 clear_bit(HCI_CONN_ENCRYPT_PEND, &hcon->pend);
Brian Gix2a335262011-11-17 12:59:23 -08001036 hci_conn_put(hcon);
1037 } else if (rsp->resp_key_dist) {
1038 if (hcon->disconn_cfm_cb)
1039 hcon->disconn_cfm_cb(hcon, SMP_UNSPECIFIED);
1040 clear_bit(HCI_CONN_ENCRYPT_PEND, &hcon->pend);
Brian Gix58ba0772011-09-23 13:40:16 -07001041 mgmt_auth_failed(hcon->hdev->id, conn->dst, SMP_UNSPECIFIED);
Brian Gix6d5fb8a2011-09-09 14:53:04 -07001042 hci_conn_put(hcon);
Vinicius Costa Gomesd26a2342011-08-19 21:06:51 -03001043 }
1044
Vinicius Costa Gomes7034b912011-07-07 18:59:34 -03001045 return 0;
1046}
Brian Gixa68668b2011-08-11 15:49:36 -07001047
Archana Ramachandran1cb41162013-01-29 16:20:19 -08001048void smp_conn_security_fail(struct l2cap_conn *conn, u8 code, u8 reason)
1049{
1050 BT_DBG("smp: %d %d ", code, reason);
1051 smp_send_cmd(conn, SMP_CMD_PAIRING_FAIL, sizeof(reason), &reason);
1052}
1053
Brian Gixa68668b2011-08-11 15:49:36 -07001054int smp_link_encrypt_cmplt(struct l2cap_conn *conn, u8 status, u8 encrypt)
1055{
1056 struct hci_conn *hcon = conn->hcon;
1057
1058 BT_DBG("smp: %d %d %d", status, encrypt, hcon->sec_req);
1059
Brian Gix8d0b7d62011-10-12 15:12:42 -07001060 clear_bit(HCI_CONN_ENCRYPT_PEND, &hcon->pend);
1061
Brian Gix80fb3a92012-01-31 13:15:20 -08001062 if (!status && encrypt && hcon->sec_level < hcon->pending_sec_level)
1063 hcon->sec_level = hcon->pending_sec_level;
1064
Brian Gixa68668b2011-08-11 15:49:36 -07001065 if (!status && encrypt && !hcon->sec_req)
Brian Gix80fb3a92012-01-31 13:15:20 -08001066 return smp_distribute_keys(conn, 0);
Brian Gixa68668b2011-08-11 15:49:36 -07001067
1068 /* Fall back to Pairing request if failed a Link Security request */
1069 else if (hcon->sec_req && (status || !encrypt))
Brian Gix80fb3a92012-01-31 13:15:20 -08001070 smp_conn_security(conn, hcon->pending_sec_level);
Brian Gixa68668b2011-08-11 15:49:36 -07001071
Brian Gix80fb3a92012-01-31 13:15:20 -08001072 hci_conn_put(hcon);
Brian Gix8d0b7d62011-10-12 15:12:42 -07001073
Vinicius Costa Gomesc1d5e1d2011-07-07 18:59:34 -03001074 return 0;
1075}
Brian Gixe9ceb522011-09-22 10:46:35 -07001076
1077void smp_timeout(unsigned long arg)
1078{
1079 struct l2cap_conn *conn = (void *) arg;
1080 u8 reason = SMP_UNSPECIFIED;
1081
1082 BT_DBG("%p", conn);
1083
1084 smp_send_cmd(conn, SMP_CMD_PAIRING_FAIL, sizeof(reason), &reason);
Brian Gix8d0b7d62011-10-12 15:12:42 -07001085 clear_bit(HCI_CONN_ENCRYPT_PEND, &conn->hcon->pend);
Brian Gix58ba0772011-09-23 13:40:16 -07001086 mgmt_auth_failed(conn->hcon->hdev->id, conn->dst, SMP_UNSPECIFIED);
Brian Gixe9ceb522011-09-22 10:46:35 -07001087 hci_conn_put(conn->hcon);
Subramanian Srinivasan6e9f2b02013-05-21 15:42:28 -07001088 //delete the l2cap connection
1089 l2cap_conn_del(conn->hcon, EACCES, 0);
Brian Gixe9ceb522011-09-22 10:46:35 -07001090}