blob: 8ef2d635865b91da881ca702b757071fa9f7cff6 [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);
456 } else if (hcon->cfm_pending) {
Brian Gixa68668b2011-08-11 15:49:36 -0700457 BT_DBG("send_pairing_confirm");
458 ret = send_pairing_confirm(conn);
459 }
460
461 return ret;
462}
463
Vinicius Costa Gomesda85e5e2011-06-09 18:50:53 -0300464static u8 smp_cmd_pairing_req(struct l2cap_conn *conn, struct sk_buff *skb)
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300465{
Brian Gixa68668b2011-08-11 15:49:36 -0700466 struct hci_conn *hcon = conn->hcon;
Vinicius Costa Gomes3158c502011-06-14 13:37:42 -0300467 struct smp_cmd_pairing rsp, *req = (void *) skb->data;
468 u8 key_size;
Brian Gix2b64d152011-12-21 16:12:12 -0800469 u8 auth = SMP_AUTH_NONE;
Vinicius Costa Gomes8aab4752011-09-05 14:31:31 -0300470 int ret;
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300471
472 BT_DBG("conn %p", conn);
473
Brian Gixa68668b2011-08-11 15:49:36 -0700474 hcon->preq[0] = SMP_CMD_PAIRING_REQ;
475 memcpy(&hcon->preq[1], req, sizeof(*req));
Vinicius Costa Gomes3158c502011-06-14 13:37:42 -0300476 skb_pull(skb, sizeof(*req));
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300477
Brian Gixa68668b2011-08-11 15:49:36 -0700478 if (req->oob_flag && hcon->oob) {
479 /* By definition, OOB data pairing will have MITM protection */
480 auth = req->auth_req | SMP_AUTH_MITM;
481 } else if (req->auth_req & SMP_AUTH_BONDING) {
482 /* We will attempt MITM for all Bonding attempts */
483 auth = SMP_AUTH_BONDING | SMP_AUTH_MITM;
484 }
Vinicius Costa Gomesda85e5e2011-06-09 18:50:53 -0300485
Vinicius Costa Gomes64532ec2011-06-09 18:50:53 -0300486 /* We didn't start the pairing, so no requirements */
Brian Gix2b64d152011-12-21 16:12:12 -0800487 build_pairing_cmd(conn, req, &rsp, auth);
Vinicius Costa Gomes3158c502011-06-14 13:37:42 -0300488
489 key_size = min(req->max_key_size, rsp.max_key_size);
490 if (check_enc_key_size(conn, key_size))
491 return SMP_ENC_KEY_SIZE;
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300492
Brian Gixa68668b2011-08-11 15:49:36 -0700493 ret = smp_rand(hcon->prnd);
Vinicius Costa Gomes8aab4752011-09-05 14:31:31 -0300494 if (ret)
495 return SMP_UNSPECIFIED;
496
Brian Gixa68668b2011-08-11 15:49:36 -0700497 /* Request setup of TK */
498 ret = tk_request(conn, req->oob_flag, auth, rsp.io_capability,
499 req->io_capability);
500 if (ret)
501 return SMP_UNSPECIFIED;
502
503 hcon->prsp[0] = SMP_CMD_PAIRING_RSP;
504 memcpy(&hcon->prsp[1], &rsp, sizeof(rsp));
Anderson Brigliaf01ead32011-06-09 18:50:45 -0300505
Vinicius Costa Gomes3158c502011-06-14 13:37:42 -0300506 smp_send_cmd(conn, SMP_CMD_PAIRING_RSP, sizeof(rsp), &rsp);
Vinicius Costa Gomesda85e5e2011-06-09 18:50:53 -0300507
Brian Gixe9ceb522011-09-22 10:46:35 -0700508 mod_timer(&hcon->smp_timer, jiffies + msecs_to_jiffies(SMP_TIMEOUT));
Brian Gix2b64d152011-12-21 16:12:12 -0800509
Vinicius Costa Gomesda85e5e2011-06-09 18:50:53 -0300510 return 0;
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300511}
512
Vinicius Costa Gomesda85e5e2011-06-09 18:50:53 -0300513static u8 smp_cmd_pairing_rsp(struct l2cap_conn *conn, struct sk_buff *skb)
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300514{
Brian Gixa68668b2011-08-11 15:49:36 -0700515 struct hci_conn *hcon = conn->hcon;
Vinicius Costa Gomes3158c502011-06-14 13:37:42 -0300516 struct smp_cmd_pairing *req, *rsp = (void *) skb->data;
Brian Gix2b64d152011-12-21 16:12:12 -0800517 u8 key_size, auth = SMP_AUTH_NONE;
Anderson Briglia7d24ddc2011-06-09 18:50:46 -0300518 int ret;
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300519
520 BT_DBG("conn %p", conn);
521
Vinicius Costa Gomes3158c502011-06-14 13:37:42 -0300522 skb_pull(skb, sizeof(*rsp));
Vinicius Costa Gomesda85e5e2011-06-09 18:50:53 -0300523
Brian Gixa68668b2011-08-11 15:49:36 -0700524 req = (void *) &hcon->preq[1];
Vinicius Costa Gomes3158c502011-06-14 13:37:42 -0300525
526 key_size = min(req->max_key_size, rsp->max_key_size);
527 if (check_enc_key_size(conn, key_size))
528 return SMP_ENC_KEY_SIZE;
529
Brian Gixa68668b2011-08-11 15:49:36 -0700530 hcon->prsp[0] = SMP_CMD_PAIRING_RSP;
531 memcpy(&hcon->prsp[1], rsp, sizeof(*rsp));
Vinicius Costa Gomes64532ec2011-06-09 18:50:53 -0300532
Brian Gixa68668b2011-08-11 15:49:36 -0700533 ret = smp_rand(hcon->prnd);
Anderson Briglia7d24ddc2011-06-09 18:50:46 -0300534 if (ret)
Vinicius Costa Gomesda85e5e2011-06-09 18:50:53 -0300535 return SMP_UNSPECIFIED;
Anderson Briglia7d24ddc2011-06-09 18:50:46 -0300536
Brian Gix2b64d152011-12-21 16:12:12 -0800537 if ((req->auth_req & SMP_AUTH_BONDING) &&
538 (rsp->auth_req & SMP_AUTH_BONDING))
539 auth = SMP_AUTH_BONDING;
540
541 auth |= (req->auth_req | rsp->auth_req) & SMP_AUTH_MITM;
542
Brian Gixa68668b2011-08-11 15:49:36 -0700543 ret = tk_request(conn, req->oob_flag, auth, rsp->io_capability,
544 req->io_capability);
Brian Gix2b64d152011-12-21 16:12:12 -0800545 if (ret)
546 return SMP_UNSPECIFIED;
547
Brian Gixa68668b2011-08-11 15:49:36 -0700548 hcon->cfm_pending = TRUE;
Brian Gix2b64d152011-12-21 16:12:12 -0800549
550 /* Can't compose response until we have been confirmed */
Brian Gixa68668b2011-08-11 15:49:36 -0700551 if (!hcon->tk_valid)
Brian Gix2b64d152011-12-21 16:12:12 -0800552 return 0;
553
Brian Gixa68668b2011-08-11 15:49:36 -0700554 ret = send_pairing_confirm(conn);
555 if (ret)
556 return SMP_CONFIRM_FAILED;
Vinicius Costa Gomesda85e5e2011-06-09 18:50:53 -0300557
558 return 0;
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300559}
560
Vinicius Costa Gomesda85e5e2011-06-09 18:50:53 -0300561static u8 smp_cmd_pairing_confirm(struct l2cap_conn *conn, struct sk_buff *skb)
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300562{
Brian Gixa68668b2011-08-11 15:49:36 -0700563 struct hci_conn *hcon = conn->hcon;
564 int ret;
Anderson Briglia7d24ddc2011-06-09 18:50:46 -0300565
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300566 BT_DBG("conn %p %s", conn, conn->hcon->out ? "master" : "slave");
567
Brian Gixa68668b2011-08-11 15:49:36 -0700568 memcpy(hcon->pcnf, skb->data, sizeof(hcon->pcnf));
569 skb_pull(skb, sizeof(hcon->pcnf));
Anderson Briglia7d24ddc2011-06-09 18:50:46 -0300570
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300571 if (conn->hcon->out) {
Anderson Briglia7d24ddc2011-06-09 18:50:46 -0300572 u8 random[16];
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300573
Brian Gixa68668b2011-08-11 15:49:36 -0700574 swap128(hcon->prnd, random);
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300575 smp_send_cmd(conn, SMP_CMD_PAIRING_RANDOM, sizeof(random),
Anderson Briglia7d24ddc2011-06-09 18:50:46 -0300576 random);
Brian Gixa68668b2011-08-11 15:49:36 -0700577 } else if (hcon->tk_valid) {
578 ret = send_pairing_confirm(conn);
Anderson Briglia13b48392011-06-09 18:50:42 -0300579
Anderson Briglia21b8a2b2011-06-09 18:50:46 -0300580 if (ret)
Vinicius Costa Gomes64532ec2011-06-09 18:50:53 -0300581 return SMP_CONFIRM_FAILED;
Brian Gixa68668b2011-08-11 15:49:36 -0700582 } else
583 hcon->cfm_pending = TRUE;
Anderson Briglia21b8a2b2011-06-09 18:50:46 -0300584
Vinicius Costa Gomes64532ec2011-06-09 18:50:53 -0300585
Brian Gixe9ceb522011-09-22 10:46:35 -0700586 mod_timer(&hcon->smp_timer, jiffies + msecs_to_jiffies(SMP_TIMEOUT));
Vinicius Costa Gomesda85e5e2011-06-09 18:50:53 -0300587
588 return 0;
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300589}
590
Vinicius Costa Gomesda85e5e2011-06-09 18:50:53 -0300591static u8 smp_cmd_pairing_random(struct l2cap_conn *conn, struct sk_buff *skb)
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300592{
Vinicius Costa Gomes735038c2011-06-09 18:50:47 -0300593 struct hci_conn *hcon = conn->hcon;
594 struct crypto_blkcipher *tfm = hcon->hdev->tfm;
Anderson Briglia21b8a2b2011-06-09 18:50:46 -0300595 int ret;
Vinicius Costa Gomesc34e25e2011-06-09 18:50:48 -0300596 u8 key[16], res[16], random[16], confirm[16];
Anderson Briglia7d24ddc2011-06-09 18:50:46 -0300597
Anderson Briglia21b8a2b2011-06-09 18:50:46 -0300598 swap128(skb->data, random);
599 skb_pull(skb, sizeof(random));
Anderson Briglia7d24ddc2011-06-09 18:50:46 -0300600
Anderson Briglia21b8a2b2011-06-09 18:50:46 -0300601 if (conn->hcon->out)
Brian Gixa68668b2011-08-11 15:49:36 -0700602 ret = smp_c1(tfm, hcon->tk, random, hcon->preq, hcon->prsp, 0,
603 conn->src, hcon->dst_type, conn->dst,
Anderson Briglia21b8a2b2011-06-09 18:50:46 -0300604 res);
605 else
Brian Gixa68668b2011-08-11 15:49:36 -0700606 ret = smp_c1(tfm, hcon->tk, random, hcon->preq, hcon->prsp,
607 hcon->dst_type, conn->dst, 0, conn->src,
Anderson Briglia21b8a2b2011-06-09 18:50:46 -0300608 res);
609 if (ret)
Vinicius Costa Gomes64532ec2011-06-09 18:50:53 -0300610 return SMP_UNSPECIFIED;
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300611
Anderson Briglia13b48392011-06-09 18:50:42 -0300612 BT_DBG("conn %p %s", conn, conn->hcon->out ? "master" : "slave");
613
Anderson Briglia21b8a2b2011-06-09 18:50:46 -0300614 swap128(res, confirm);
615
Brian Gixa68668b2011-08-11 15:49:36 -0700616 if (memcmp(hcon->pcnf, confirm, sizeof(hcon->pcnf)) != 0) {
Anderson Briglia21b8a2b2011-06-09 18:50:46 -0300617 BT_ERR("Pairing failed (confirmation values mismatch)");
Vinicius Costa Gomes64532ec2011-06-09 18:50:53 -0300618 return SMP_CONFIRM_FAILED;
Anderson Briglia21b8a2b2011-06-09 18:50:46 -0300619 }
Anderson Briglia13b48392011-06-09 18:50:42 -0300620
621 if (conn->hcon->out) {
Vinicius Costa Gomesf1b45c52011-07-07 18:59:40 -0300622 u8 stk[16], rand[8];
Vinicius Costa Gomes735038c2011-06-09 18:50:47 -0300623 __le16 ediv;
Vinicius Costa Gomes397d9ae2011-06-14 13:37:42 -0300624
Vinicius Costa Gomes735038c2011-06-09 18:50:47 -0300625 memset(rand, 0, sizeof(rand));
626 ediv = 0;
Vinicius Costa Gomesf1b45c52011-07-07 18:59:40 -0300627
Brian Gixa68668b2011-08-11 15:49:36 -0700628 smp_s1(tfm, hcon->tk, random, hcon->prnd, key);
Vinicius Costa Gomesf1b45c52011-07-07 18:59:40 -0300629 swap128(key, stk);
630
Brian Gixa68668b2011-08-11 15:49:36 -0700631 memset(stk + hcon->smp_key_size, 0,
632 SMP_MAX_ENC_KEY_SIZE - hcon->smp_key_size);
Vinicius Costa Gomesf1b45c52011-07-07 18:59:40 -0300633
634 hci_le_start_enc(hcon, ediv, rand, stk);
Brian Gixa68668b2011-08-11 15:49:36 -0700635 hcon->enc_key_size = hcon->smp_key_size;
Anderson Briglia21b8a2b2011-06-09 18:50:46 -0300636 } else {
Vinicius Costa Gomesf1b45c52011-07-07 18:59:40 -0300637 u8 stk[16], r[16], rand[8];
638 __le16 ediv;
639
640 memset(rand, 0, sizeof(rand));
641 ediv = 0;
Anderson Briglia21b8a2b2011-06-09 18:50:46 -0300642
Brian Gixa68668b2011-08-11 15:49:36 -0700643 swap128(hcon->prnd, r);
Anderson Briglia21b8a2b2011-06-09 18:50:46 -0300644 smp_send_cmd(conn, SMP_CMD_PAIRING_RANDOM, sizeof(r), r);
645
Brian Gixa68668b2011-08-11 15:49:36 -0700646 smp_s1(tfm, hcon->tk, hcon->prnd, random, key);
Vinicius Costa Gomesf1b45c52011-07-07 18:59:40 -0300647 swap128(key, stk);
Vinicius Costa Gomes397d9ae2011-06-14 13:37:42 -0300648
Brian Gixa68668b2011-08-11 15:49:36 -0700649 memset(stk + hcon->smp_key_size, 0,
650 SMP_MAX_ENC_KEY_SIZE - hcon->smp_key_size);
Vinicius Costa Gomesf1b45c52011-07-07 18:59:40 -0300651
Brian Gixcf956772011-10-20 15:18:51 -0700652 hci_add_ltk(conn->hcon->hdev, 0, conn->dst, hcon->dst_type,
653 hcon->smp_key_size, hcon->auth, ediv, rand, stk);
Anderson Briglia13b48392011-06-09 18:50:42 -0300654 }
Vinicius Costa Gomesda85e5e2011-06-09 18:50:53 -0300655
656 return 0;
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300657}
658
Brian Gix372257b2011-10-25 09:06:30 -0700659static int smp_encrypt_link(struct hci_conn *hcon, struct link_key *key)
Vinicius Costa Gomes988c5992011-08-25 20:02:28 -0300660{
Brian Gix372257b2011-10-25 09:06:30 -0700661 struct key_master_id *master;
Brian Gix80fb3a92012-01-31 13:15:20 -0800662 u8 sec_level;
Brian Gix372257b2011-10-25 09:06:30 -0700663 u8 zerobuf[8];
Vinicius Costa Gomes988c5992011-08-25 20:02:28 -0300664
Brian Gix372257b2011-10-25 09:06:30 -0700665 if (!hcon || !key || !key->data)
666 return -EINVAL;
Vinicius Costa Gomes988c5992011-08-25 20:02:28 -0300667
Brian Gix372257b2011-10-25 09:06:30 -0700668 memset(zerobuf, 0, sizeof(zerobuf));
Vinicius Costa Gomes988c5992011-08-25 20:02:28 -0300669
Brian Gix372257b2011-10-25 09:06:30 -0700670 master = (void *) key->data;
Vinicius Costa Gomes988c5992011-08-25 20:02:28 -0300671
Brian Gix372257b2011-10-25 09:06:30 -0700672 if (!master->ediv && !memcmp(master->rand, zerobuf, sizeof(zerobuf)))
673 return -EINVAL;
Vinicius Costa Gomes988c5992011-08-25 20:02:28 -0300674
Brian Gix372257b2011-10-25 09:06:30 -0700675 hcon->enc_key_size = key->pin_len;
676 hcon->sec_req = TRUE;
Brian Gix80fb3a92012-01-31 13:15:20 -0800677 sec_level = authreq_to_seclevel(key->auth);
678
679 BT_DBG("cur %d, req: %d", hcon->sec_level, sec_level);
680
681 if (sec_level > hcon->sec_level)
682 hcon->pending_sec_level = sec_level;
683
684
685 if (!(hcon->link_mode & HCI_LM_ENCRYPT))
686 hci_conn_hold(hcon);
687
Brian Gix372257b2011-10-25 09:06:30 -0700688 hci_le_start_enc(hcon, master->ediv, master->rand, key->val);
689
690 return 0;
Vinicius Costa Gomes988c5992011-08-25 20:02:28 -0300691}
Brian Gix372257b2011-10-25 09:06:30 -0700692
Vinicius Costa Gomesda85e5e2011-06-09 18:50:53 -0300693static u8 smp_cmd_security_req(struct l2cap_conn *conn, struct sk_buff *skb)
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300694{
Brian Gixa68668b2011-08-11 15:49:36 -0700695 struct hci_conn *hcon = conn->hcon;
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300696 struct smp_cmd_security_req *rp = (void *) skb->data;
697 struct smp_cmd_pairing cp;
Brian Gixa68668b2011-08-11 15:49:36 -0700698 struct link_key *key;
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300699
700 BT_DBG("conn %p", conn);
701
Vinicius Costa Gomesa5474a82011-01-26 21:42:57 -0300702 if (test_bit(HCI_CONN_ENCRYPT_PEND, &hcon->pend))
Vinicius Costa Gomes988c5992011-08-25 20:02:28 -0300703 return 0;
704
Brian Gixa68668b2011-08-11 15:49:36 -0700705 key = hci_find_link_key_type(hcon->hdev, conn->dst, KEY_TYPE_LTK);
706 if (key && ((key->auth & SMP_AUTH_MITM) ||
707 !(rp->auth_req & SMP_AUTH_MITM))) {
Vinicius Costa Gomesf1cb9af2011-01-26 21:42:57 -0300708
Brian Gix372257b2011-10-25 09:06:30 -0700709 if (smp_encrypt_link(hcon, key) < 0)
710 goto invalid_key;
Brian Gixa68668b2011-08-11 15:49:36 -0700711
Brian Gixa68668b2011-08-11 15:49:36 -0700712 return 0;
713 }
714
Brian Gix372257b2011-10-25 09:06:30 -0700715invalid_key:
Brian Gixa68668b2011-08-11 15:49:36 -0700716 hcon->sec_req = FALSE;
717
Archana Ramachandran82dac162013-03-04 17:45:22 -0800718 /* Switch to Pairing Connection Parameters */
719 hci_le_conn_update(hcon, SMP_MIN_CONN_INTERVAL, SMP_MAX_CONN_INTERVAL,
720 SMP_MAX_CONN_LATENCY, SMP_SUPERVISION_TIMEOUT);
721
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300722 skb_pull(skb, sizeof(*rp));
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300723
Vinicius Costa Gomesda85e5e2011-06-09 18:50:53 -0300724 memset(&cp, 0, sizeof(cp));
Vinicius Costa Gomes54790f72011-07-07 18:59:38 -0300725 build_pairing_cmd(conn, &cp, NULL, rp->auth_req);
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300726
Brian Gix27a795c2012-04-19 11:05:06 -0700727 hcon->pending_sec_level = authreq_to_seclevel(rp->auth_req);
Brian Gixa68668b2011-08-11 15:49:36 -0700728 hcon->preq[0] = SMP_CMD_PAIRING_REQ;
729 memcpy(&hcon->preq[1], &cp, sizeof(cp));
Anderson Brigliaf01ead32011-06-09 18:50:45 -0300730
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300731 smp_send_cmd(conn, SMP_CMD_PAIRING_REQ, sizeof(cp), &cp);
Vinicius Costa Gomesf1cb9af2011-01-26 21:42:57 -0300732
Brian Gixe9ceb522011-09-22 10:46:35 -0700733 mod_timer(&hcon->smp_timer, jiffies + msecs_to_jiffies(SMP_TIMEOUT));
Vinicius Costa Gomesb19d5ce2011-06-14 13:37:41 -0300734
Vinicius Costa Gomesa5474a82011-01-26 21:42:57 -0300735 set_bit(HCI_CONN_ENCRYPT_PEND, &hcon->pend);
Vinicius Costa Gomesa5474a82011-01-26 21:42:57 -0300736
Brian Gix8d0b7d62011-10-12 15:12:42 -0700737 hci_conn_hold(hcon);
738
Vinicius Costa Gomesda85e5e2011-06-09 18:50:53 -0300739 return 0;
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300740}
741
Anderson Brigliaeb492e02011-06-09 18:50:40 -0300742int smp_conn_security(struct l2cap_conn *conn, __u8 sec_level)
743{
Vinicius Costa Gomes3a0259b2011-06-09 18:50:43 -0300744 struct hci_conn *hcon = conn->hcon;
Brian Gix2b64d152011-12-21 16:12:12 -0800745 __u8 authreq;
Anderson Brigliaeb492e02011-06-09 18:50:40 -0300746
Brian Gix80fb3a92012-01-31 13:15:20 -0800747 BT_DBG("conn %p hcon %p %d req: %d",
748 conn, hcon, hcon->sec_level, sec_level);
Vinicius Costa Gomes3a0259b2011-06-09 18:50:43 -0300749
Brian Gix80fb3a92012-01-31 13:15:20 -0800750 if (IS_ERR(hcon->hdev->tfm))
Andre Guedes2e65c9d2011-06-30 19:20:56 -0300751 return 1;
752
Brian Gix80fb3a92012-01-31 13:15:20 -0800753 if (test_bit(HCI_CONN_ENCRYPT_PEND, &hcon->pend))
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700754 return -EINPROGRESS;
Anderson Briglia133e14c2011-06-09 18:50:40 -0300755
Vinicius Costa Gomesf1cb9af2011-01-26 21:42:57 -0300756 if (sec_level == BT_SECURITY_LOW)
Anderson Brigliaeb492e02011-06-09 18:50:40 -0300757 return 1;
Vinicius Costa Gomesf1cb9af2011-01-26 21:42:57 -0300758
Brian Gix80fb3a92012-01-31 13:15:20 -0800759
Vinicius Costa Gomesf1cb9af2011-01-26 21:42:57 -0300760 if (hcon->sec_level >= sec_level)
761 return 1;
762
Brian Gix2b64d152011-12-21 16:12:12 -0800763 authreq = seclevel_to_authreq(sec_level);
Vinicius Costa Gomesd26a2342011-08-19 21:06:51 -0300764
Brian Gixa68668b2011-08-11 15:49:36 -0700765 hcon->smp_conn = conn;
Brian Gix80fb3a92012-01-31 13:15:20 -0800766 hcon->pending_sec_level = sec_level;
Subramanian Srinivasan311eac42012-10-08 17:22:43 -0700767 if (hcon->link_mode & HCI_LM_MASTER) {
Vinicius Costa Gomes5d873ca2011-07-07 18:59:41 -0300768 struct link_key *key;
769
770 key = hci_find_link_key_type(hcon->hdev, conn->dst,
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700771 KEY_TYPE_LTK);
Vinicius Costa Gomes5d873ca2011-07-07 18:59:41 -0300772
Brian Gix372257b2011-10-25 09:06:30 -0700773 if (smp_encrypt_link(hcon, key) == 0)
Vinicius Costa Gomes5d873ca2011-07-07 18:59:41 -0300774 goto done;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700775 }
776
Brian Gixa68668b2011-08-11 15:49:36 -0700777 hcon->sec_req = FALSE;
778
Vinicius Costa Gomesd26a2342011-08-19 21:06:51 -0300779 if (hcon->link_mode & HCI_LM_MASTER) {
780 struct smp_cmd_pairing cp;
Anderson Brigliaf01ead32011-06-09 18:50:45 -0300781
Archana Ramachandran82dac162013-03-04 17:45:22 -0800782 /* Switch to Pairing Connection Parameters */
783 hci_le_conn_update(hcon, SMP_MIN_CONN_INTERVAL,
784 SMP_MAX_CONN_INTERVAL, SMP_MAX_CONN_LATENCY,
785 SMP_SUPERVISION_TIMEOUT);
786
Brian Gix2b64d152011-12-21 16:12:12 -0800787 build_pairing_cmd(conn, &cp, NULL, authreq);
Brian Gixa68668b2011-08-11 15:49:36 -0700788 hcon->preq[0] = SMP_CMD_PAIRING_REQ;
789 memcpy(&hcon->preq[1], &cp, sizeof(cp));
Anderson Brigliac8e856e2011-06-09 18:50:45 -0300790
Brian Gixe9ceb522011-09-22 10:46:35 -0700791 mod_timer(&hcon->smp_timer, jiffies +
Vinicius Costa Gomesb19d5ce2011-06-14 13:37:41 -0300792 msecs_to_jiffies(SMP_TIMEOUT));
Anderson Brigliaf01ead32011-06-09 18:50:45 -0300793
Anderson Brigliaeb492e02011-06-09 18:50:40 -0300794 smp_send_cmd(conn, SMP_CMD_PAIRING_REQ, sizeof(cp), &cp);
Brian Gix80fb3a92012-01-31 13:15:20 -0800795 hci_conn_hold(hcon);
Anderson Brigliaeb492e02011-06-09 18:50:40 -0300796 } else {
797 struct smp_cmd_security_req cp;
Brian Gix2b64d152011-12-21 16:12:12 -0800798 cp.auth_req = authreq;
Anderson Brigliaeb492e02011-06-09 18:50:40 -0300799 smp_send_cmd(conn, SMP_CMD_SECURITY_REQ, sizeof(cp), &cp);
800 }
801
Vinicius Costa Gomes02bc7452011-07-07 18:59:41 -0300802done:
Vinicius Costa Gomesa5474a82011-01-26 21:42:57 -0300803 set_bit(HCI_CONN_ENCRYPT_PEND, &hcon->pend);
Vinicius Costa Gomesf1cb9af2011-01-26 21:42:57 -0300804
Anderson Brigliaeb492e02011-06-09 18:50:40 -0300805 return 0;
806}
807
Vinicius Costa Gomes7034b912011-07-07 18:59:34 -0300808static int smp_cmd_encrypt_info(struct l2cap_conn *conn, struct sk_buff *skb)
809{
Brian Gixa68668b2011-08-11 15:49:36 -0700810 struct hci_conn *hcon = conn->hcon;
Vinicius Costa Gomes16b90832011-07-07 18:59:39 -0300811 struct smp_cmd_encrypt_info *rp = (void *) skb->data;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700812 u8 rand[8];
813 int err;
Vinicius Costa Gomes16b90832011-07-07 18:59:39 -0300814
815 skb_pull(skb, sizeof(*rp));
816
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700817 BT_DBG("conn %p", conn);
818
819 memset(rand, 0, sizeof(rand));
820
Brian Gixcf956772011-10-20 15:18:51 -0700821 err = hci_add_ltk(hcon->hdev, 0, conn->dst, hcon->dst_type,
822 0, 0, 0, rand, rp->ltk);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700823 if (err)
824 return SMP_UNSPECIFIED;
Vinicius Costa Gomes16b90832011-07-07 18:59:39 -0300825
Vinicius Costa Gomes7034b912011-07-07 18:59:34 -0300826 return 0;
827}
828
829static int smp_cmd_master_ident(struct l2cap_conn *conn, struct sk_buff *skb)
830{
Vinicius Costa Gomesc9839a12012-02-02 21:08:01 -0300831 struct hci_conn *hcon = conn->hcon;
Vinicius Costa Gomese56cede2011-07-07 18:59:39 -0300832 struct smp_cmd_master_ident *rp = (void *) skb->data;
Brian Gixa68668b2011-08-11 15:49:36 -0700833 struct smp_cmd_pairing *paircmd = (void *) &hcon->prsp[1];
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700834 struct link_key *key;
Brian Gixa68668b2011-08-11 15:49:36 -0700835 u8 *keydist;
Vinicius Costa Gomes7034b912011-07-07 18:59:34 -0300836
Vinicius Costa Gomes16b90832011-07-07 18:59:39 -0300837 skb_pull(skb, sizeof(*rp));
838
Brian Gixa68668b2011-08-11 15:49:36 -0700839 key = hci_find_link_key_type(hcon->hdev, conn->dst, KEY_TYPE_LTK);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700840 if (key == NULL)
841 return SMP_UNSPECIFIED;
842
Brian Gixa68668b2011-08-11 15:49:36 -0700843 if (hcon->out)
844 keydist = &paircmd->resp_key_dist;
845 else
846 keydist = &paircmd->init_key_dist;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700847
Brian Gixa68668b2011-08-11 15:49:36 -0700848 BT_DBG("keydist 0x%x", *keydist);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700849
Brian Gixcf956772011-10-20 15:18:51 -0700850 hci_add_ltk(hcon->hdev, 1, conn->dst, hcon->dst_type,
851 hcon->smp_key_size, hcon->auth, rp->ediv,
852 rp->rand, key->val);
Vinicius Costa Gomesc1d5e1d2011-07-07 18:59:34 -0300853
Brian Gixa68668b2011-08-11 15:49:36 -0700854 *keydist &= ~SMP_DIST_ENC_KEY;
855 if (hcon->out) {
856 if (!(*keydist))
857 smp_distribute_keys(conn, 1);
858 }
Vinicius Costa Gomes7034b912011-07-07 18:59:34 -0300859
860 return 0;
861}
862
Anderson Brigliaeb492e02011-06-09 18:50:40 -0300863int smp_sig_channel(struct l2cap_conn *conn, struct sk_buff *skb)
864{
Brian Gixa68668b2011-08-11 15:49:36 -0700865 struct hci_conn *hcon = conn->hcon;
Anderson Brigliaeb492e02011-06-09 18:50:40 -0300866 __u8 code = skb->data[0];
867 __u8 reason;
868 int err = 0;
869
Brian Gixa68668b2011-08-11 15:49:36 -0700870 if (IS_ERR(hcon->hdev->tfm)) {
871 err = PTR_ERR(hcon->hdev->tfm);
Andre Guedes2e65c9d2011-06-30 19:20:56 -0300872 reason = SMP_PAIRING_NOTSUPP;
Brian Gixa68668b2011-08-11 15:49:36 -0700873 BT_ERR("SMP_PAIRING_NOTSUPP %p", hcon->hdev->tfm);
Andre Guedes2e65c9d2011-06-30 19:20:56 -0300874 goto done;
875 }
876
Brian Gixa68668b2011-08-11 15:49:36 -0700877 hcon->smp_conn = conn;
Anderson Brigliaeb492e02011-06-09 18:50:40 -0300878 skb_pull(skb, sizeof(code));
879
880 switch (code) {
881 case SMP_CMD_PAIRING_REQ:
Vinicius Costa Gomesda85e5e2011-06-09 18:50:53 -0300882 reason = smp_cmd_pairing_req(conn, skb);
Anderson Brigliaeb492e02011-06-09 18:50:40 -0300883 break;
884
885 case SMP_CMD_PAIRING_FAIL:
Vinicius Costa Gomesda85e5e2011-06-09 18:50:53 -0300886 reason = 0;
887 err = -EPERM;
Brian Gixe9ceb522011-09-22 10:46:35 -0700888 del_timer(&hcon->smp_timer);
Brian Gix8d0b7d62011-10-12 15:12:42 -0700889 clear_bit(HCI_CONN_ENCRYPT_PEND, &hcon->pend);
Brian Gix570efc92011-10-13 15:59:51 -0700890 mgmt_auth_failed(hcon->hdev->id, conn->dst, skb->data[0]);
Brian Gix6d5fb8a2011-09-09 14:53:04 -0700891 hci_conn_put(hcon);
Anderson Brigliaeb492e02011-06-09 18:50:40 -0300892 break;
893
894 case SMP_CMD_PAIRING_RSP:
Vinicius Costa Gomesda85e5e2011-06-09 18:50:53 -0300895 reason = smp_cmd_pairing_rsp(conn, skb);
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300896 break;
897
898 case SMP_CMD_SECURITY_REQ:
Vinicius Costa Gomesda85e5e2011-06-09 18:50:53 -0300899 reason = smp_cmd_security_req(conn, skb);
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300900 break;
901
Anderson Brigliaeb492e02011-06-09 18:50:40 -0300902 case SMP_CMD_PAIRING_CONFIRM:
Vinicius Costa Gomesda85e5e2011-06-09 18:50:53 -0300903 reason = smp_cmd_pairing_confirm(conn, skb);
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300904 break;
905
Anderson Brigliaeb492e02011-06-09 18:50:40 -0300906 case SMP_CMD_PAIRING_RANDOM:
Vinicius Costa Gomesda85e5e2011-06-09 18:50:53 -0300907 reason = smp_cmd_pairing_random(conn, skb);
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300908 break;
909
Anderson Brigliaeb492e02011-06-09 18:50:40 -0300910 case SMP_CMD_ENCRYPT_INFO:
Vinicius Costa Gomes7034b912011-07-07 18:59:34 -0300911 reason = smp_cmd_encrypt_info(conn, skb);
912 break;
913
Anderson Brigliaeb492e02011-06-09 18:50:40 -0300914 case SMP_CMD_MASTER_IDENT:
Vinicius Costa Gomes7034b912011-07-07 18:59:34 -0300915 reason = smp_cmd_master_ident(conn, skb);
916 break;
917
Anderson Brigliaeb492e02011-06-09 18:50:40 -0300918 case SMP_CMD_IDENT_INFO:
919 case SMP_CMD_IDENT_ADDR_INFO:
920 case SMP_CMD_SIGN_INFO:
Vinicius Costa Gomes7034b912011-07-07 18:59:34 -0300921 /* Just ignored */
922 reason = 0;
923 break;
924
Anderson Brigliaeb492e02011-06-09 18:50:40 -0300925 default:
926 BT_DBG("Unknown command code 0x%2.2x", code);
927
928 reason = SMP_CMD_NOTSUPP;
Vinicius Costa Gomes3a0259b2011-06-09 18:50:43 -0300929 err = -EOPNOTSUPP;
930 goto done;
931 }
932
933done:
Brian Gixa68668b2011-08-11 15:49:36 -0700934 if (reason) {
935 BT_ERR("SMP_CMD_PAIRING_FAIL: %d", reason);
Anderson Briglia133e14c2011-06-09 18:50:40 -0300936 smp_send_cmd(conn, SMP_CMD_PAIRING_FAIL, sizeof(reason),
937 &reason);
Brian Gixe9ceb522011-09-22 10:46:35 -0700938 del_timer(&hcon->smp_timer);
Brian Gix8d0b7d62011-10-12 15:12:42 -0700939 clear_bit(HCI_CONN_ENCRYPT_PEND, &hcon->pend);
Brian Gix58ba0772011-09-23 13:40:16 -0700940 mgmt_auth_failed(hcon->hdev->id, conn->dst, reason);
Brian Gix6d5fb8a2011-09-09 14:53:04 -0700941 hci_conn_put(hcon);
Brian Gixa68668b2011-08-11 15:49:36 -0700942 }
Anderson Brigliaeb492e02011-06-09 18:50:40 -0300943
944 kfree_skb(skb);
945 return err;
946}
Vinicius Costa Gomes7034b912011-07-07 18:59:34 -0300947
Brian Gixa68668b2011-08-11 15:49:36 -0700948static int smp_distribute_keys(struct l2cap_conn *conn, __u8 force)
Vinicius Costa Gomes7034b912011-07-07 18:59:34 -0300949{
Brian Gixa68668b2011-08-11 15:49:36 -0700950 struct hci_conn *hcon = conn->hcon;
Vinicius Costa Gomes7034b912011-07-07 18:59:34 -0300951 struct smp_cmd_pairing *req, *rsp;
952 __u8 *keydist;
953
954 BT_DBG("conn %p force %d", conn, force);
955
Brian Gixa68668b2011-08-11 15:49:36 -0700956 if (IS_ERR(hcon->hdev->tfm))
957 return PTR_ERR(hcon->hdev->tfm);
Vinicius Costa Gomesd26a2342011-08-19 21:06:51 -0300958
Brian Gixa68668b2011-08-11 15:49:36 -0700959 rsp = (void *) &hcon->prsp[1];
Vinicius Costa Gomes7034b912011-07-07 18:59:34 -0300960
961 /* The responder sends its keys first */
Brian Gixa68668b2011-08-11 15:49:36 -0700962 if (!force && hcon->out && (rsp->resp_key_dist & 0x07))
Vinicius Costa Gomes7034b912011-07-07 18:59:34 -0300963 return 0;
964
Brian Gixa68668b2011-08-11 15:49:36 -0700965 req = (void *) &hcon->preq[1];
Vinicius Costa Gomes7034b912011-07-07 18:59:34 -0300966
Brian Gixa68668b2011-08-11 15:49:36 -0700967 if (hcon->out) {
Vinicius Costa Gomes7034b912011-07-07 18:59:34 -0300968 keydist = &rsp->init_key_dist;
969 *keydist &= req->init_key_dist;
970 } else {
971 keydist = &rsp->resp_key_dist;
972 *keydist &= req->resp_key_dist;
973 }
974
975
976 BT_DBG("keydist 0x%x", *keydist);
977
978 if (*keydist & SMP_DIST_ENC_KEY) {
979 struct smp_cmd_encrypt_info enc;
980 struct smp_cmd_master_ident ident;
981 __le16 ediv;
982
983 get_random_bytes(enc.ltk, sizeof(enc.ltk));
984 get_random_bytes(&ediv, sizeof(ediv));
985 get_random_bytes(ident.rand, sizeof(ident.rand));
986
987 smp_send_cmd(conn, SMP_CMD_ENCRYPT_INFO, sizeof(enc), &enc);
988
Brian Gixcf956772011-10-20 15:18:51 -0700989 hci_add_ltk(hcon->hdev, 1, conn->dst, hcon->dst_type,
990 hcon->smp_key_size, hcon->auth, ediv,
991 ident.rand, enc.ltk);
Vinicius Costa Gomes16b90832011-07-07 18:59:39 -0300992
Vinicius Costa Gomes7034b912011-07-07 18:59:34 -0300993 ident.ediv = cpu_to_le16(ediv);
994
995 smp_send_cmd(conn, SMP_CMD_MASTER_IDENT, sizeof(ident), &ident);
996
997 *keydist &= ~SMP_DIST_ENC_KEY;
998 }
999
1000 if (*keydist & SMP_DIST_ID_KEY) {
1001 struct smp_cmd_ident_addr_info addrinfo;
1002 struct smp_cmd_ident_info idinfo;
1003
1004 /* Send a dummy key */
1005 get_random_bytes(idinfo.irk, sizeof(idinfo.irk));
1006
1007 smp_send_cmd(conn, SMP_CMD_IDENT_INFO, sizeof(idinfo), &idinfo);
1008
1009 /* Just public address */
1010 memset(&addrinfo, 0, sizeof(addrinfo));
1011 bacpy(&addrinfo.bdaddr, conn->src);
1012
1013 smp_send_cmd(conn, SMP_CMD_IDENT_ADDR_INFO, sizeof(addrinfo),
1014 &addrinfo);
1015
1016 *keydist &= ~SMP_DIST_ID_KEY;
1017 }
1018
1019 if (*keydist & SMP_DIST_SIGN) {
1020 struct smp_cmd_sign_info sign;
1021
1022 /* Send a dummy key */
1023 get_random_bytes(sign.csrk, sizeof(sign.csrk));
1024
1025 smp_send_cmd(conn, SMP_CMD_SIGN_INFO, sizeof(sign), &sign);
1026
1027 *keydist &= ~SMP_DIST_SIGN;
1028 }
1029
Brian Gix2a335262011-11-17 12:59:23 -08001030 if (hcon->out) {
Brian Gixe57c1672011-09-13 12:34:59 -07001031 if (hcon->disconn_cfm_cb)
1032 hcon->disconn_cfm_cb(hcon, 0);
Brian Gixe9ceb522011-09-22 10:46:35 -07001033 del_timer(&hcon->smp_timer);
Brian Gix8d0b7d62011-10-12 15:12:42 -07001034 clear_bit(HCI_CONN_ENCRYPT_PEND, &hcon->pend);
Brian Gix2a335262011-11-17 12:59:23 -08001035 hci_conn_put(hcon);
1036 } else if (rsp->resp_key_dist) {
1037 if (hcon->disconn_cfm_cb)
1038 hcon->disconn_cfm_cb(hcon, SMP_UNSPECIFIED);
1039 clear_bit(HCI_CONN_ENCRYPT_PEND, &hcon->pend);
Brian Gix58ba0772011-09-23 13:40:16 -07001040 mgmt_auth_failed(hcon->hdev->id, conn->dst, SMP_UNSPECIFIED);
Brian Gix6d5fb8a2011-09-09 14:53:04 -07001041 hci_conn_put(hcon);
Vinicius Costa Gomesd26a2342011-08-19 21:06:51 -03001042 }
1043
Vinicius Costa Gomes7034b912011-07-07 18:59:34 -03001044 return 0;
1045}
Brian Gixa68668b2011-08-11 15:49:36 -07001046
1047int smp_link_encrypt_cmplt(struct l2cap_conn *conn, u8 status, u8 encrypt)
1048{
1049 struct hci_conn *hcon = conn->hcon;
1050
1051 BT_DBG("smp: %d %d %d", status, encrypt, hcon->sec_req);
1052
Brian Gix8d0b7d62011-10-12 15:12:42 -07001053 clear_bit(HCI_CONN_ENCRYPT_PEND, &hcon->pend);
1054
Brian Gix80fb3a92012-01-31 13:15:20 -08001055 if (!status && encrypt && hcon->sec_level < hcon->pending_sec_level)
1056 hcon->sec_level = hcon->pending_sec_level;
1057
Brian Gixa68668b2011-08-11 15:49:36 -07001058 if (!status && encrypt && !hcon->sec_req)
Brian Gix80fb3a92012-01-31 13:15:20 -08001059 return smp_distribute_keys(conn, 0);
Brian Gixa68668b2011-08-11 15:49:36 -07001060
1061 /* Fall back to Pairing request if failed a Link Security request */
1062 else if (hcon->sec_req && (status || !encrypt))
Brian Gix80fb3a92012-01-31 13:15:20 -08001063 smp_conn_security(conn, hcon->pending_sec_level);
Brian Gixa68668b2011-08-11 15:49:36 -07001064
Brian Gix80fb3a92012-01-31 13:15:20 -08001065 hci_conn_put(hcon);
Brian Gix8d0b7d62011-10-12 15:12:42 -07001066
Vinicius Costa Gomesc1d5e1d2011-07-07 18:59:34 -03001067 return 0;
1068}
Brian Gixe9ceb522011-09-22 10:46:35 -07001069
1070void smp_timeout(unsigned long arg)
1071{
1072 struct l2cap_conn *conn = (void *) arg;
1073 u8 reason = SMP_UNSPECIFIED;
1074
1075 BT_DBG("%p", conn);
1076
1077 smp_send_cmd(conn, SMP_CMD_PAIRING_FAIL, sizeof(reason), &reason);
Brian Gix8d0b7d62011-10-12 15:12:42 -07001078 clear_bit(HCI_CONN_ENCRYPT_PEND, &conn->hcon->pend);
Brian Gix58ba0772011-09-23 13:40:16 -07001079 mgmt_auth_failed(conn->hcon->hdev->id, conn->dst, SMP_UNSPECIFIED);
Brian Gixe9ceb522011-09-22 10:46:35 -07001080 hci_conn_put(conn->hcon);
1081}