blob: 517779f441c780e10810f702ea114acf99b0c5e6 [file] [log] [blame]
Anderson Brigliaeb492e02011-06-09 18:50:40 -03001/*
2 BlueZ - Bluetooth protocol stack for Linux
3 Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
4
5 This program is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License version 2 as
7 published by the Free Software Foundation;
8
9 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
10 OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
11 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF THIRD PARTY RIGHTS.
12 IN NO EVENT SHALL THE COPYRIGHT HOLDER(S) AND AUTHOR(S) BE LIABLE FOR ANY
13 CLAIM, OR ANY SPECIAL INDIRECT OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES
14 WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15 ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16 OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17
18 ALL LIABILITY, INCLUDING LIABILITY FOR INFRINGEMENT OF ANY PATENTS,
19 COPYRIGHTS, TRADEMARKS OR OTHER RIGHTS, RELATING TO USE OF THIS
20 SOFTWARE IS DISCLAIMED.
21*/
22
Steve Mucklef132c6c2012-06-06 18:30:57 -070023#include <linux/interrupt.h>
24#include <linux/module.h>
25
Anderson Brigliaeb492e02011-06-09 18:50:40 -030026#include <net/bluetooth/bluetooth.h>
27#include <net/bluetooth/hci_core.h>
28#include <net/bluetooth/l2cap.h>
Brian Gix2b64d152011-12-21 16:12:12 -080029#include <net/bluetooth/mgmt.h>
Anderson Brigliaeb492e02011-06-09 18:50:40 -030030#include <net/bluetooth/smp.h>
Anderson Brigliad22ef0b2011-06-09 18:50:44 -030031#include <linux/crypto.h>
32#include <crypto/b128ops.h>
Brian Gixa68668b2011-08-11 15:49:36 -070033#include <asm/unaligned.h>
Anderson Brigliad22ef0b2011-06-09 18:50:44 -030034
Vinicius Costa Gomesb19d5ce2011-06-14 13:37:41 -030035#define SMP_TIMEOUT 30000 /* 30 seconds */
36
Brian Gix7f7e16c2011-11-01 16:27:25 -070037#define SMP_MIN_CONN_INTERVAL 40 /* 50ms (40 * 1.25ms) */
38#define SMP_MAX_CONN_INTERVAL 56 /* 70ms (56 * 1.25ms) */
39#define SMP_MAX_CONN_LATENCY 0 /* 0ms (0 * 1.25ms) */
40#define SMP_SUPERVISION_TIMEOUT 500 /* 5 seconds (500 * 10ms) */
41
Brian Gixa68668b2011-08-11 15:49:36 -070042#ifndef FALSE
43#define FALSE 0
44#define TRUE (!FALSE)
45#endif
46
47static int smp_distribute_keys(struct l2cap_conn *conn, __u8 force);
Vinicius Costa Gomes5d3de7d2011-06-14 13:37:41 -030048
Anderson Brigliad22ef0b2011-06-09 18:50:44 -030049static inline void swap128(u8 src[16], u8 dst[16])
50{
51 int i;
52 for (i = 0; i < 16; i++)
53 dst[15 - i] = src[i];
54}
55
56static inline void swap56(u8 src[7], u8 dst[7])
57{
58 int i;
59 for (i = 0; i < 7; i++)
60 dst[6 - i] = src[i];
61}
62
63static int smp_e(struct crypto_blkcipher *tfm, const u8 *k, u8 *r)
64{
65 struct blkcipher_desc desc;
66 struct scatterlist sg;
67 int err, iv_len;
68 unsigned char iv[128];
69
70 if (tfm == NULL) {
71 BT_ERR("tfm %p", tfm);
72 return -EINVAL;
73 }
74
75 desc.tfm = tfm;
76 desc.flags = 0;
77
78 err = crypto_blkcipher_setkey(tfm, k, 16);
79 if (err) {
80 BT_ERR("cipher setkey failed: %d", err);
81 return err;
82 }
83
84 sg_init_one(&sg, r, 16);
85
86 iv_len = crypto_blkcipher_ivsize(tfm);
87 if (iv_len) {
88 memset(&iv, 0xff, iv_len);
89 crypto_blkcipher_set_iv(tfm, iv, iv_len);
90 }
91
92 err = crypto_blkcipher_encrypt(&desc, &sg, &sg, 16);
93 if (err)
94 BT_ERR("Encrypt data error %d", err);
95
96 return err;
97}
98
99static int smp_c1(struct crypto_blkcipher *tfm, u8 k[16], u8 r[16],
100 u8 preq[7], u8 pres[7], u8 _iat, bdaddr_t *ia,
101 u8 _rat, bdaddr_t *ra, u8 res[16])
102{
103 u8 p1[16], p2[16];
104 int err;
105
106 memset(p1, 0, 16);
107
108 /* p1 = pres || preq || _rat || _iat */
109 swap56(pres, p1);
110 swap56(preq, p1 + 7);
111 p1[14] = _rat;
112 p1[15] = _iat;
113
114 memset(p2, 0, 16);
115
116 /* p2 = padding || ia || ra */
117 baswap((bdaddr_t *) (p2 + 4), ia);
118 baswap((bdaddr_t *) (p2 + 10), ra);
119
120 /* res = r XOR p1 */
121 u128_xor((u128 *) res, (u128 *) r, (u128 *) p1);
122
123 /* res = e(k, res) */
124 err = smp_e(tfm, k, res);
125 if (err) {
126 BT_ERR("Encrypt data error");
127 return err;
128 }
129
130 /* res = res XOR p2 */
131 u128_xor((u128 *) res, (u128 *) res, (u128 *) p2);
132
133 /* res = e(k, res) */
134 err = smp_e(tfm, k, res);
135 if (err)
136 BT_ERR("Encrypt data error");
137
138 return err;
139}
140
141static int smp_s1(struct crypto_blkcipher *tfm, u8 k[16],
142 u8 r1[16], u8 r2[16], u8 _r[16])
143{
144 int err;
145
146 /* Just least significant octets from r1 and r2 are considered */
147 memcpy(_r, r1 + 8, 8);
148 memcpy(_r + 8, r2 + 8, 8);
149
150 err = smp_e(tfm, k, _r);
151 if (err)
152 BT_ERR("Encrypt data error");
153
154 return err;
155}
156
157static int smp_rand(u8 *buf)
158{
159 get_random_bytes(buf, 16);
160
161 return 0;
162}
Anderson Brigliaeb492e02011-06-09 18:50:40 -0300163
164static struct sk_buff *smp_build_cmd(struct l2cap_conn *conn, u8 code,
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700165 u16 dlen, void *data)
Anderson Brigliaeb492e02011-06-09 18:50:40 -0300166{
167 struct sk_buff *skb;
168 struct l2cap_hdr *lh;
169 int len;
170
171 len = L2CAP_HDR_SIZE + sizeof(code) + dlen;
172
173 if (len > conn->mtu)
174 return NULL;
175
176 skb = bt_skb_alloc(len, GFP_ATOMIC);
177 if (!skb)
178 return NULL;
179
180 lh = (struct l2cap_hdr *) skb_put(skb, L2CAP_HDR_SIZE);
181 lh->len = cpu_to_le16(sizeof(code) + dlen);
182 lh->cid = cpu_to_le16(L2CAP_CID_SMP);
183
184 memcpy(skb_put(skb, sizeof(code)), &code, sizeof(code));
185
186 memcpy(skb_put(skb, dlen), data, dlen);
187
188 return skb;
189}
190
191static void smp_send_cmd(struct l2cap_conn *conn, u8 code, u16 len, void *data)
192{
193 struct sk_buff *skb = smp_build_cmd(conn, code, len, data);
194
195 BT_DBG("code 0x%2.2x", code);
196
197 if (!skb)
198 return;
199
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700200 hci_send_acl(conn->hcon, NULL, skb, 0);
Anderson Brigliaeb492e02011-06-09 18:50:40 -0300201}
202
Brian Gix2b64d152011-12-21 16:12:12 -0800203static __u8 authreq_to_seclevel(__u8 authreq)
204{
205 if (authreq & SMP_AUTH_MITM)
206 return BT_SECURITY_HIGH;
Brian Gixa68668b2011-08-11 15:49:36 -0700207 else if (authreq & SMP_AUTH_BONDING)
Brian Gix2b64d152011-12-21 16:12:12 -0800208 return BT_SECURITY_MEDIUM;
Brian Gixa68668b2011-08-11 15:49:36 -0700209 else
210 return BT_SECURITY_LOW;
Brian Gix2b64d152011-12-21 16:12:12 -0800211}
212
Vinicius Costa Gomes64532ec2011-06-09 18:50:53 -0300213static __u8 seclevel_to_authreq(__u8 level)
Brian Gix2b64d152011-12-21 16:12:12 -0800214{
Vinicius Costa Gomes64532ec2011-06-09 18:50:53 -0300215 switch (level) {
Brian Gix2b64d152011-12-21 16:12:12 -0800216 case BT_SECURITY_HIGH:
217 return SMP_AUTH_MITM | SMP_AUTH_BONDING;
Vinicius Costa Gomes64532ec2011-06-09 18:50:53 -0300218
Brian Gix2b64d152011-12-21 16:12:12 -0800219 default:
220 return SMP_AUTH_NONE;
221 }
222}
223
Vinicius Costa Gomesb8e66ea2011-06-09 18:50:52 -0300224static void build_pairing_cmd(struct l2cap_conn *conn,
Vinicius Costa Gomes54790f72011-07-07 18:59:38 -0300225 struct smp_cmd_pairing *req,
226 struct smp_cmd_pairing *rsp,
227 __u8 authreq)
Vinicius Costa Gomesb8e66ea2011-06-09 18:50:52 -0300228{
Brian Gixa68668b2011-08-11 15:49:36 -0700229 struct hci_conn *hcon = conn->hcon;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700230 u8 all_keys = 0;
Brian Gix2b64d152011-12-21 16:12:12 -0800231 u8 dist_keys = 0;
Vinicius Costa Gomes54790f72011-07-07 18:59:38 -0300232
Brian Gixa68668b2011-08-11 15:49:36 -0700233 dist_keys = SMP_DIST_ENC_KEY;
234 authreq |= SMP_AUTH_BONDING;
235
236 BT_DBG("conn->hcon->io_capability:%d", conn->hcon->io_capability);
Vinicius Costa Gomes54790f72011-07-07 18:59:38 -0300237
238 if (rsp == NULL) {
239 req->io_capability = conn->hcon->io_capability;
Brian Gixa68668b2011-08-11 15:49:36 -0700240 req->oob_flag = hcon->oob ? SMP_OOB_PRESENT :
241 SMP_OOB_NOT_PRESENT;
Vinicius Costa Gomes54790f72011-07-07 18:59:38 -0300242 req->max_key_size = SMP_MAX_ENC_KEY_SIZE;
Brian Gixa68668b2011-08-11 15:49:36 -0700243 req->init_key_dist = all_keys;
Vinicius Costa Gomes54790f72011-07-07 18:59:38 -0300244 req->resp_key_dist = dist_keys;
245 req->auth_req = authreq;
Brian Gixa68668b2011-08-11 15:49:36 -0700246 BT_DBG("SMP_CMD_PAIRING_REQ %d %d %d %d %2.2x %2.2x",
247 req->io_capability, req->oob_flag,
248 req->auth_req, req->max_key_size,
249 req->init_key_dist, req->resp_key_dist);
Vinicius Costa Gomes54790f72011-07-07 18:59:38 -0300250 return;
251 }
252
Brian Gixa68668b2011-08-11 15:49:36 -0700253 /* Only request OOB if remote AND we support it */
254 if (req->oob_flag)
255 rsp->oob_flag = hcon->oob ? SMP_OOB_PRESENT :
256 SMP_OOB_NOT_PRESENT;
257 else
258 rsp->oob_flag = SMP_OOB_NOT_PRESENT;
259
Vinicius Costa Gomes54790f72011-07-07 18:59:38 -0300260 rsp->io_capability = conn->hcon->io_capability;
Vinicius Costa Gomes54790f72011-07-07 18:59:38 -0300261 rsp->max_key_size = SMP_MAX_ENC_KEY_SIZE;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700262 rsp->init_key_dist = req->init_key_dist & all_keys;
Vinicius Costa Gomes54790f72011-07-07 18:59:38 -0300263 rsp->resp_key_dist = req->resp_key_dist & dist_keys;
264 rsp->auth_req = authreq;
Brian Gixa68668b2011-08-11 15:49:36 -0700265 BT_DBG("SMP_CMD_PAIRING_RSP %d %d %d %d %2.2x %2.2x",
266 req->io_capability, req->oob_flag, req->auth_req,
267 req->max_key_size, req->init_key_dist,
268 req->resp_key_dist);
Vinicius Costa Gomesb8e66ea2011-06-09 18:50:52 -0300269}
270
Vinicius Costa Gomes3158c502011-06-14 13:37:42 -0300271static u8 check_enc_key_size(struct l2cap_conn *conn, __u8 max_key_size)
272{
Brian Gixa68668b2011-08-11 15:49:36 -0700273 struct hci_conn *hcon = conn->hcon;
Vinicius Costa Gomes1c1def02011-09-05 14:31:30 -0300274
Vinicius Costa Gomes3158c502011-06-14 13:37:42 -0300275 if ((max_key_size > SMP_MAX_ENC_KEY_SIZE) ||
276 (max_key_size < SMP_MIN_ENC_KEY_SIZE))
277 return SMP_ENC_KEY_SIZE;
278
Brian Gixa68668b2011-08-11 15:49:36 -0700279 hcon->smp_key_size = max_key_size;
Vinicius Costa Gomes3158c502011-06-14 13:37:42 -0300280
281 return 0;
282}
283
Brian Gixa68668b2011-08-11 15:49:36 -0700284#define JUST_WORKS SMP_JUST_WORKS
285#define REQ_PASSKEY SMP_REQ_PASSKEY
286#define CFM_PASSKEY SMP_CFM_PASSKEY
287#define JUST_CFM SMP_JUST_CFM
288#define OVERLAP SMP_OVERLAP
289static const u8 gen_method[5][5] = {
290 {JUST_WORKS, JUST_CFM, REQ_PASSKEY, JUST_WORKS, REQ_PASSKEY},
291 {JUST_WORKS, JUST_CFM, REQ_PASSKEY, JUST_WORKS, REQ_PASSKEY},
292 {CFM_PASSKEY, CFM_PASSKEY, REQ_PASSKEY, JUST_WORKS, CFM_PASSKEY},
293 {JUST_WORKS, JUST_CFM, JUST_WORKS, JUST_WORKS, JUST_CFM},
294 {CFM_PASSKEY, CFM_PASSKEY, REQ_PASSKEY, JUST_WORKS, OVERLAP}
Brian Gix2b64d152011-12-21 16:12:12 -0800295};
296
297static int tk_request(struct l2cap_conn *conn, u8 remote_oob, u8 auth,
298 u8 local_io, u8 remote_io)
299{
300 struct hci_conn *hcon = conn->hcon;
Brian Gix2b64d152011-12-21 16:12:12 -0800301 u8 method;
302 u32 passkey = 0;
303 int ret = 0;
304
Brian Gixa68668b2011-08-11 15:49:36 -0700305 /* Initialize key to JUST WORKS */
306 memset(hcon->tk, 0, sizeof(hcon->tk));
307 hcon->tk_valid = FALSE;
308 hcon->auth = auth;
309
310 /* By definition, OOB data will be used if both sides have it available
311 */
312 if (remote_oob && hcon->oob) {
313 method = SMP_REQ_OOB;
314 goto agent_request;
315 }
Brian Gix2b64d152011-12-21 16:12:12 -0800316
317 BT_DBG("tk_request: auth:%d lcl:%d rem:%d", auth, local_io, remote_io);
318
319 /* If neither side wants MITM, use JUST WORKS */
Brian Gixa68668b2011-08-11 15:49:36 -0700320 /* If either side has unknown io_caps, use JUST_WORKS */
Brian Gix2b64d152011-12-21 16:12:12 -0800321 if (!(auth & SMP_AUTH_MITM) ||
322 local_io > SMP_IO_KEYBOARD_DISPLAY ||
Brian Gixa68668b2011-08-11 15:49:36 -0700323 remote_io > SMP_IO_KEYBOARD_DISPLAY) {
324 hcon->auth &= ~SMP_AUTH_MITM;
325 hcon->tk_valid = TRUE;
Brian Gix2b64d152011-12-21 16:12:12 -0800326 return 0;
327 }
328
Brian Gixa68668b2011-08-11 15:49:36 -0700329 /* MITM is now officially requested, but not required */
330 /* Determine what we need (if anything) from the agent */
331 method = gen_method[local_io][remote_io];
Brian Gix2b64d152011-12-21 16:12:12 -0800332
Brian Gixa68668b2011-08-11 15:49:36 -0700333 BT_DBG("tk_method: %d", method);
334
335 if (method == SMP_JUST_WORKS || method == SMP_JUST_CFM)
336 hcon->auth &= ~SMP_AUTH_MITM;
337
338 /* Don't bother confirming unbonded JUST_WORKS */
339 if (!(auth & SMP_AUTH_BONDING) && method == SMP_JUST_CFM) {
340 hcon->tk_valid = TRUE;
341 return 0;
342 } else if (method == SMP_JUST_WORKS) {
343 hcon->tk_valid = TRUE;
344 return 0;
345 } else if (method == SMP_OVERLAP) {
Brian Gix2b64d152011-12-21 16:12:12 -0800346 if (hcon->link_mode & HCI_LM_MASTER)
Brian Gixa68668b2011-08-11 15:49:36 -0700347 method = SMP_CFM_PASSKEY;
Brian Gix2b64d152011-12-21 16:12:12 -0800348 else
Brian Gixa68668b2011-08-11 15:49:36 -0700349 method = SMP_REQ_PASSKEY;
Brian Gix2b64d152011-12-21 16:12:12 -0800350 }
351
Brian Gixa68668b2011-08-11 15:49:36 -0700352 BT_DBG("tk_method-2: %d", method);
Brian Gix2b64d152011-12-21 16:12:12 -0800353
Brian Gixa68668b2011-08-11 15:49:36 -0700354 if (method == SMP_CFM_PASSKEY) {
355 u8 key[16];
356 /* Generate a passkey for display. It is not valid until
357 * confirmed.
358 */
Brian Gix2b64d152011-12-21 16:12:12 -0800359 memset(key, 0, sizeof(key));
360 get_random_bytes(&passkey, sizeof(passkey));
361 passkey %= 1000000;
362 put_unaligned_le32(passkey, key);
Brian Gixa68668b2011-08-11 15:49:36 -0700363 swap128(key, hcon->tk);
Brian Gix2b64d152011-12-21 16:12:12 -0800364 BT_DBG("PassKey: %d", passkey);
365 }
366
Brian Gixa68668b2011-08-11 15:49:36 -0700367agent_request:
Brian Gix2b64d152011-12-21 16:12:12 -0800368 hci_dev_lock(hcon->hdev);
369
Brian Gixa68668b2011-08-11 15:49:36 -0700370 switch (method) {
371 case SMP_REQ_PASSKEY:
Brian Gix3dd70172011-09-16 21:38:54 -0700372 ret = mgmt_user_confirm_request(hcon->hdev->id,
373 HCI_EV_USER_PASSKEY_REQUEST, conn->dst, 0);
374 break;
Brian Gixa68668b2011-08-11 15:49:36 -0700375 case SMP_CFM_PASSKEY:
376 default:
Brian Gix3dd70172011-09-16 21:38:54 -0700377 ret = mgmt_user_confirm_request(hcon->hdev->id,
378 HCI_EV_USER_CONFIRM_REQUEST, conn->dst, passkey);
379 break;
Brian Gixa68668b2011-08-11 15:49:36 -0700380 }
Brian Gix2b64d152011-12-21 16:12:12 -0800381
382 hci_dev_unlock(hcon->hdev);
383
384 return ret;
385}
386
Brian Gixa68668b2011-08-11 15:49:36 -0700387static int send_pairing_confirm(struct l2cap_conn *conn)
Vinicius Costa Gomes8aab4752011-09-05 14:31:31 -0300388{
Brian Gixa68668b2011-08-11 15:49:36 -0700389 struct hci_conn *hcon = conn->hcon;
390 struct crypto_blkcipher *tfm = hcon->hdev->tfm;
Vinicius Costa Gomes8aab4752011-09-05 14:31:31 -0300391 struct smp_cmd_pairing_confirm cp;
392 int ret;
Brian Gixa68668b2011-08-11 15:49:36 -0700393 u8 res[16];
Vinicius Costa Gomes8aab4752011-09-05 14:31:31 -0300394
395 if (conn->hcon->out)
Brian Gixa68668b2011-08-11 15:49:36 -0700396 ret = smp_c1(tfm, hcon->tk, hcon->prnd, hcon->preq, hcon->prsp,
397 0, conn->src, hcon->dst_type, conn->dst, res);
Vinicius Costa Gomes8aab4752011-09-05 14:31:31 -0300398 else
Brian Gixa68668b2011-08-11 15:49:36 -0700399 ret = smp_c1(tfm, hcon->tk, hcon->prnd, hcon->preq, hcon->prsp,
400 hcon->dst_type, conn->dst, 0, conn->src, res);
Vinicius Costa Gomes8aab4752011-09-05 14:31:31 -0300401
Brian Gixa68668b2011-08-11 15:49:36 -0700402 if (ret)
403 return SMP_CONFIRM_FAILED;
Brian Gix2b64d152011-12-21 16:12:12 -0800404
Vinicius Costa Gomes8aab4752011-09-05 14:31:31 -0300405 swap128(res, cp.confirm_val);
Vinicius Costa Gomes8aab4752011-09-05 14:31:31 -0300406
Brian Gixa68668b2011-08-11 15:49:36 -0700407 hcon->cfm_pending = FALSE;
Vinicius Costa Gomes8aab4752011-09-05 14:31:31 -0300408
Brian Gixa68668b2011-08-11 15:49:36 -0700409 smp_send_cmd(conn, SMP_CMD_PAIRING_CONFIRM, sizeof(cp), &cp);
Brian Gix2b64d152011-12-21 16:12:12 -0800410
411 return 0;
412}
413
Brian Gix6d5fb8a2011-09-09 14:53:04 -0700414int le_user_confirm_reply(struct hci_conn *hcon, u16 mgmt_op, void *cp)
Brian Gixa68668b2011-08-11 15:49:36 -0700415{
416 struct mgmt_cp_user_passkey_reply *psk_reply = cp;
Brian Gix6d5fb8a2011-09-09 14:53:04 -0700417 struct l2cap_conn *conn = hcon->smp_conn;
Brian Gixa68668b2011-08-11 15:49:36 -0700418 u8 key[16];
419 u8 reason = 0;
420 int ret = 0;
421
422 BT_DBG("");
423
Brian Gix6d5fb8a2011-09-09 14:53:04 -0700424 hcon->tk_valid = TRUE;
Brian Gixa68668b2011-08-11 15:49:36 -0700425
426 switch (mgmt_op) {
427 case MGMT_OP_USER_CONFIRM_NEG_REPLY:
428 reason = SMP_CONFIRM_FAILED;
429 break;
430 case MGMT_OP_USER_CONFIRM_REPLY:
431 break;
432 case MGMT_OP_USER_PASSKEY_REPLY:
433 memset(key, 0, sizeof(key));
434 BT_DBG("PassKey: %d", psk_reply->passkey);
435 put_unaligned_le32(psk_reply->passkey, key);
Brian Gix6d5fb8a2011-09-09 14:53:04 -0700436 swap128(key, hcon->tk);
Brian Gixa68668b2011-08-11 15:49:36 -0700437 break;
438 default:
439 reason = SMP_CONFIRM_FAILED;
440 ret = -EOPNOTSUPP;
441 break;
442 }
443
444 if (reason) {
445 BT_DBG("smp_send_cmd: SMP_CMD_PAIRING_FAIL");
446 smp_send_cmd(conn, SMP_CMD_PAIRING_FAIL, sizeof(reason),
447 &reason);
Brian Gixe9ceb522011-09-22 10:46:35 -0700448 del_timer(&hcon->smp_timer);
Archana Ramachandran0bb14f02012-11-14 11:00:48 -0800449 if (hcon->disconn_cfm_cb)
450 hcon->disconn_cfm_cb(hcon, SMP_UNSPECIFIED);
Brian Gix8d0b7d62011-10-12 15:12:42 -0700451 clear_bit(HCI_CONN_ENCRYPT_PEND, &hcon->pend);
Brian Gix58ba0772011-09-23 13:40:16 -0700452 mgmt_auth_failed(hcon->hdev->id, conn->dst, reason);
Brian Gix6d5fb8a2011-09-09 14:53:04 -0700453 hci_conn_put(hcon);
454 } else if (hcon->cfm_pending) {
Brian Gixa68668b2011-08-11 15:49:36 -0700455 BT_DBG("send_pairing_confirm");
456 ret = send_pairing_confirm(conn);
457 }
458
459 return ret;
460}
461
Vinicius Costa Gomesda85e5e2011-06-09 18:50:53 -0300462static u8 smp_cmd_pairing_req(struct l2cap_conn *conn, struct sk_buff *skb)
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300463{
Brian Gixa68668b2011-08-11 15:49:36 -0700464 struct hci_conn *hcon = conn->hcon;
Vinicius Costa Gomes3158c502011-06-14 13:37:42 -0300465 struct smp_cmd_pairing rsp, *req = (void *) skb->data;
466 u8 key_size;
Brian Gix2b64d152011-12-21 16:12:12 -0800467 u8 auth = SMP_AUTH_NONE;
Vinicius Costa Gomes8aab4752011-09-05 14:31:31 -0300468 int ret;
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300469
470 BT_DBG("conn %p", conn);
471
Brian Gixa68668b2011-08-11 15:49:36 -0700472 hcon->preq[0] = SMP_CMD_PAIRING_REQ;
473 memcpy(&hcon->preq[1], req, sizeof(*req));
Vinicius Costa Gomes3158c502011-06-14 13:37:42 -0300474 skb_pull(skb, sizeof(*req));
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300475
Brian Gixa68668b2011-08-11 15:49:36 -0700476 if (req->oob_flag && hcon->oob) {
477 /* By definition, OOB data pairing will have MITM protection */
478 auth = req->auth_req | SMP_AUTH_MITM;
479 } else if (req->auth_req & SMP_AUTH_BONDING) {
480 /* We will attempt MITM for all Bonding attempts */
481 auth = SMP_AUTH_BONDING | SMP_AUTH_MITM;
482 }
Vinicius Costa Gomesda85e5e2011-06-09 18:50:53 -0300483
Vinicius Costa Gomes64532ec2011-06-09 18:50:53 -0300484 /* We didn't start the pairing, so no requirements */
Brian Gix2b64d152011-12-21 16:12:12 -0800485 build_pairing_cmd(conn, req, &rsp, auth);
Vinicius Costa Gomes3158c502011-06-14 13:37:42 -0300486
487 key_size = min(req->max_key_size, rsp.max_key_size);
488 if (check_enc_key_size(conn, key_size))
489 return SMP_ENC_KEY_SIZE;
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300490
Brian Gixa68668b2011-08-11 15:49:36 -0700491 ret = smp_rand(hcon->prnd);
Vinicius Costa Gomes8aab4752011-09-05 14:31:31 -0300492 if (ret)
493 return SMP_UNSPECIFIED;
494
Brian Gixa68668b2011-08-11 15:49:36 -0700495 /* Request setup of TK */
496 ret = tk_request(conn, req->oob_flag, auth, rsp.io_capability,
497 req->io_capability);
498 if (ret)
499 return SMP_UNSPECIFIED;
500
501 hcon->prsp[0] = SMP_CMD_PAIRING_RSP;
502 memcpy(&hcon->prsp[1], &rsp, sizeof(rsp));
Anderson Brigliaf01ead32011-06-09 18:50:45 -0300503
Vinicius Costa Gomes3158c502011-06-14 13:37:42 -0300504 smp_send_cmd(conn, SMP_CMD_PAIRING_RSP, sizeof(rsp), &rsp);
Vinicius Costa Gomesda85e5e2011-06-09 18:50:53 -0300505
Brian Gixe9ceb522011-09-22 10:46:35 -0700506 mod_timer(&hcon->smp_timer, jiffies + msecs_to_jiffies(SMP_TIMEOUT));
Brian Gix2b64d152011-12-21 16:12:12 -0800507
Vinicius Costa Gomesda85e5e2011-06-09 18:50:53 -0300508 return 0;
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300509}
510
Vinicius Costa Gomesda85e5e2011-06-09 18:50:53 -0300511static u8 smp_cmd_pairing_rsp(struct l2cap_conn *conn, struct sk_buff *skb)
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300512{
Brian Gixa68668b2011-08-11 15:49:36 -0700513 struct hci_conn *hcon = conn->hcon;
Vinicius Costa Gomes3158c502011-06-14 13:37:42 -0300514 struct smp_cmd_pairing *req, *rsp = (void *) skb->data;
Brian Gix2b64d152011-12-21 16:12:12 -0800515 u8 key_size, auth = SMP_AUTH_NONE;
Anderson Briglia7d24ddc2011-06-09 18:50:46 -0300516 int ret;
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300517
518 BT_DBG("conn %p", conn);
519
Vinicius Costa Gomes3158c502011-06-14 13:37:42 -0300520 skb_pull(skb, sizeof(*rsp));
Vinicius Costa Gomesda85e5e2011-06-09 18:50:53 -0300521
Brian Gixa68668b2011-08-11 15:49:36 -0700522 req = (void *) &hcon->preq[1];
Vinicius Costa Gomes3158c502011-06-14 13:37:42 -0300523
524 key_size = min(req->max_key_size, rsp->max_key_size);
525 if (check_enc_key_size(conn, key_size))
526 return SMP_ENC_KEY_SIZE;
527
Brian Gixa68668b2011-08-11 15:49:36 -0700528 hcon->prsp[0] = SMP_CMD_PAIRING_RSP;
529 memcpy(&hcon->prsp[1], rsp, sizeof(*rsp));
Vinicius Costa Gomes64532ec2011-06-09 18:50:53 -0300530
Brian Gixa68668b2011-08-11 15:49:36 -0700531 ret = smp_rand(hcon->prnd);
Anderson Briglia7d24ddc2011-06-09 18:50:46 -0300532 if (ret)
Vinicius Costa Gomesda85e5e2011-06-09 18:50:53 -0300533 return SMP_UNSPECIFIED;
Anderson Briglia7d24ddc2011-06-09 18:50:46 -0300534
Brian Gix2b64d152011-12-21 16:12:12 -0800535 if ((req->auth_req & SMP_AUTH_BONDING) &&
536 (rsp->auth_req & SMP_AUTH_BONDING))
537 auth = SMP_AUTH_BONDING;
538
539 auth |= (req->auth_req | rsp->auth_req) & SMP_AUTH_MITM;
540
Brian Gixa68668b2011-08-11 15:49:36 -0700541 ret = tk_request(conn, req->oob_flag, auth, rsp->io_capability,
542 req->io_capability);
Brian Gix2b64d152011-12-21 16:12:12 -0800543 if (ret)
544 return SMP_UNSPECIFIED;
545
Brian Gixa68668b2011-08-11 15:49:36 -0700546 hcon->cfm_pending = TRUE;
Brian Gix2b64d152011-12-21 16:12:12 -0800547
548 /* Can't compose response until we have been confirmed */
Brian Gixa68668b2011-08-11 15:49:36 -0700549 if (!hcon->tk_valid)
Brian Gix2b64d152011-12-21 16:12:12 -0800550 return 0;
551
Brian Gixa68668b2011-08-11 15:49:36 -0700552 ret = send_pairing_confirm(conn);
553 if (ret)
554 return SMP_CONFIRM_FAILED;
Vinicius Costa Gomesda85e5e2011-06-09 18:50:53 -0300555
556 return 0;
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300557}
558
Vinicius Costa Gomesda85e5e2011-06-09 18:50:53 -0300559static u8 smp_cmd_pairing_confirm(struct l2cap_conn *conn, struct sk_buff *skb)
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300560{
Brian Gixa68668b2011-08-11 15:49:36 -0700561 struct hci_conn *hcon = conn->hcon;
562 int ret;
Anderson Briglia7d24ddc2011-06-09 18:50:46 -0300563
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300564 BT_DBG("conn %p %s", conn, conn->hcon->out ? "master" : "slave");
565
Brian Gixa68668b2011-08-11 15:49:36 -0700566 memcpy(hcon->pcnf, skb->data, sizeof(hcon->pcnf));
567 skb_pull(skb, sizeof(hcon->pcnf));
Anderson Briglia7d24ddc2011-06-09 18:50:46 -0300568
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300569 if (conn->hcon->out) {
Anderson Briglia7d24ddc2011-06-09 18:50:46 -0300570 u8 random[16];
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300571
Brian Gixa68668b2011-08-11 15:49:36 -0700572 swap128(hcon->prnd, random);
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300573 smp_send_cmd(conn, SMP_CMD_PAIRING_RANDOM, sizeof(random),
Anderson Briglia7d24ddc2011-06-09 18:50:46 -0300574 random);
Brian Gixa68668b2011-08-11 15:49:36 -0700575 } else if (hcon->tk_valid) {
576 ret = send_pairing_confirm(conn);
Anderson Briglia13b48392011-06-09 18:50:42 -0300577
Anderson Briglia21b8a2b2011-06-09 18:50:46 -0300578 if (ret)
Vinicius Costa Gomes64532ec2011-06-09 18:50:53 -0300579 return SMP_CONFIRM_FAILED;
Brian Gixa68668b2011-08-11 15:49:36 -0700580 } else
581 hcon->cfm_pending = TRUE;
Anderson Briglia21b8a2b2011-06-09 18:50:46 -0300582
Vinicius Costa Gomes64532ec2011-06-09 18:50:53 -0300583
Brian Gixe9ceb522011-09-22 10:46:35 -0700584 mod_timer(&hcon->smp_timer, jiffies + msecs_to_jiffies(SMP_TIMEOUT));
Vinicius Costa Gomesda85e5e2011-06-09 18:50:53 -0300585
586 return 0;
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300587}
588
Vinicius Costa Gomesda85e5e2011-06-09 18:50:53 -0300589static u8 smp_cmd_pairing_random(struct l2cap_conn *conn, struct sk_buff *skb)
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300590{
Vinicius Costa Gomes735038c2011-06-09 18:50:47 -0300591 struct hci_conn *hcon = conn->hcon;
592 struct crypto_blkcipher *tfm = hcon->hdev->tfm;
Anderson Briglia21b8a2b2011-06-09 18:50:46 -0300593 int ret;
Vinicius Costa Gomesc34e25e2011-06-09 18:50:48 -0300594 u8 key[16], res[16], random[16], confirm[16];
Anderson Briglia7d24ddc2011-06-09 18:50:46 -0300595
Anderson Briglia21b8a2b2011-06-09 18:50:46 -0300596 swap128(skb->data, random);
597 skb_pull(skb, sizeof(random));
Anderson Briglia7d24ddc2011-06-09 18:50:46 -0300598
Anderson Briglia21b8a2b2011-06-09 18:50:46 -0300599 if (conn->hcon->out)
Brian Gixa68668b2011-08-11 15:49:36 -0700600 ret = smp_c1(tfm, hcon->tk, random, hcon->preq, hcon->prsp, 0,
601 conn->src, hcon->dst_type, conn->dst,
Anderson Briglia21b8a2b2011-06-09 18:50:46 -0300602 res);
603 else
Brian Gixa68668b2011-08-11 15:49:36 -0700604 ret = smp_c1(tfm, hcon->tk, random, hcon->preq, hcon->prsp,
605 hcon->dst_type, conn->dst, 0, conn->src,
Anderson Briglia21b8a2b2011-06-09 18:50:46 -0300606 res);
607 if (ret)
Vinicius Costa Gomes64532ec2011-06-09 18:50:53 -0300608 return SMP_UNSPECIFIED;
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300609
Anderson Briglia13b48392011-06-09 18:50:42 -0300610 BT_DBG("conn %p %s", conn, conn->hcon->out ? "master" : "slave");
611
Anderson Briglia21b8a2b2011-06-09 18:50:46 -0300612 swap128(res, confirm);
613
Brian Gixa68668b2011-08-11 15:49:36 -0700614 if (memcmp(hcon->pcnf, confirm, sizeof(hcon->pcnf)) != 0) {
Anderson Briglia21b8a2b2011-06-09 18:50:46 -0300615 BT_ERR("Pairing failed (confirmation values mismatch)");
Vinicius Costa Gomes64532ec2011-06-09 18:50:53 -0300616 return SMP_CONFIRM_FAILED;
Anderson Briglia21b8a2b2011-06-09 18:50:46 -0300617 }
Anderson Briglia13b48392011-06-09 18:50:42 -0300618
619 if (conn->hcon->out) {
Vinicius Costa Gomesf1b45c52011-07-07 18:59:40 -0300620 u8 stk[16], rand[8];
Vinicius Costa Gomes735038c2011-06-09 18:50:47 -0300621 __le16 ediv;
Vinicius Costa Gomes397d9ae2011-06-14 13:37:42 -0300622
Vinicius Costa Gomes735038c2011-06-09 18:50:47 -0300623 memset(rand, 0, sizeof(rand));
624 ediv = 0;
Vinicius Costa Gomesf1b45c52011-07-07 18:59:40 -0300625
Brian Gixa68668b2011-08-11 15:49:36 -0700626 smp_s1(tfm, hcon->tk, random, hcon->prnd, key);
Vinicius Costa Gomesf1b45c52011-07-07 18:59:40 -0300627 swap128(key, stk);
628
Brian Gixa68668b2011-08-11 15:49:36 -0700629 memset(stk + hcon->smp_key_size, 0,
630 SMP_MAX_ENC_KEY_SIZE - hcon->smp_key_size);
Vinicius Costa Gomesf1b45c52011-07-07 18:59:40 -0300631
632 hci_le_start_enc(hcon, ediv, rand, stk);
Brian Gixa68668b2011-08-11 15:49:36 -0700633 hcon->enc_key_size = hcon->smp_key_size;
Anderson Briglia21b8a2b2011-06-09 18:50:46 -0300634 } else {
Vinicius Costa Gomesf1b45c52011-07-07 18:59:40 -0300635 u8 stk[16], r[16], rand[8];
636 __le16 ediv;
637
638 memset(rand, 0, sizeof(rand));
639 ediv = 0;
Anderson Briglia21b8a2b2011-06-09 18:50:46 -0300640
Brian Gixa68668b2011-08-11 15:49:36 -0700641 swap128(hcon->prnd, r);
Anderson Briglia21b8a2b2011-06-09 18:50:46 -0300642 smp_send_cmd(conn, SMP_CMD_PAIRING_RANDOM, sizeof(r), r);
643
Brian Gixa68668b2011-08-11 15:49:36 -0700644 smp_s1(tfm, hcon->tk, hcon->prnd, random, key);
Vinicius Costa Gomesf1b45c52011-07-07 18:59:40 -0300645 swap128(key, stk);
Vinicius Costa Gomes397d9ae2011-06-14 13:37:42 -0300646
Brian Gixa68668b2011-08-11 15:49:36 -0700647 memset(stk + hcon->smp_key_size, 0,
648 SMP_MAX_ENC_KEY_SIZE - hcon->smp_key_size);
Vinicius Costa Gomesf1b45c52011-07-07 18:59:40 -0300649
Brian Gixcf956772011-10-20 15:18:51 -0700650 hci_add_ltk(conn->hcon->hdev, 0, conn->dst, hcon->dst_type,
651 hcon->smp_key_size, hcon->auth, ediv, rand, stk);
Anderson Briglia13b48392011-06-09 18:50:42 -0300652 }
Vinicius Costa Gomesda85e5e2011-06-09 18:50:53 -0300653
654 return 0;
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300655}
656
Brian Gix372257b2011-10-25 09:06:30 -0700657static int smp_encrypt_link(struct hci_conn *hcon, struct link_key *key)
Vinicius Costa Gomes988c5992011-08-25 20:02:28 -0300658{
Brian Gix372257b2011-10-25 09:06:30 -0700659 struct key_master_id *master;
Brian Gix80fb3a92012-01-31 13:15:20 -0800660 u8 sec_level;
Brian Gix372257b2011-10-25 09:06:30 -0700661 u8 zerobuf[8];
Vinicius Costa Gomes988c5992011-08-25 20:02:28 -0300662
Brian Gix372257b2011-10-25 09:06:30 -0700663 if (!hcon || !key || !key->data)
664 return -EINVAL;
Vinicius Costa Gomes988c5992011-08-25 20:02:28 -0300665
Brian Gix372257b2011-10-25 09:06:30 -0700666 memset(zerobuf, 0, sizeof(zerobuf));
Vinicius Costa Gomes988c5992011-08-25 20:02:28 -0300667
Brian Gix372257b2011-10-25 09:06:30 -0700668 master = (void *) key->data;
Vinicius Costa Gomes988c5992011-08-25 20:02:28 -0300669
Brian Gix372257b2011-10-25 09:06:30 -0700670 if (!master->ediv && !memcmp(master->rand, zerobuf, sizeof(zerobuf)))
671 return -EINVAL;
Vinicius Costa Gomes988c5992011-08-25 20:02:28 -0300672
Brian Gix372257b2011-10-25 09:06:30 -0700673 hcon->enc_key_size = key->pin_len;
674 hcon->sec_req = TRUE;
Brian Gix80fb3a92012-01-31 13:15:20 -0800675 sec_level = authreq_to_seclevel(key->auth);
676
677 BT_DBG("cur %d, req: %d", hcon->sec_level, sec_level);
678
679 if (sec_level > hcon->sec_level)
680 hcon->pending_sec_level = sec_level;
681
682
683 if (!(hcon->link_mode & HCI_LM_ENCRYPT))
684 hci_conn_hold(hcon);
685
Brian Gix372257b2011-10-25 09:06:30 -0700686 hci_le_start_enc(hcon, master->ediv, master->rand, key->val);
687
688 return 0;
Vinicius Costa Gomes988c5992011-08-25 20:02:28 -0300689}
Brian Gix372257b2011-10-25 09:06:30 -0700690
Vinicius Costa Gomesda85e5e2011-06-09 18:50:53 -0300691static u8 smp_cmd_security_req(struct l2cap_conn *conn, struct sk_buff *skb)
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300692{
Brian Gixa68668b2011-08-11 15:49:36 -0700693 struct hci_conn *hcon = conn->hcon;
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300694 struct smp_cmd_security_req *rp = (void *) skb->data;
695 struct smp_cmd_pairing cp;
Brian Gixa68668b2011-08-11 15:49:36 -0700696 struct link_key *key;
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300697
698 BT_DBG("conn %p", conn);
699
Vinicius Costa Gomesa5474a82011-01-26 21:42:57 -0300700 if (test_bit(HCI_CONN_ENCRYPT_PEND, &hcon->pend))
Vinicius Costa Gomes988c5992011-08-25 20:02:28 -0300701 return 0;
702
Brian Gixa68668b2011-08-11 15:49:36 -0700703 key = hci_find_link_key_type(hcon->hdev, conn->dst, KEY_TYPE_LTK);
704 if (key && ((key->auth & SMP_AUTH_MITM) ||
705 !(rp->auth_req & SMP_AUTH_MITM))) {
Vinicius Costa Gomesf1cb9af2011-01-26 21:42:57 -0300706
Brian Gix372257b2011-10-25 09:06:30 -0700707 if (smp_encrypt_link(hcon, key) < 0)
708 goto invalid_key;
Brian Gixa68668b2011-08-11 15:49:36 -0700709
Brian Gixa68668b2011-08-11 15:49:36 -0700710 return 0;
711 }
712
Brian Gix372257b2011-10-25 09:06:30 -0700713invalid_key:
Brian Gixa68668b2011-08-11 15:49:36 -0700714 hcon->sec_req = FALSE;
715
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300716 skb_pull(skb, sizeof(*rp));
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300717
Vinicius Costa Gomesda85e5e2011-06-09 18:50:53 -0300718 memset(&cp, 0, sizeof(cp));
Vinicius Costa Gomes54790f72011-07-07 18:59:38 -0300719 build_pairing_cmd(conn, &cp, NULL, rp->auth_req);
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300720
Brian Gix27a795c2012-04-19 11:05:06 -0700721 hcon->pending_sec_level = authreq_to_seclevel(rp->auth_req);
Brian Gixa68668b2011-08-11 15:49:36 -0700722 hcon->preq[0] = SMP_CMD_PAIRING_REQ;
723 memcpy(&hcon->preq[1], &cp, sizeof(cp));
Anderson Brigliaf01ead32011-06-09 18:50:45 -0300724
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300725 smp_send_cmd(conn, SMP_CMD_PAIRING_REQ, sizeof(cp), &cp);
Vinicius Costa Gomesf1cb9af2011-01-26 21:42:57 -0300726
Brian Gixe9ceb522011-09-22 10:46:35 -0700727 mod_timer(&hcon->smp_timer, jiffies + msecs_to_jiffies(SMP_TIMEOUT));
Vinicius Costa Gomesb19d5ce2011-06-14 13:37:41 -0300728
Vinicius Costa Gomesa5474a82011-01-26 21:42:57 -0300729 set_bit(HCI_CONN_ENCRYPT_PEND, &hcon->pend);
Vinicius Costa Gomesa5474a82011-01-26 21:42:57 -0300730
Brian Gix8d0b7d62011-10-12 15:12:42 -0700731 hci_conn_hold(hcon);
732
Vinicius Costa Gomesda85e5e2011-06-09 18:50:53 -0300733 return 0;
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300734}
735
Anderson Brigliaeb492e02011-06-09 18:50:40 -0300736int smp_conn_security(struct l2cap_conn *conn, __u8 sec_level)
737{
Vinicius Costa Gomes3a0259b2011-06-09 18:50:43 -0300738 struct hci_conn *hcon = conn->hcon;
Brian Gix2b64d152011-12-21 16:12:12 -0800739 __u8 authreq;
Anderson Brigliaeb492e02011-06-09 18:50:40 -0300740
Brian Gix80fb3a92012-01-31 13:15:20 -0800741 BT_DBG("conn %p hcon %p %d req: %d",
742 conn, hcon, hcon->sec_level, sec_level);
Vinicius Costa Gomes3a0259b2011-06-09 18:50:43 -0300743
Brian Gix80fb3a92012-01-31 13:15:20 -0800744 if (IS_ERR(hcon->hdev->tfm))
Andre Guedes2e65c9d2011-06-30 19:20:56 -0300745 return 1;
746
Brian Gix80fb3a92012-01-31 13:15:20 -0800747 if (test_bit(HCI_CONN_ENCRYPT_PEND, &hcon->pend))
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700748 return -EINPROGRESS;
Anderson Briglia133e14c2011-06-09 18:50:40 -0300749
Vinicius Costa Gomesf1cb9af2011-01-26 21:42:57 -0300750 if (sec_level == BT_SECURITY_LOW)
Anderson Brigliaeb492e02011-06-09 18:50:40 -0300751 return 1;
Vinicius Costa Gomesf1cb9af2011-01-26 21:42:57 -0300752
Brian Gix80fb3a92012-01-31 13:15:20 -0800753
Vinicius Costa Gomesf1cb9af2011-01-26 21:42:57 -0300754 if (hcon->sec_level >= sec_level)
755 return 1;
756
Brian Gix2b64d152011-12-21 16:12:12 -0800757 authreq = seclevel_to_authreq(sec_level);
Vinicius Costa Gomesd26a2342011-08-19 21:06:51 -0300758
Brian Gixa68668b2011-08-11 15:49:36 -0700759 hcon->smp_conn = conn;
Brian Gix80fb3a92012-01-31 13:15:20 -0800760 hcon->pending_sec_level = sec_level;
Subramanian Srinivasan3e7c75d2012-10-08 17:22:43 -0700761 if (hcon->link_mode & HCI_LM_MASTER) {
Vinicius Costa Gomes5d873ca2011-07-07 18:59:41 -0300762 struct link_key *key;
763
764 key = hci_find_link_key_type(hcon->hdev, conn->dst,
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700765 KEY_TYPE_LTK);
Vinicius Costa Gomes5d873ca2011-07-07 18:59:41 -0300766
Brian Gix372257b2011-10-25 09:06:30 -0700767 if (smp_encrypt_link(hcon, key) == 0)
Vinicius Costa Gomes5d873ca2011-07-07 18:59:41 -0300768 goto done;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700769 }
770
Brian Gixa68668b2011-08-11 15:49:36 -0700771 hcon->sec_req = FALSE;
772
Vinicius Costa Gomesd26a2342011-08-19 21:06:51 -0300773 if (hcon->link_mode & HCI_LM_MASTER) {
774 struct smp_cmd_pairing cp;
Anderson Brigliaf01ead32011-06-09 18:50:45 -0300775
Brian Gix2b64d152011-12-21 16:12:12 -0800776 build_pairing_cmd(conn, &cp, NULL, authreq);
Brian Gixa68668b2011-08-11 15:49:36 -0700777 hcon->preq[0] = SMP_CMD_PAIRING_REQ;
778 memcpy(&hcon->preq[1], &cp, sizeof(cp));
Anderson Brigliac8e856e2011-06-09 18:50:45 -0300779
Brian Gixe9ceb522011-09-22 10:46:35 -0700780 mod_timer(&hcon->smp_timer, jiffies +
Vinicius Costa Gomesb19d5ce2011-06-14 13:37:41 -0300781 msecs_to_jiffies(SMP_TIMEOUT));
Anderson Brigliaf01ead32011-06-09 18:50:45 -0300782
Anderson Brigliaeb492e02011-06-09 18:50:40 -0300783 smp_send_cmd(conn, SMP_CMD_PAIRING_REQ, sizeof(cp), &cp);
Brian Gix80fb3a92012-01-31 13:15:20 -0800784 hci_conn_hold(hcon);
Anderson Brigliaeb492e02011-06-09 18:50:40 -0300785 } else {
786 struct smp_cmd_security_req cp;
Brian Gix2b64d152011-12-21 16:12:12 -0800787 cp.auth_req = authreq;
Anderson Brigliaeb492e02011-06-09 18:50:40 -0300788 smp_send_cmd(conn, SMP_CMD_SECURITY_REQ, sizeof(cp), &cp);
789 }
790
Vinicius Costa Gomes02bc7452011-07-07 18:59:41 -0300791done:
Vinicius Costa Gomesa5474a82011-01-26 21:42:57 -0300792 set_bit(HCI_CONN_ENCRYPT_PEND, &hcon->pend);
Vinicius Costa Gomesf1cb9af2011-01-26 21:42:57 -0300793
Anderson Brigliaeb492e02011-06-09 18:50:40 -0300794 return 0;
795}
796
Vinicius Costa Gomes7034b912011-07-07 18:59:34 -0300797static int smp_cmd_encrypt_info(struct l2cap_conn *conn, struct sk_buff *skb)
798{
Brian Gixa68668b2011-08-11 15:49:36 -0700799 struct hci_conn *hcon = conn->hcon;
Vinicius Costa Gomes16b90832011-07-07 18:59:39 -0300800 struct smp_cmd_encrypt_info *rp = (void *) skb->data;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700801 u8 rand[8];
802 int err;
Vinicius Costa Gomes16b90832011-07-07 18:59:39 -0300803
804 skb_pull(skb, sizeof(*rp));
805
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700806 BT_DBG("conn %p", conn);
807
808 memset(rand, 0, sizeof(rand));
809
Brian Gixcf956772011-10-20 15:18:51 -0700810 err = hci_add_ltk(hcon->hdev, 0, conn->dst, hcon->dst_type,
811 0, 0, 0, rand, rp->ltk);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700812 if (err)
813 return SMP_UNSPECIFIED;
Vinicius Costa Gomes16b90832011-07-07 18:59:39 -0300814
Vinicius Costa Gomes7034b912011-07-07 18:59:34 -0300815 return 0;
816}
817
818static int smp_cmd_master_ident(struct l2cap_conn *conn, struct sk_buff *skb)
819{
Vinicius Costa Gomesc9839a12012-02-02 21:08:01 -0300820 struct hci_conn *hcon = conn->hcon;
Vinicius Costa Gomese56cede2011-07-07 18:59:39 -0300821 struct smp_cmd_master_ident *rp = (void *) skb->data;
Brian Gixa68668b2011-08-11 15:49:36 -0700822 struct smp_cmd_pairing *paircmd = (void *) &hcon->prsp[1];
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700823 struct link_key *key;
Brian Gixa68668b2011-08-11 15:49:36 -0700824 u8 *keydist;
Vinicius Costa Gomes7034b912011-07-07 18:59:34 -0300825
Vinicius Costa Gomes16b90832011-07-07 18:59:39 -0300826 skb_pull(skb, sizeof(*rp));
827
Brian Gixa68668b2011-08-11 15:49:36 -0700828 key = hci_find_link_key_type(hcon->hdev, conn->dst, KEY_TYPE_LTK);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700829 if (key == NULL)
830 return SMP_UNSPECIFIED;
831
Brian Gixa68668b2011-08-11 15:49:36 -0700832 if (hcon->out)
833 keydist = &paircmd->resp_key_dist;
834 else
835 keydist = &paircmd->init_key_dist;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700836
Brian Gixa68668b2011-08-11 15:49:36 -0700837 BT_DBG("keydist 0x%x", *keydist);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700838
Brian Gixcf956772011-10-20 15:18:51 -0700839 hci_add_ltk(hcon->hdev, 1, conn->dst, hcon->dst_type,
840 hcon->smp_key_size, hcon->auth, rp->ediv,
841 rp->rand, key->val);
Vinicius Costa Gomesc1d5e1d2011-07-07 18:59:34 -0300842
Brian Gixa68668b2011-08-11 15:49:36 -0700843 *keydist &= ~SMP_DIST_ENC_KEY;
844 if (hcon->out) {
845 if (!(*keydist))
846 smp_distribute_keys(conn, 1);
847 }
Vinicius Costa Gomes7034b912011-07-07 18:59:34 -0300848
849 return 0;
850}
851
Anderson Brigliaeb492e02011-06-09 18:50:40 -0300852int smp_sig_channel(struct l2cap_conn *conn, struct sk_buff *skb)
853{
Brian Gixa68668b2011-08-11 15:49:36 -0700854 struct hci_conn *hcon = conn->hcon;
Anderson Brigliaeb492e02011-06-09 18:50:40 -0300855 __u8 code = skb->data[0];
856 __u8 reason;
857 int err = 0;
858
Brian Gixa68668b2011-08-11 15:49:36 -0700859 if (IS_ERR(hcon->hdev->tfm)) {
860 err = PTR_ERR(hcon->hdev->tfm);
Andre Guedes2e65c9d2011-06-30 19:20:56 -0300861 reason = SMP_PAIRING_NOTSUPP;
Brian Gixa68668b2011-08-11 15:49:36 -0700862 BT_ERR("SMP_PAIRING_NOTSUPP %p", hcon->hdev->tfm);
Andre Guedes2e65c9d2011-06-30 19:20:56 -0300863 goto done;
864 }
865
Brian Gixa68668b2011-08-11 15:49:36 -0700866 hcon->smp_conn = conn;
Anderson Brigliaeb492e02011-06-09 18:50:40 -0300867 skb_pull(skb, sizeof(code));
868
869 switch (code) {
870 case SMP_CMD_PAIRING_REQ:
Vinicius Costa Gomesda85e5e2011-06-09 18:50:53 -0300871 reason = smp_cmd_pairing_req(conn, skb);
Anderson Brigliaeb492e02011-06-09 18:50:40 -0300872 break;
873
874 case SMP_CMD_PAIRING_FAIL:
Vinicius Costa Gomesda85e5e2011-06-09 18:50:53 -0300875 reason = 0;
876 err = -EPERM;
Brian Gixe9ceb522011-09-22 10:46:35 -0700877 del_timer(&hcon->smp_timer);
Brian Gix8d0b7d62011-10-12 15:12:42 -0700878 clear_bit(HCI_CONN_ENCRYPT_PEND, &hcon->pend);
Brian Gix570efc92011-10-13 15:59:51 -0700879 mgmt_auth_failed(hcon->hdev->id, conn->dst, skb->data[0]);
Brian Gix6d5fb8a2011-09-09 14:53:04 -0700880 hci_conn_put(hcon);
Anderson Brigliaeb492e02011-06-09 18:50:40 -0300881 break;
882
883 case SMP_CMD_PAIRING_RSP:
Vinicius Costa Gomesda85e5e2011-06-09 18:50:53 -0300884 reason = smp_cmd_pairing_rsp(conn, skb);
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300885 break;
886
887 case SMP_CMD_SECURITY_REQ:
Vinicius Costa Gomesda85e5e2011-06-09 18:50:53 -0300888 reason = smp_cmd_security_req(conn, skb);
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300889 break;
890
Anderson Brigliaeb492e02011-06-09 18:50:40 -0300891 case SMP_CMD_PAIRING_CONFIRM:
Vinicius Costa Gomesda85e5e2011-06-09 18:50:53 -0300892 reason = smp_cmd_pairing_confirm(conn, skb);
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300893 break;
894
Anderson Brigliaeb492e02011-06-09 18:50:40 -0300895 case SMP_CMD_PAIRING_RANDOM:
Vinicius Costa Gomesda85e5e2011-06-09 18:50:53 -0300896 reason = smp_cmd_pairing_random(conn, skb);
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300897 break;
898
Anderson Brigliaeb492e02011-06-09 18:50:40 -0300899 case SMP_CMD_ENCRYPT_INFO:
Vinicius Costa Gomes7034b912011-07-07 18:59:34 -0300900 reason = smp_cmd_encrypt_info(conn, skb);
901 break;
902
Anderson Brigliaeb492e02011-06-09 18:50:40 -0300903 case SMP_CMD_MASTER_IDENT:
Vinicius Costa Gomes7034b912011-07-07 18:59:34 -0300904 reason = smp_cmd_master_ident(conn, skb);
905 break;
906
Anderson Brigliaeb492e02011-06-09 18:50:40 -0300907 case SMP_CMD_IDENT_INFO:
908 case SMP_CMD_IDENT_ADDR_INFO:
909 case SMP_CMD_SIGN_INFO:
Vinicius Costa Gomes7034b912011-07-07 18:59:34 -0300910 /* Just ignored */
911 reason = 0;
912 break;
913
Anderson Brigliaeb492e02011-06-09 18:50:40 -0300914 default:
915 BT_DBG("Unknown command code 0x%2.2x", code);
916
917 reason = SMP_CMD_NOTSUPP;
Vinicius Costa Gomes3a0259b2011-06-09 18:50:43 -0300918 err = -EOPNOTSUPP;
919 goto done;
920 }
921
922done:
Brian Gixa68668b2011-08-11 15:49:36 -0700923 if (reason) {
924 BT_ERR("SMP_CMD_PAIRING_FAIL: %d", reason);
Anderson Briglia133e14c2011-06-09 18:50:40 -0300925 smp_send_cmd(conn, SMP_CMD_PAIRING_FAIL, sizeof(reason),
926 &reason);
Brian Gixe9ceb522011-09-22 10:46:35 -0700927 del_timer(&hcon->smp_timer);
Brian Gix8d0b7d62011-10-12 15:12:42 -0700928 clear_bit(HCI_CONN_ENCRYPT_PEND, &hcon->pend);
Brian Gix58ba0772011-09-23 13:40:16 -0700929 mgmt_auth_failed(hcon->hdev->id, conn->dst, reason);
Brian Gix6d5fb8a2011-09-09 14:53:04 -0700930 hci_conn_put(hcon);
Brian Gixa68668b2011-08-11 15:49:36 -0700931 }
Anderson Brigliaeb492e02011-06-09 18:50:40 -0300932
933 kfree_skb(skb);
934 return err;
935}
Vinicius Costa Gomes7034b912011-07-07 18:59:34 -0300936
Brian Gixa68668b2011-08-11 15:49:36 -0700937static int smp_distribute_keys(struct l2cap_conn *conn, __u8 force)
Vinicius Costa Gomes7034b912011-07-07 18:59:34 -0300938{
Brian Gixa68668b2011-08-11 15:49:36 -0700939 struct hci_conn *hcon = conn->hcon;
Vinicius Costa Gomes7034b912011-07-07 18:59:34 -0300940 struct smp_cmd_pairing *req, *rsp;
941 __u8 *keydist;
942
943 BT_DBG("conn %p force %d", conn, force);
944
Brian Gixa68668b2011-08-11 15:49:36 -0700945 if (IS_ERR(hcon->hdev->tfm))
946 return PTR_ERR(hcon->hdev->tfm);
Vinicius Costa Gomesd26a2342011-08-19 21:06:51 -0300947
Brian Gixa68668b2011-08-11 15:49:36 -0700948 rsp = (void *) &hcon->prsp[1];
Vinicius Costa Gomes7034b912011-07-07 18:59:34 -0300949
950 /* The responder sends its keys first */
Brian Gixa68668b2011-08-11 15:49:36 -0700951 if (!force && hcon->out && (rsp->resp_key_dist & 0x07))
Vinicius Costa Gomes7034b912011-07-07 18:59:34 -0300952 return 0;
953
Brian Gixa68668b2011-08-11 15:49:36 -0700954 req = (void *) &hcon->preq[1];
Vinicius Costa Gomes7034b912011-07-07 18:59:34 -0300955
Brian Gixa68668b2011-08-11 15:49:36 -0700956 if (hcon->out) {
Vinicius Costa Gomes7034b912011-07-07 18:59:34 -0300957 keydist = &rsp->init_key_dist;
958 *keydist &= req->init_key_dist;
959 } else {
960 keydist = &rsp->resp_key_dist;
961 *keydist &= req->resp_key_dist;
962 }
963
964
965 BT_DBG("keydist 0x%x", *keydist);
966
967 if (*keydist & SMP_DIST_ENC_KEY) {
968 struct smp_cmd_encrypt_info enc;
969 struct smp_cmd_master_ident ident;
970 __le16 ediv;
971
972 get_random_bytes(enc.ltk, sizeof(enc.ltk));
973 get_random_bytes(&ediv, sizeof(ediv));
974 get_random_bytes(ident.rand, sizeof(ident.rand));
975
976 smp_send_cmd(conn, SMP_CMD_ENCRYPT_INFO, sizeof(enc), &enc);
977
Brian Gixcf956772011-10-20 15:18:51 -0700978 hci_add_ltk(hcon->hdev, 1, conn->dst, hcon->dst_type,
979 hcon->smp_key_size, hcon->auth, ediv,
980 ident.rand, enc.ltk);
Vinicius Costa Gomes16b90832011-07-07 18:59:39 -0300981
Vinicius Costa Gomes7034b912011-07-07 18:59:34 -0300982 ident.ediv = cpu_to_le16(ediv);
983
984 smp_send_cmd(conn, SMP_CMD_MASTER_IDENT, sizeof(ident), &ident);
985
986 *keydist &= ~SMP_DIST_ENC_KEY;
987 }
988
989 if (*keydist & SMP_DIST_ID_KEY) {
990 struct smp_cmd_ident_addr_info addrinfo;
991 struct smp_cmd_ident_info idinfo;
992
993 /* Send a dummy key */
994 get_random_bytes(idinfo.irk, sizeof(idinfo.irk));
995
996 smp_send_cmd(conn, SMP_CMD_IDENT_INFO, sizeof(idinfo), &idinfo);
997
998 /* Just public address */
999 memset(&addrinfo, 0, sizeof(addrinfo));
1000 bacpy(&addrinfo.bdaddr, conn->src);
1001
1002 smp_send_cmd(conn, SMP_CMD_IDENT_ADDR_INFO, sizeof(addrinfo),
1003 &addrinfo);
1004
1005 *keydist &= ~SMP_DIST_ID_KEY;
1006 }
1007
1008 if (*keydist & SMP_DIST_SIGN) {
1009 struct smp_cmd_sign_info sign;
1010
1011 /* Send a dummy key */
1012 get_random_bytes(sign.csrk, sizeof(sign.csrk));
1013
1014 smp_send_cmd(conn, SMP_CMD_SIGN_INFO, sizeof(sign), &sign);
1015
1016 *keydist &= ~SMP_DIST_SIGN;
1017 }
1018
Brian Gix2a335262011-11-17 12:59:23 -08001019 if (hcon->out) {
Brian Gixe57c1672011-09-13 12:34:59 -07001020 if (hcon->disconn_cfm_cb)
1021 hcon->disconn_cfm_cb(hcon, 0);
Brian Gixe9ceb522011-09-22 10:46:35 -07001022 del_timer(&hcon->smp_timer);
Brian Gix8d0b7d62011-10-12 15:12:42 -07001023 clear_bit(HCI_CONN_ENCRYPT_PEND, &hcon->pend);
Brian Gix2a335262011-11-17 12:59:23 -08001024 hci_conn_put(hcon);
1025 } else if (rsp->resp_key_dist) {
1026 if (hcon->disconn_cfm_cb)
1027 hcon->disconn_cfm_cb(hcon, SMP_UNSPECIFIED);
1028 clear_bit(HCI_CONN_ENCRYPT_PEND, &hcon->pend);
Brian Gix58ba0772011-09-23 13:40:16 -07001029 mgmt_auth_failed(hcon->hdev->id, conn->dst, SMP_UNSPECIFIED);
Brian Gix6d5fb8a2011-09-09 14:53:04 -07001030 hci_conn_put(hcon);
Vinicius Costa Gomesd26a2342011-08-19 21:06:51 -03001031 }
1032
Vinicius Costa Gomes7034b912011-07-07 18:59:34 -03001033 return 0;
1034}
Brian Gixa68668b2011-08-11 15:49:36 -07001035
1036int smp_link_encrypt_cmplt(struct l2cap_conn *conn, u8 status, u8 encrypt)
1037{
1038 struct hci_conn *hcon = conn->hcon;
1039
1040 BT_DBG("smp: %d %d %d", status, encrypt, hcon->sec_req);
1041
Brian Gix8d0b7d62011-10-12 15:12:42 -07001042 clear_bit(HCI_CONN_ENCRYPT_PEND, &hcon->pend);
1043
Brian Gix80fb3a92012-01-31 13:15:20 -08001044 if (!status && encrypt && hcon->sec_level < hcon->pending_sec_level)
1045 hcon->sec_level = hcon->pending_sec_level;
1046
Brian Gixa68668b2011-08-11 15:49:36 -07001047 if (!status && encrypt && !hcon->sec_req)
Brian Gix80fb3a92012-01-31 13:15:20 -08001048 return smp_distribute_keys(conn, 0);
Brian Gixa68668b2011-08-11 15:49:36 -07001049
1050 /* Fall back to Pairing request if failed a Link Security request */
1051 else if (hcon->sec_req && (status || !encrypt))
Brian Gix80fb3a92012-01-31 13:15:20 -08001052 smp_conn_security(conn, hcon->pending_sec_level);
Brian Gixa68668b2011-08-11 15:49:36 -07001053
Brian Gix80fb3a92012-01-31 13:15:20 -08001054 hci_conn_put(hcon);
Brian Gix8d0b7d62011-10-12 15:12:42 -07001055
Vinicius Costa Gomesc1d5e1d2011-07-07 18:59:34 -03001056 return 0;
1057}
Brian Gixe9ceb522011-09-22 10:46:35 -07001058
1059void smp_timeout(unsigned long arg)
1060{
1061 struct l2cap_conn *conn = (void *) arg;
1062 u8 reason = SMP_UNSPECIFIED;
1063
1064 BT_DBG("%p", conn);
1065
1066 smp_send_cmd(conn, SMP_CMD_PAIRING_FAIL, sizeof(reason), &reason);
Brian Gix8d0b7d62011-10-12 15:12:42 -07001067 clear_bit(HCI_CONN_ENCRYPT_PEND, &conn->hcon->pend);
Brian Gix58ba0772011-09-23 13:40:16 -07001068 mgmt_auth_failed(conn->hcon->hdev->id, conn->dst, SMP_UNSPECIFIED);
Brian Gixe9ceb522011-09-22 10:46:35 -07001069 hci_conn_put(conn->hcon);
1070}