blob: b9089969cc58486d8d80e6b08a182853dd88c03e [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
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300718 skb_pull(skb, sizeof(*rp));
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300719
Vinicius Costa Gomesda85e5e2011-06-09 18:50:53 -0300720 memset(&cp, 0, sizeof(cp));
Vinicius Costa Gomes54790f72011-07-07 18:59:38 -0300721 build_pairing_cmd(conn, &cp, NULL, rp->auth_req);
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300722
Brian Gix27a795c2012-04-19 11:05:06 -0700723 hcon->pending_sec_level = authreq_to_seclevel(rp->auth_req);
Brian Gixa68668b2011-08-11 15:49:36 -0700724 hcon->preq[0] = SMP_CMD_PAIRING_REQ;
725 memcpy(&hcon->preq[1], &cp, sizeof(cp));
Anderson Brigliaf01ead32011-06-09 18:50:45 -0300726
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300727 smp_send_cmd(conn, SMP_CMD_PAIRING_REQ, sizeof(cp), &cp);
Vinicius Costa Gomesf1cb9af2011-01-26 21:42:57 -0300728
Brian Gixe9ceb522011-09-22 10:46:35 -0700729 mod_timer(&hcon->smp_timer, jiffies + msecs_to_jiffies(SMP_TIMEOUT));
Vinicius Costa Gomesb19d5ce2011-06-14 13:37:41 -0300730
Vinicius Costa Gomesa5474a82011-01-26 21:42:57 -0300731 set_bit(HCI_CONN_ENCRYPT_PEND, &hcon->pend);
Vinicius Costa Gomesa5474a82011-01-26 21:42:57 -0300732
Brian Gix8d0b7d62011-10-12 15:12:42 -0700733 hci_conn_hold(hcon);
734
Vinicius Costa Gomesda85e5e2011-06-09 18:50:53 -0300735 return 0;
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300736}
737
Anderson Brigliaeb492e02011-06-09 18:50:40 -0300738int smp_conn_security(struct l2cap_conn *conn, __u8 sec_level)
739{
Vinicius Costa Gomes3a0259b2011-06-09 18:50:43 -0300740 struct hci_conn *hcon = conn->hcon;
Brian Gix2b64d152011-12-21 16:12:12 -0800741 __u8 authreq;
Anderson Brigliaeb492e02011-06-09 18:50:40 -0300742
Brian Gix80fb3a92012-01-31 13:15:20 -0800743 BT_DBG("conn %p hcon %p %d req: %d",
744 conn, hcon, hcon->sec_level, sec_level);
Vinicius Costa Gomes3a0259b2011-06-09 18:50:43 -0300745
Brian Gix80fb3a92012-01-31 13:15:20 -0800746 if (IS_ERR(hcon->hdev->tfm))
Andre Guedes2e65c9d2011-06-30 19:20:56 -0300747 return 1;
748
Brian Gix80fb3a92012-01-31 13:15:20 -0800749 if (test_bit(HCI_CONN_ENCRYPT_PEND, &hcon->pend))
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700750 return -EINPROGRESS;
Anderson Briglia133e14c2011-06-09 18:50:40 -0300751
Vinicius Costa Gomesf1cb9af2011-01-26 21:42:57 -0300752 if (sec_level == BT_SECURITY_LOW)
Anderson Brigliaeb492e02011-06-09 18:50:40 -0300753 return 1;
Vinicius Costa Gomesf1cb9af2011-01-26 21:42:57 -0300754
Brian Gix80fb3a92012-01-31 13:15:20 -0800755
Vinicius Costa Gomesf1cb9af2011-01-26 21:42:57 -0300756 if (hcon->sec_level >= sec_level)
757 return 1;
758
Brian Gix2b64d152011-12-21 16:12:12 -0800759 authreq = seclevel_to_authreq(sec_level);
Vinicius Costa Gomesd26a2342011-08-19 21:06:51 -0300760
Brian Gixa68668b2011-08-11 15:49:36 -0700761 hcon->smp_conn = conn;
Brian Gix80fb3a92012-01-31 13:15:20 -0800762 hcon->pending_sec_level = sec_level;
Subramanian Srinivasan311eac42012-10-08 17:22:43 -0700763 if (hcon->link_mode & HCI_LM_MASTER) {
Vinicius Costa Gomes5d873ca2011-07-07 18:59:41 -0300764 struct link_key *key;
765
766 key = hci_find_link_key_type(hcon->hdev, conn->dst,
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700767 KEY_TYPE_LTK);
Vinicius Costa Gomes5d873ca2011-07-07 18:59:41 -0300768
Brian Gix372257b2011-10-25 09:06:30 -0700769 if (smp_encrypt_link(hcon, key) == 0)
Vinicius Costa Gomes5d873ca2011-07-07 18:59:41 -0300770 goto done;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700771 }
772
Brian Gixa68668b2011-08-11 15:49:36 -0700773 hcon->sec_req = FALSE;
774
Vinicius Costa Gomesd26a2342011-08-19 21:06:51 -0300775 if (hcon->link_mode & HCI_LM_MASTER) {
776 struct smp_cmd_pairing cp;
Anderson Brigliaf01ead32011-06-09 18:50:45 -0300777
Brian Gix2b64d152011-12-21 16:12:12 -0800778 build_pairing_cmd(conn, &cp, NULL, authreq);
Brian Gixa68668b2011-08-11 15:49:36 -0700779 hcon->preq[0] = SMP_CMD_PAIRING_REQ;
780 memcpy(&hcon->preq[1], &cp, sizeof(cp));
Anderson Brigliac8e856e2011-06-09 18:50:45 -0300781
Brian Gixe9ceb522011-09-22 10:46:35 -0700782 mod_timer(&hcon->smp_timer, jiffies +
Vinicius Costa Gomesb19d5ce2011-06-14 13:37:41 -0300783 msecs_to_jiffies(SMP_TIMEOUT));
Anderson Brigliaf01ead32011-06-09 18:50:45 -0300784
Anderson Brigliaeb492e02011-06-09 18:50:40 -0300785 smp_send_cmd(conn, SMP_CMD_PAIRING_REQ, sizeof(cp), &cp);
Brian Gix80fb3a92012-01-31 13:15:20 -0800786 hci_conn_hold(hcon);
Anderson Brigliaeb492e02011-06-09 18:50:40 -0300787 } else {
788 struct smp_cmd_security_req cp;
Brian Gix2b64d152011-12-21 16:12:12 -0800789 cp.auth_req = authreq;
Anderson Brigliaeb492e02011-06-09 18:50:40 -0300790 smp_send_cmd(conn, SMP_CMD_SECURITY_REQ, sizeof(cp), &cp);
791 }
792
Vinicius Costa Gomes02bc7452011-07-07 18:59:41 -0300793done:
Vinicius Costa Gomesa5474a82011-01-26 21:42:57 -0300794 set_bit(HCI_CONN_ENCRYPT_PEND, &hcon->pend);
Vinicius Costa Gomesf1cb9af2011-01-26 21:42:57 -0300795
Anderson Brigliaeb492e02011-06-09 18:50:40 -0300796 return 0;
797}
798
Vinicius Costa Gomes7034b912011-07-07 18:59:34 -0300799static int smp_cmd_encrypt_info(struct l2cap_conn *conn, struct sk_buff *skb)
800{
Brian Gixa68668b2011-08-11 15:49:36 -0700801 struct hci_conn *hcon = conn->hcon;
Vinicius Costa Gomes16b90832011-07-07 18:59:39 -0300802 struct smp_cmd_encrypt_info *rp = (void *) skb->data;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700803 u8 rand[8];
804 int err;
Vinicius Costa Gomes16b90832011-07-07 18:59:39 -0300805
806 skb_pull(skb, sizeof(*rp));
807
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700808 BT_DBG("conn %p", conn);
809
810 memset(rand, 0, sizeof(rand));
811
Brian Gixcf956772011-10-20 15:18:51 -0700812 err = hci_add_ltk(hcon->hdev, 0, conn->dst, hcon->dst_type,
813 0, 0, 0, rand, rp->ltk);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700814 if (err)
815 return SMP_UNSPECIFIED;
Vinicius Costa Gomes16b90832011-07-07 18:59:39 -0300816
Vinicius Costa Gomes7034b912011-07-07 18:59:34 -0300817 return 0;
818}
819
820static int smp_cmd_master_ident(struct l2cap_conn *conn, struct sk_buff *skb)
821{
Vinicius Costa Gomesc9839a12012-02-02 21:08:01 -0300822 struct hci_conn *hcon = conn->hcon;
Vinicius Costa Gomese56cede2011-07-07 18:59:39 -0300823 struct smp_cmd_master_ident *rp = (void *) skb->data;
Brian Gixa68668b2011-08-11 15:49:36 -0700824 struct smp_cmd_pairing *paircmd = (void *) &hcon->prsp[1];
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700825 struct link_key *key;
Brian Gixa68668b2011-08-11 15:49:36 -0700826 u8 *keydist;
Vinicius Costa Gomes7034b912011-07-07 18:59:34 -0300827
Vinicius Costa Gomes16b90832011-07-07 18:59:39 -0300828 skb_pull(skb, sizeof(*rp));
829
Brian Gixa68668b2011-08-11 15:49:36 -0700830 key = hci_find_link_key_type(hcon->hdev, conn->dst, KEY_TYPE_LTK);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700831 if (key == NULL)
832 return SMP_UNSPECIFIED;
833
Brian Gixa68668b2011-08-11 15:49:36 -0700834 if (hcon->out)
835 keydist = &paircmd->resp_key_dist;
836 else
837 keydist = &paircmd->init_key_dist;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700838
Brian Gixa68668b2011-08-11 15:49:36 -0700839 BT_DBG("keydist 0x%x", *keydist);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700840
Brian Gixcf956772011-10-20 15:18:51 -0700841 hci_add_ltk(hcon->hdev, 1, conn->dst, hcon->dst_type,
842 hcon->smp_key_size, hcon->auth, rp->ediv,
843 rp->rand, key->val);
Vinicius Costa Gomesc1d5e1d2011-07-07 18:59:34 -0300844
Brian Gixa68668b2011-08-11 15:49:36 -0700845 *keydist &= ~SMP_DIST_ENC_KEY;
846 if (hcon->out) {
847 if (!(*keydist))
848 smp_distribute_keys(conn, 1);
849 }
Vinicius Costa Gomes7034b912011-07-07 18:59:34 -0300850
851 return 0;
852}
853
Anderson Brigliaeb492e02011-06-09 18:50:40 -0300854int smp_sig_channel(struct l2cap_conn *conn, struct sk_buff *skb)
855{
Brian Gixa68668b2011-08-11 15:49:36 -0700856 struct hci_conn *hcon = conn->hcon;
Anderson Brigliaeb492e02011-06-09 18:50:40 -0300857 __u8 code = skb->data[0];
858 __u8 reason;
859 int err = 0;
860
Brian Gixa68668b2011-08-11 15:49:36 -0700861 if (IS_ERR(hcon->hdev->tfm)) {
862 err = PTR_ERR(hcon->hdev->tfm);
Andre Guedes2e65c9d2011-06-30 19:20:56 -0300863 reason = SMP_PAIRING_NOTSUPP;
Brian Gixa68668b2011-08-11 15:49:36 -0700864 BT_ERR("SMP_PAIRING_NOTSUPP %p", hcon->hdev->tfm);
Andre Guedes2e65c9d2011-06-30 19:20:56 -0300865 goto done;
866 }
867
Brian Gixa68668b2011-08-11 15:49:36 -0700868 hcon->smp_conn = conn;
Anderson Brigliaeb492e02011-06-09 18:50:40 -0300869 skb_pull(skb, sizeof(code));
870
871 switch (code) {
872 case SMP_CMD_PAIRING_REQ:
Vinicius Costa Gomesda85e5e2011-06-09 18:50:53 -0300873 reason = smp_cmd_pairing_req(conn, skb);
Anderson Brigliaeb492e02011-06-09 18:50:40 -0300874 break;
875
876 case SMP_CMD_PAIRING_FAIL:
Vinicius Costa Gomesda85e5e2011-06-09 18:50:53 -0300877 reason = 0;
878 err = -EPERM;
Brian Gixe9ceb522011-09-22 10:46:35 -0700879 del_timer(&hcon->smp_timer);
Brian Gix8d0b7d62011-10-12 15:12:42 -0700880 clear_bit(HCI_CONN_ENCRYPT_PEND, &hcon->pend);
Brian Gix570efc92011-10-13 15:59:51 -0700881 mgmt_auth_failed(hcon->hdev->id, conn->dst, skb->data[0]);
Brian Gix6d5fb8a2011-09-09 14:53:04 -0700882 hci_conn_put(hcon);
Anderson Brigliaeb492e02011-06-09 18:50:40 -0300883 break;
884
885 case SMP_CMD_PAIRING_RSP:
Vinicius Costa Gomesda85e5e2011-06-09 18:50:53 -0300886 reason = smp_cmd_pairing_rsp(conn, skb);
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300887 break;
888
889 case SMP_CMD_SECURITY_REQ:
Vinicius Costa Gomesda85e5e2011-06-09 18:50:53 -0300890 reason = smp_cmd_security_req(conn, skb);
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300891 break;
892
Anderson Brigliaeb492e02011-06-09 18:50:40 -0300893 case SMP_CMD_PAIRING_CONFIRM:
Vinicius Costa Gomesda85e5e2011-06-09 18:50:53 -0300894 reason = smp_cmd_pairing_confirm(conn, skb);
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300895 break;
896
Anderson Brigliaeb492e02011-06-09 18:50:40 -0300897 case SMP_CMD_PAIRING_RANDOM:
Vinicius Costa Gomesda85e5e2011-06-09 18:50:53 -0300898 reason = smp_cmd_pairing_random(conn, skb);
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300899 break;
900
Anderson Brigliaeb492e02011-06-09 18:50:40 -0300901 case SMP_CMD_ENCRYPT_INFO:
Vinicius Costa Gomes7034b912011-07-07 18:59:34 -0300902 reason = smp_cmd_encrypt_info(conn, skb);
903 break;
904
Anderson Brigliaeb492e02011-06-09 18:50:40 -0300905 case SMP_CMD_MASTER_IDENT:
Vinicius Costa Gomes7034b912011-07-07 18:59:34 -0300906 reason = smp_cmd_master_ident(conn, skb);
907 break;
908
Anderson Brigliaeb492e02011-06-09 18:50:40 -0300909 case SMP_CMD_IDENT_INFO:
910 case SMP_CMD_IDENT_ADDR_INFO:
911 case SMP_CMD_SIGN_INFO:
Vinicius Costa Gomes7034b912011-07-07 18:59:34 -0300912 /* Just ignored */
913 reason = 0;
914 break;
915
Anderson Brigliaeb492e02011-06-09 18:50:40 -0300916 default:
917 BT_DBG("Unknown command code 0x%2.2x", code);
918
919 reason = SMP_CMD_NOTSUPP;
Vinicius Costa Gomes3a0259b2011-06-09 18:50:43 -0300920 err = -EOPNOTSUPP;
921 goto done;
922 }
923
924done:
Brian Gixa68668b2011-08-11 15:49:36 -0700925 if (reason) {
926 BT_ERR("SMP_CMD_PAIRING_FAIL: %d", reason);
Anderson Briglia133e14c2011-06-09 18:50:40 -0300927 smp_send_cmd(conn, SMP_CMD_PAIRING_FAIL, sizeof(reason),
928 &reason);
Brian Gixe9ceb522011-09-22 10:46:35 -0700929 del_timer(&hcon->smp_timer);
Brian Gix8d0b7d62011-10-12 15:12:42 -0700930 clear_bit(HCI_CONN_ENCRYPT_PEND, &hcon->pend);
Brian Gix58ba0772011-09-23 13:40:16 -0700931 mgmt_auth_failed(hcon->hdev->id, conn->dst, reason);
Brian Gix6d5fb8a2011-09-09 14:53:04 -0700932 hci_conn_put(hcon);
Brian Gixa68668b2011-08-11 15:49:36 -0700933 }
Anderson Brigliaeb492e02011-06-09 18:50:40 -0300934
935 kfree_skb(skb);
936 return err;
937}
Vinicius Costa Gomes7034b912011-07-07 18:59:34 -0300938
Brian Gixa68668b2011-08-11 15:49:36 -0700939static int smp_distribute_keys(struct l2cap_conn *conn, __u8 force)
Vinicius Costa Gomes7034b912011-07-07 18:59:34 -0300940{
Brian Gixa68668b2011-08-11 15:49:36 -0700941 struct hci_conn *hcon = conn->hcon;
Vinicius Costa Gomes7034b912011-07-07 18:59:34 -0300942 struct smp_cmd_pairing *req, *rsp;
943 __u8 *keydist;
944
945 BT_DBG("conn %p force %d", conn, force);
946
Brian Gixa68668b2011-08-11 15:49:36 -0700947 if (IS_ERR(hcon->hdev->tfm))
948 return PTR_ERR(hcon->hdev->tfm);
Vinicius Costa Gomesd26a2342011-08-19 21:06:51 -0300949
Brian Gixa68668b2011-08-11 15:49:36 -0700950 rsp = (void *) &hcon->prsp[1];
Vinicius Costa Gomes7034b912011-07-07 18:59:34 -0300951
952 /* The responder sends its keys first */
Brian Gixa68668b2011-08-11 15:49:36 -0700953 if (!force && hcon->out && (rsp->resp_key_dist & 0x07))
Vinicius Costa Gomes7034b912011-07-07 18:59:34 -0300954 return 0;
955
Brian Gixa68668b2011-08-11 15:49:36 -0700956 req = (void *) &hcon->preq[1];
Vinicius Costa Gomes7034b912011-07-07 18:59:34 -0300957
Brian Gixa68668b2011-08-11 15:49:36 -0700958 if (hcon->out) {
Vinicius Costa Gomes7034b912011-07-07 18:59:34 -0300959 keydist = &rsp->init_key_dist;
960 *keydist &= req->init_key_dist;
961 } else {
962 keydist = &rsp->resp_key_dist;
963 *keydist &= req->resp_key_dist;
964 }
965
966
967 BT_DBG("keydist 0x%x", *keydist);
968
969 if (*keydist & SMP_DIST_ENC_KEY) {
970 struct smp_cmd_encrypt_info enc;
971 struct smp_cmd_master_ident ident;
972 __le16 ediv;
973
974 get_random_bytes(enc.ltk, sizeof(enc.ltk));
975 get_random_bytes(&ediv, sizeof(ediv));
976 get_random_bytes(ident.rand, sizeof(ident.rand));
977
978 smp_send_cmd(conn, SMP_CMD_ENCRYPT_INFO, sizeof(enc), &enc);
979
Brian Gixcf956772011-10-20 15:18:51 -0700980 hci_add_ltk(hcon->hdev, 1, conn->dst, hcon->dst_type,
981 hcon->smp_key_size, hcon->auth, ediv,
982 ident.rand, enc.ltk);
Vinicius Costa Gomes16b90832011-07-07 18:59:39 -0300983
Vinicius Costa Gomes7034b912011-07-07 18:59:34 -0300984 ident.ediv = cpu_to_le16(ediv);
985
986 smp_send_cmd(conn, SMP_CMD_MASTER_IDENT, sizeof(ident), &ident);
987
988 *keydist &= ~SMP_DIST_ENC_KEY;
989 }
990
991 if (*keydist & SMP_DIST_ID_KEY) {
992 struct smp_cmd_ident_addr_info addrinfo;
993 struct smp_cmd_ident_info idinfo;
994
995 /* Send a dummy key */
996 get_random_bytes(idinfo.irk, sizeof(idinfo.irk));
997
998 smp_send_cmd(conn, SMP_CMD_IDENT_INFO, sizeof(idinfo), &idinfo);
999
1000 /* Just public address */
1001 memset(&addrinfo, 0, sizeof(addrinfo));
1002 bacpy(&addrinfo.bdaddr, conn->src);
1003
1004 smp_send_cmd(conn, SMP_CMD_IDENT_ADDR_INFO, sizeof(addrinfo),
1005 &addrinfo);
1006
1007 *keydist &= ~SMP_DIST_ID_KEY;
1008 }
1009
1010 if (*keydist & SMP_DIST_SIGN) {
1011 struct smp_cmd_sign_info sign;
1012
1013 /* Send a dummy key */
1014 get_random_bytes(sign.csrk, sizeof(sign.csrk));
1015
1016 smp_send_cmd(conn, SMP_CMD_SIGN_INFO, sizeof(sign), &sign);
1017
1018 *keydist &= ~SMP_DIST_SIGN;
1019 }
1020
Brian Gix2a335262011-11-17 12:59:23 -08001021 if (hcon->out) {
Brian Gixe57c1672011-09-13 12:34:59 -07001022 if (hcon->disconn_cfm_cb)
1023 hcon->disconn_cfm_cb(hcon, 0);
Brian Gixe9ceb522011-09-22 10:46:35 -07001024 del_timer(&hcon->smp_timer);
Brian Gix8d0b7d62011-10-12 15:12:42 -07001025 clear_bit(HCI_CONN_ENCRYPT_PEND, &hcon->pend);
Brian Gix2a335262011-11-17 12:59:23 -08001026 hci_conn_put(hcon);
1027 } else if (rsp->resp_key_dist) {
1028 if (hcon->disconn_cfm_cb)
1029 hcon->disconn_cfm_cb(hcon, SMP_UNSPECIFIED);
1030 clear_bit(HCI_CONN_ENCRYPT_PEND, &hcon->pend);
Brian Gix58ba0772011-09-23 13:40:16 -07001031 mgmt_auth_failed(hcon->hdev->id, conn->dst, SMP_UNSPECIFIED);
Brian Gix6d5fb8a2011-09-09 14:53:04 -07001032 hci_conn_put(hcon);
Vinicius Costa Gomesd26a2342011-08-19 21:06:51 -03001033 }
1034
Vinicius Costa Gomes7034b912011-07-07 18:59:34 -03001035 return 0;
1036}
Brian Gixa68668b2011-08-11 15:49:36 -07001037
1038int smp_link_encrypt_cmplt(struct l2cap_conn *conn, u8 status, u8 encrypt)
1039{
1040 struct hci_conn *hcon = conn->hcon;
1041
1042 BT_DBG("smp: %d %d %d", status, encrypt, hcon->sec_req);
1043
Brian Gix8d0b7d62011-10-12 15:12:42 -07001044 clear_bit(HCI_CONN_ENCRYPT_PEND, &hcon->pend);
1045
Brian Gix80fb3a92012-01-31 13:15:20 -08001046 if (!status && encrypt && hcon->sec_level < hcon->pending_sec_level)
1047 hcon->sec_level = hcon->pending_sec_level;
1048
Brian Gixa68668b2011-08-11 15:49:36 -07001049 if (!status && encrypt && !hcon->sec_req)
Brian Gix80fb3a92012-01-31 13:15:20 -08001050 return smp_distribute_keys(conn, 0);
Brian Gixa68668b2011-08-11 15:49:36 -07001051
1052 /* Fall back to Pairing request if failed a Link Security request */
1053 else if (hcon->sec_req && (status || !encrypt))
Brian Gix80fb3a92012-01-31 13:15:20 -08001054 smp_conn_security(conn, hcon->pending_sec_level);
Brian Gixa68668b2011-08-11 15:49:36 -07001055
Brian Gix80fb3a92012-01-31 13:15:20 -08001056 hci_conn_put(hcon);
Brian Gix8d0b7d62011-10-12 15:12:42 -07001057
Vinicius Costa Gomesc1d5e1d2011-07-07 18:59:34 -03001058 return 0;
1059}
Brian Gixe9ceb522011-09-22 10:46:35 -07001060
1061void smp_timeout(unsigned long arg)
1062{
1063 struct l2cap_conn *conn = (void *) arg;
1064 u8 reason = SMP_UNSPECIFIED;
1065
1066 BT_DBG("%p", conn);
1067
1068 smp_send_cmd(conn, SMP_CMD_PAIRING_FAIL, sizeof(reason), &reason);
Brian Gix8d0b7d62011-10-12 15:12:42 -07001069 clear_bit(HCI_CONN_ENCRYPT_PEND, &conn->hcon->pend);
Brian Gix58ba0772011-09-23 13:40:16 -07001070 mgmt_auth_failed(conn->hcon->hdev->id, conn->dst, SMP_UNSPECIFIED);
Brian Gixe9ceb522011-09-22 10:46:35 -07001071 hci_conn_put(conn->hcon);
1072}