blob: 4a830206fcc6b5241747d64df9cc3fa122280e68 [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) {
Bhakthavatsala Raghavendrab03b5702013-02-12 19:44:47 +0530216 case BT_SECURITY_VERY_HIGH:
Brian Gix2b64d152011-12-21 16:12:12 -0800217 case BT_SECURITY_HIGH:
218 return SMP_AUTH_MITM | SMP_AUTH_BONDING;
Vinicius Costa Gomes64532ec2011-06-09 18:50:53 -0300219
Brian Gix2b64d152011-12-21 16:12:12 -0800220 default:
221 return SMP_AUTH_NONE;
222 }
223}
224
Vinicius Costa Gomesb8e66ea2011-06-09 18:50:52 -0300225static void build_pairing_cmd(struct l2cap_conn *conn,
Vinicius Costa Gomes54790f72011-07-07 18:59:38 -0300226 struct smp_cmd_pairing *req,
227 struct smp_cmd_pairing *rsp,
228 __u8 authreq)
Vinicius Costa Gomesb8e66ea2011-06-09 18:50:52 -0300229{
Brian Gixa68668b2011-08-11 15:49:36 -0700230 struct hci_conn *hcon = conn->hcon;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700231 u8 all_keys = 0;
Brian Gix2b64d152011-12-21 16:12:12 -0800232 u8 dist_keys = 0;
Vinicius Costa Gomes54790f72011-07-07 18:59:38 -0300233
Brian Gixa68668b2011-08-11 15:49:36 -0700234 dist_keys = SMP_DIST_ENC_KEY;
235 authreq |= SMP_AUTH_BONDING;
236
237 BT_DBG("conn->hcon->io_capability:%d", conn->hcon->io_capability);
Vinicius Costa Gomes54790f72011-07-07 18:59:38 -0300238
239 if (rsp == NULL) {
240 req->io_capability = conn->hcon->io_capability;
Brian Gixa68668b2011-08-11 15:49:36 -0700241 req->oob_flag = hcon->oob ? SMP_OOB_PRESENT :
242 SMP_OOB_NOT_PRESENT;
Vinicius Costa Gomes54790f72011-07-07 18:59:38 -0300243 req->max_key_size = SMP_MAX_ENC_KEY_SIZE;
Brian Gixa68668b2011-08-11 15:49:36 -0700244 req->init_key_dist = all_keys;
Vinicius Costa Gomes54790f72011-07-07 18:59:38 -0300245 req->resp_key_dist = dist_keys;
246 req->auth_req = authreq;
Brian Gixa68668b2011-08-11 15:49:36 -0700247 BT_DBG("SMP_CMD_PAIRING_REQ %d %d %d %d %2.2x %2.2x",
248 req->io_capability, req->oob_flag,
249 req->auth_req, req->max_key_size,
250 req->init_key_dist, req->resp_key_dist);
Vinicius Costa Gomes54790f72011-07-07 18:59:38 -0300251 return;
252 }
253
Brian Gixa68668b2011-08-11 15:49:36 -0700254 /* Only request OOB if remote AND we support it */
255 if (req->oob_flag)
256 rsp->oob_flag = hcon->oob ? SMP_OOB_PRESENT :
257 SMP_OOB_NOT_PRESENT;
258 else
259 rsp->oob_flag = SMP_OOB_NOT_PRESENT;
260
Vinicius Costa Gomes54790f72011-07-07 18:59:38 -0300261 rsp->io_capability = conn->hcon->io_capability;
Vinicius Costa Gomes54790f72011-07-07 18:59:38 -0300262 rsp->max_key_size = SMP_MAX_ENC_KEY_SIZE;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700263 rsp->init_key_dist = req->init_key_dist & all_keys;
Vinicius Costa Gomes54790f72011-07-07 18:59:38 -0300264 rsp->resp_key_dist = req->resp_key_dist & dist_keys;
265 rsp->auth_req = authreq;
Brian Gixa68668b2011-08-11 15:49:36 -0700266 BT_DBG("SMP_CMD_PAIRING_RSP %d %d %d %d %2.2x %2.2x",
267 req->io_capability, req->oob_flag, req->auth_req,
268 req->max_key_size, req->init_key_dist,
269 req->resp_key_dist);
Vinicius Costa Gomesb8e66ea2011-06-09 18:50:52 -0300270}
271
Vinicius Costa Gomes3158c502011-06-14 13:37:42 -0300272static u8 check_enc_key_size(struct l2cap_conn *conn, __u8 max_key_size)
273{
Brian Gixa68668b2011-08-11 15:49:36 -0700274 struct hci_conn *hcon = conn->hcon;
Vinicius Costa Gomes1c1def02011-09-05 14:31:30 -0300275
Vinicius Costa Gomes3158c502011-06-14 13:37:42 -0300276 if ((max_key_size > SMP_MAX_ENC_KEY_SIZE) ||
277 (max_key_size < SMP_MIN_ENC_KEY_SIZE))
278 return SMP_ENC_KEY_SIZE;
279
Brian Gixa68668b2011-08-11 15:49:36 -0700280 hcon->smp_key_size = max_key_size;
Vinicius Costa Gomes3158c502011-06-14 13:37:42 -0300281
282 return 0;
283}
284
Brian Gixa68668b2011-08-11 15:49:36 -0700285#define JUST_WORKS SMP_JUST_WORKS
286#define REQ_PASSKEY SMP_REQ_PASSKEY
287#define CFM_PASSKEY SMP_CFM_PASSKEY
288#define JUST_CFM SMP_JUST_CFM
289#define OVERLAP SMP_OVERLAP
290static const u8 gen_method[5][5] = {
291 {JUST_WORKS, JUST_CFM, REQ_PASSKEY, JUST_WORKS, REQ_PASSKEY},
292 {JUST_WORKS, JUST_CFM, REQ_PASSKEY, JUST_WORKS, REQ_PASSKEY},
293 {CFM_PASSKEY, CFM_PASSKEY, REQ_PASSKEY, JUST_WORKS, CFM_PASSKEY},
294 {JUST_WORKS, JUST_CFM, JUST_WORKS, JUST_WORKS, JUST_CFM},
295 {CFM_PASSKEY, CFM_PASSKEY, REQ_PASSKEY, JUST_WORKS, OVERLAP}
Brian Gix2b64d152011-12-21 16:12:12 -0800296};
297
298static int tk_request(struct l2cap_conn *conn, u8 remote_oob, u8 auth,
299 u8 local_io, u8 remote_io)
300{
301 struct hci_conn *hcon = conn->hcon;
Brian Gix2b64d152011-12-21 16:12:12 -0800302 u8 method;
303 u32 passkey = 0;
304 int ret = 0;
305
Brian Gixa68668b2011-08-11 15:49:36 -0700306 /* Initialize key to JUST WORKS */
307 memset(hcon->tk, 0, sizeof(hcon->tk));
308 hcon->tk_valid = FALSE;
309 hcon->auth = auth;
310
311 /* By definition, OOB data will be used if both sides have it available
312 */
313 if (remote_oob && hcon->oob) {
314 method = SMP_REQ_OOB;
315 goto agent_request;
316 }
Brian Gix2b64d152011-12-21 16:12:12 -0800317
318 BT_DBG("tk_request: auth:%d lcl:%d rem:%d", auth, local_io, remote_io);
319
320 /* If neither side wants MITM, use JUST WORKS */
Brian Gixa68668b2011-08-11 15:49:36 -0700321 /* If either side has unknown io_caps, use JUST_WORKS */
Brian Gix2b64d152011-12-21 16:12:12 -0800322 if (!(auth & SMP_AUTH_MITM) ||
323 local_io > SMP_IO_KEYBOARD_DISPLAY ||
Brian Gixa68668b2011-08-11 15:49:36 -0700324 remote_io > SMP_IO_KEYBOARD_DISPLAY) {
325 hcon->auth &= ~SMP_AUTH_MITM;
326 hcon->tk_valid = TRUE;
Brian Gix2b64d152011-12-21 16:12:12 -0800327 return 0;
328 }
329
Brian Gixa68668b2011-08-11 15:49:36 -0700330 /* MITM is now officially requested, but not required */
331 /* Determine what we need (if anything) from the agent */
332 method = gen_method[local_io][remote_io];
Brian Gix2b64d152011-12-21 16:12:12 -0800333
Brian Gixa68668b2011-08-11 15:49:36 -0700334 BT_DBG("tk_method: %d", method);
335
336 if (method == SMP_JUST_WORKS || method == SMP_JUST_CFM)
337 hcon->auth &= ~SMP_AUTH_MITM;
338
339 /* Don't bother confirming unbonded JUST_WORKS */
340 if (!(auth & SMP_AUTH_BONDING) && method == SMP_JUST_CFM) {
341 hcon->tk_valid = TRUE;
342 return 0;
343 } else if (method == SMP_JUST_WORKS) {
344 hcon->tk_valid = TRUE;
345 return 0;
346 } else if (method == SMP_OVERLAP) {
Brian Gix2b64d152011-12-21 16:12:12 -0800347 if (hcon->link_mode & HCI_LM_MASTER)
Brian Gixa68668b2011-08-11 15:49:36 -0700348 method = SMP_CFM_PASSKEY;
Brian Gix2b64d152011-12-21 16:12:12 -0800349 else
Brian Gixa68668b2011-08-11 15:49:36 -0700350 method = SMP_REQ_PASSKEY;
Brian Gix2b64d152011-12-21 16:12:12 -0800351 }
352
Brian Gixa68668b2011-08-11 15:49:36 -0700353 BT_DBG("tk_method-2: %d", method);
Brian Gix2b64d152011-12-21 16:12:12 -0800354
Brian Gixa68668b2011-08-11 15:49:36 -0700355 if (method == SMP_CFM_PASSKEY) {
356 u8 key[16];
357 /* Generate a passkey for display. It is not valid until
358 * confirmed.
359 */
Brian Gix2b64d152011-12-21 16:12:12 -0800360 memset(key, 0, sizeof(key));
361 get_random_bytes(&passkey, sizeof(passkey));
362 passkey %= 1000000;
363 put_unaligned_le32(passkey, key);
Brian Gixa68668b2011-08-11 15:49:36 -0700364 swap128(key, hcon->tk);
Brian Gix2b64d152011-12-21 16:12:12 -0800365 BT_DBG("PassKey: %d", passkey);
366 }
367
Brian Gixa68668b2011-08-11 15:49:36 -0700368agent_request:
Brian Gix2b64d152011-12-21 16:12:12 -0800369 hci_dev_lock(hcon->hdev);
370
Brian Gixa68668b2011-08-11 15:49:36 -0700371 switch (method) {
372 case SMP_REQ_PASSKEY:
Brian Gix3dd70172011-09-16 21:38:54 -0700373 ret = mgmt_user_confirm_request(hcon->hdev->id,
374 HCI_EV_USER_PASSKEY_REQUEST, conn->dst, 0);
375 break;
Brian Gixa68668b2011-08-11 15:49:36 -0700376 case SMP_CFM_PASSKEY:
377 default:
Brian Gix3dd70172011-09-16 21:38:54 -0700378 ret = mgmt_user_confirm_request(hcon->hdev->id,
379 HCI_EV_USER_CONFIRM_REQUEST, conn->dst, passkey);
380 break;
Brian Gixa68668b2011-08-11 15:49:36 -0700381 }
Brian Gix2b64d152011-12-21 16:12:12 -0800382
383 hci_dev_unlock(hcon->hdev);
384
385 return ret;
386}
387
Brian Gixa68668b2011-08-11 15:49:36 -0700388static int send_pairing_confirm(struct l2cap_conn *conn)
Vinicius Costa Gomes8aab4752011-09-05 14:31:31 -0300389{
Brian Gixa68668b2011-08-11 15:49:36 -0700390 struct hci_conn *hcon = conn->hcon;
391 struct crypto_blkcipher *tfm = hcon->hdev->tfm;
Vinicius Costa Gomes8aab4752011-09-05 14:31:31 -0300392 struct smp_cmd_pairing_confirm cp;
393 int ret;
Brian Gixa68668b2011-08-11 15:49:36 -0700394 u8 res[16];
Vinicius Costa Gomes8aab4752011-09-05 14:31:31 -0300395
396 if (conn->hcon->out)
Brian Gixa68668b2011-08-11 15:49:36 -0700397 ret = smp_c1(tfm, hcon->tk, hcon->prnd, hcon->preq, hcon->prsp,
398 0, conn->src, hcon->dst_type, conn->dst, res);
Vinicius Costa Gomes8aab4752011-09-05 14:31:31 -0300399 else
Brian Gixa68668b2011-08-11 15:49:36 -0700400 ret = smp_c1(tfm, hcon->tk, hcon->prnd, hcon->preq, hcon->prsp,
401 hcon->dst_type, conn->dst, 0, conn->src, res);
Vinicius Costa Gomes8aab4752011-09-05 14:31:31 -0300402
Brian Gixa68668b2011-08-11 15:49:36 -0700403 if (ret)
404 return SMP_CONFIRM_FAILED;
Brian Gix2b64d152011-12-21 16:12:12 -0800405
Vinicius Costa Gomes8aab4752011-09-05 14:31:31 -0300406 swap128(res, cp.confirm_val);
Vinicius Costa Gomes8aab4752011-09-05 14:31:31 -0300407
Brian Gixa68668b2011-08-11 15:49:36 -0700408 hcon->cfm_pending = FALSE;
Vinicius Costa Gomes8aab4752011-09-05 14:31:31 -0300409
Brian Gixa68668b2011-08-11 15:49:36 -0700410 smp_send_cmd(conn, SMP_CMD_PAIRING_CONFIRM, sizeof(cp), &cp);
Brian Gix2b64d152011-12-21 16:12:12 -0800411
412 return 0;
413}
414
Brian Gix6d5fb8a2011-09-09 14:53:04 -0700415int le_user_confirm_reply(struct hci_conn *hcon, u16 mgmt_op, void *cp)
Brian Gixa68668b2011-08-11 15:49:36 -0700416{
417 struct mgmt_cp_user_passkey_reply *psk_reply = cp;
Brian Gix6d5fb8a2011-09-09 14:53:04 -0700418 struct l2cap_conn *conn = hcon->smp_conn;
Brian Gixa68668b2011-08-11 15:49:36 -0700419 u8 key[16];
420 u8 reason = 0;
421 int ret = 0;
422
423 BT_DBG("");
424
Brian Gix6d5fb8a2011-09-09 14:53:04 -0700425 hcon->tk_valid = TRUE;
Brian Gixa68668b2011-08-11 15:49:36 -0700426
427 switch (mgmt_op) {
428 case MGMT_OP_USER_CONFIRM_NEG_REPLY:
429 reason = SMP_CONFIRM_FAILED;
430 break;
431 case MGMT_OP_USER_CONFIRM_REPLY:
432 break;
433 case MGMT_OP_USER_PASSKEY_REPLY:
434 memset(key, 0, sizeof(key));
435 BT_DBG("PassKey: %d", psk_reply->passkey);
436 put_unaligned_le32(psk_reply->passkey, key);
Brian Gix6d5fb8a2011-09-09 14:53:04 -0700437 swap128(key, hcon->tk);
Brian Gixa68668b2011-08-11 15:49:36 -0700438 break;
439 default:
440 reason = SMP_CONFIRM_FAILED;
441 ret = -EOPNOTSUPP;
442 break;
443 }
444
445 if (reason) {
446 BT_DBG("smp_send_cmd: SMP_CMD_PAIRING_FAIL");
447 smp_send_cmd(conn, SMP_CMD_PAIRING_FAIL, sizeof(reason),
448 &reason);
Brian Gixe9ceb522011-09-22 10:46:35 -0700449 del_timer(&hcon->smp_timer);
Archana Ramachandran0bb14f02012-11-14 11:00:48 -0800450 if (hcon->disconn_cfm_cb)
451 hcon->disconn_cfm_cb(hcon, SMP_UNSPECIFIED);
Brian Gix8d0b7d62011-10-12 15:12:42 -0700452 clear_bit(HCI_CONN_ENCRYPT_PEND, &hcon->pend);
Brian Gix58ba0772011-09-23 13:40:16 -0700453 mgmt_auth_failed(hcon->hdev->id, conn->dst, reason);
Brian Gix6d5fb8a2011-09-09 14:53:04 -0700454 hci_conn_put(hcon);
455 } else if (hcon->cfm_pending) {
Brian Gixa68668b2011-08-11 15:49:36 -0700456 BT_DBG("send_pairing_confirm");
457 ret = send_pairing_confirm(conn);
458 }
459
460 return ret;
461}
462
Vinicius Costa Gomesda85e5e2011-06-09 18:50:53 -0300463static u8 smp_cmd_pairing_req(struct l2cap_conn *conn, struct sk_buff *skb)
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300464{
Brian Gixa68668b2011-08-11 15:49:36 -0700465 struct hci_conn *hcon = conn->hcon;
Vinicius Costa Gomes3158c502011-06-14 13:37:42 -0300466 struct smp_cmd_pairing rsp, *req = (void *) skb->data;
467 u8 key_size;
Brian Gix2b64d152011-12-21 16:12:12 -0800468 u8 auth = SMP_AUTH_NONE;
Vinicius Costa Gomes8aab4752011-09-05 14:31:31 -0300469 int ret;
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300470
471 BT_DBG("conn %p", conn);
472
Brian Gixa68668b2011-08-11 15:49:36 -0700473 hcon->preq[0] = SMP_CMD_PAIRING_REQ;
474 memcpy(&hcon->preq[1], req, sizeof(*req));
Vinicius Costa Gomes3158c502011-06-14 13:37:42 -0300475 skb_pull(skb, sizeof(*req));
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300476
Brian Gixa68668b2011-08-11 15:49:36 -0700477 if (req->oob_flag && hcon->oob) {
478 /* By definition, OOB data pairing will have MITM protection */
479 auth = req->auth_req | SMP_AUTH_MITM;
480 } else if (req->auth_req & SMP_AUTH_BONDING) {
481 /* We will attempt MITM for all Bonding attempts */
482 auth = SMP_AUTH_BONDING | SMP_AUTH_MITM;
483 }
Vinicius Costa Gomesda85e5e2011-06-09 18:50:53 -0300484
Vinicius Costa Gomes64532ec2011-06-09 18:50:53 -0300485 /* We didn't start the pairing, so no requirements */
Brian Gix2b64d152011-12-21 16:12:12 -0800486 build_pairing_cmd(conn, req, &rsp, auth);
Vinicius Costa Gomes3158c502011-06-14 13:37:42 -0300487
488 key_size = min(req->max_key_size, rsp.max_key_size);
489 if (check_enc_key_size(conn, key_size))
490 return SMP_ENC_KEY_SIZE;
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300491
Brian Gixa68668b2011-08-11 15:49:36 -0700492 ret = smp_rand(hcon->prnd);
Vinicius Costa Gomes8aab4752011-09-05 14:31:31 -0300493 if (ret)
494 return SMP_UNSPECIFIED;
495
Brian Gixa68668b2011-08-11 15:49:36 -0700496 /* Request setup of TK */
497 ret = tk_request(conn, req->oob_flag, auth, rsp.io_capability,
498 req->io_capability);
499 if (ret)
500 return SMP_UNSPECIFIED;
501
502 hcon->prsp[0] = SMP_CMD_PAIRING_RSP;
503 memcpy(&hcon->prsp[1], &rsp, sizeof(rsp));
Anderson Brigliaf01ead32011-06-09 18:50:45 -0300504
Vinicius Costa Gomes3158c502011-06-14 13:37:42 -0300505 smp_send_cmd(conn, SMP_CMD_PAIRING_RSP, sizeof(rsp), &rsp);
Vinicius Costa Gomesda85e5e2011-06-09 18:50:53 -0300506
Brian Gixe9ceb522011-09-22 10:46:35 -0700507 mod_timer(&hcon->smp_timer, jiffies + msecs_to_jiffies(SMP_TIMEOUT));
Brian Gix2b64d152011-12-21 16:12:12 -0800508
Vinicius Costa Gomesda85e5e2011-06-09 18:50:53 -0300509 return 0;
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300510}
511
Vinicius Costa Gomesda85e5e2011-06-09 18:50:53 -0300512static u8 smp_cmd_pairing_rsp(struct l2cap_conn *conn, struct sk_buff *skb)
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300513{
Brian Gixa68668b2011-08-11 15:49:36 -0700514 struct hci_conn *hcon = conn->hcon;
Vinicius Costa Gomes3158c502011-06-14 13:37:42 -0300515 struct smp_cmd_pairing *req, *rsp = (void *) skb->data;
Brian Gix2b64d152011-12-21 16:12:12 -0800516 u8 key_size, auth = SMP_AUTH_NONE;
Anderson Briglia7d24ddc2011-06-09 18:50:46 -0300517 int ret;
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300518
519 BT_DBG("conn %p", conn);
520
Vinicius Costa Gomes3158c502011-06-14 13:37:42 -0300521 skb_pull(skb, sizeof(*rsp));
Vinicius Costa Gomesda85e5e2011-06-09 18:50:53 -0300522
Brian Gixa68668b2011-08-11 15:49:36 -0700523 req = (void *) &hcon->preq[1];
Vinicius Costa Gomes3158c502011-06-14 13:37:42 -0300524
525 key_size = min(req->max_key_size, rsp->max_key_size);
526 if (check_enc_key_size(conn, key_size))
527 return SMP_ENC_KEY_SIZE;
528
Brian Gixa68668b2011-08-11 15:49:36 -0700529 hcon->prsp[0] = SMP_CMD_PAIRING_RSP;
530 memcpy(&hcon->prsp[1], rsp, sizeof(*rsp));
Vinicius Costa Gomes64532ec2011-06-09 18:50:53 -0300531
Brian Gixa68668b2011-08-11 15:49:36 -0700532 ret = smp_rand(hcon->prnd);
Anderson Briglia7d24ddc2011-06-09 18:50:46 -0300533 if (ret)
Vinicius Costa Gomesda85e5e2011-06-09 18:50:53 -0300534 return SMP_UNSPECIFIED;
Anderson Briglia7d24ddc2011-06-09 18:50:46 -0300535
Brian Gix2b64d152011-12-21 16:12:12 -0800536 if ((req->auth_req & SMP_AUTH_BONDING) &&
537 (rsp->auth_req & SMP_AUTH_BONDING))
538 auth = SMP_AUTH_BONDING;
539
540 auth |= (req->auth_req | rsp->auth_req) & SMP_AUTH_MITM;
541
Brian Gixa68668b2011-08-11 15:49:36 -0700542 ret = tk_request(conn, req->oob_flag, auth, rsp->io_capability,
543 req->io_capability);
Brian Gix2b64d152011-12-21 16:12:12 -0800544 if (ret)
545 return SMP_UNSPECIFIED;
546
Brian Gixa68668b2011-08-11 15:49:36 -0700547 hcon->cfm_pending = TRUE;
Brian Gix2b64d152011-12-21 16:12:12 -0800548
549 /* Can't compose response until we have been confirmed */
Brian Gixa68668b2011-08-11 15:49:36 -0700550 if (!hcon->tk_valid)
Brian Gix2b64d152011-12-21 16:12:12 -0800551 return 0;
552
Brian Gixa68668b2011-08-11 15:49:36 -0700553 ret = send_pairing_confirm(conn);
554 if (ret)
555 return SMP_CONFIRM_FAILED;
Vinicius Costa Gomesda85e5e2011-06-09 18:50:53 -0300556
557 return 0;
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300558}
559
Vinicius Costa Gomesda85e5e2011-06-09 18:50:53 -0300560static u8 smp_cmd_pairing_confirm(struct l2cap_conn *conn, struct sk_buff *skb)
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300561{
Brian Gixa68668b2011-08-11 15:49:36 -0700562 struct hci_conn *hcon = conn->hcon;
563 int ret;
Anderson Briglia7d24ddc2011-06-09 18:50:46 -0300564
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300565 BT_DBG("conn %p %s", conn, conn->hcon->out ? "master" : "slave");
566
Brian Gixa68668b2011-08-11 15:49:36 -0700567 memcpy(hcon->pcnf, skb->data, sizeof(hcon->pcnf));
568 skb_pull(skb, sizeof(hcon->pcnf));
Anderson Briglia7d24ddc2011-06-09 18:50:46 -0300569
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300570 if (conn->hcon->out) {
Anderson Briglia7d24ddc2011-06-09 18:50:46 -0300571 u8 random[16];
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300572
Brian Gixa68668b2011-08-11 15:49:36 -0700573 swap128(hcon->prnd, random);
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300574 smp_send_cmd(conn, SMP_CMD_PAIRING_RANDOM, sizeof(random),
Anderson Briglia7d24ddc2011-06-09 18:50:46 -0300575 random);
Brian Gixa68668b2011-08-11 15:49:36 -0700576 } else if (hcon->tk_valid) {
577 ret = send_pairing_confirm(conn);
Anderson Briglia13b48392011-06-09 18:50:42 -0300578
Anderson Briglia21b8a2b2011-06-09 18:50:46 -0300579 if (ret)
Vinicius Costa Gomes64532ec2011-06-09 18:50:53 -0300580 return SMP_CONFIRM_FAILED;
Brian Gixa68668b2011-08-11 15:49:36 -0700581 } else
582 hcon->cfm_pending = TRUE;
Anderson Briglia21b8a2b2011-06-09 18:50:46 -0300583
Vinicius Costa Gomes64532ec2011-06-09 18:50:53 -0300584
Brian Gixe9ceb522011-09-22 10:46:35 -0700585 mod_timer(&hcon->smp_timer, jiffies + msecs_to_jiffies(SMP_TIMEOUT));
Vinicius Costa Gomesda85e5e2011-06-09 18:50:53 -0300586
587 return 0;
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300588}
589
Vinicius Costa Gomesda85e5e2011-06-09 18:50:53 -0300590static u8 smp_cmd_pairing_random(struct l2cap_conn *conn, struct sk_buff *skb)
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300591{
Vinicius Costa Gomes735038c2011-06-09 18:50:47 -0300592 struct hci_conn *hcon = conn->hcon;
593 struct crypto_blkcipher *tfm = hcon->hdev->tfm;
Anderson Briglia21b8a2b2011-06-09 18:50:46 -0300594 int ret;
Vinicius Costa Gomesc34e25e2011-06-09 18:50:48 -0300595 u8 key[16], res[16], random[16], confirm[16];
Anderson Briglia7d24ddc2011-06-09 18:50:46 -0300596
Anderson Briglia21b8a2b2011-06-09 18:50:46 -0300597 swap128(skb->data, random);
598 skb_pull(skb, sizeof(random));
Anderson Briglia7d24ddc2011-06-09 18:50:46 -0300599
Anderson Briglia21b8a2b2011-06-09 18:50:46 -0300600 if (conn->hcon->out)
Brian Gixa68668b2011-08-11 15:49:36 -0700601 ret = smp_c1(tfm, hcon->tk, random, hcon->preq, hcon->prsp, 0,
602 conn->src, hcon->dst_type, conn->dst,
Anderson Briglia21b8a2b2011-06-09 18:50:46 -0300603 res);
604 else
Brian Gixa68668b2011-08-11 15:49:36 -0700605 ret = smp_c1(tfm, hcon->tk, random, hcon->preq, hcon->prsp,
606 hcon->dst_type, conn->dst, 0, conn->src,
Anderson Briglia21b8a2b2011-06-09 18:50:46 -0300607 res);
608 if (ret)
Vinicius Costa Gomes64532ec2011-06-09 18:50:53 -0300609 return SMP_UNSPECIFIED;
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300610
Anderson Briglia13b48392011-06-09 18:50:42 -0300611 BT_DBG("conn %p %s", conn, conn->hcon->out ? "master" : "slave");
612
Anderson Briglia21b8a2b2011-06-09 18:50:46 -0300613 swap128(res, confirm);
614
Brian Gixa68668b2011-08-11 15:49:36 -0700615 if (memcmp(hcon->pcnf, confirm, sizeof(hcon->pcnf)) != 0) {
Anderson Briglia21b8a2b2011-06-09 18:50:46 -0300616 BT_ERR("Pairing failed (confirmation values mismatch)");
Vinicius Costa Gomes64532ec2011-06-09 18:50:53 -0300617 return SMP_CONFIRM_FAILED;
Anderson Briglia21b8a2b2011-06-09 18:50:46 -0300618 }
Anderson Briglia13b48392011-06-09 18:50:42 -0300619
620 if (conn->hcon->out) {
Vinicius Costa Gomesf1b45c52011-07-07 18:59:40 -0300621 u8 stk[16], rand[8];
Vinicius Costa Gomes735038c2011-06-09 18:50:47 -0300622 __le16 ediv;
Vinicius Costa Gomes397d9ae2011-06-14 13:37:42 -0300623
Vinicius Costa Gomes735038c2011-06-09 18:50:47 -0300624 memset(rand, 0, sizeof(rand));
625 ediv = 0;
Vinicius Costa Gomesf1b45c52011-07-07 18:59:40 -0300626
Brian Gixa68668b2011-08-11 15:49:36 -0700627 smp_s1(tfm, hcon->tk, random, hcon->prnd, key);
Vinicius Costa Gomesf1b45c52011-07-07 18:59:40 -0300628 swap128(key, stk);
629
Brian Gixa68668b2011-08-11 15:49:36 -0700630 memset(stk + hcon->smp_key_size, 0,
631 SMP_MAX_ENC_KEY_SIZE - hcon->smp_key_size);
Vinicius Costa Gomesf1b45c52011-07-07 18:59:40 -0300632
633 hci_le_start_enc(hcon, ediv, rand, stk);
Brian Gixa68668b2011-08-11 15:49:36 -0700634 hcon->enc_key_size = hcon->smp_key_size;
Anderson Briglia21b8a2b2011-06-09 18:50:46 -0300635 } else {
Vinicius Costa Gomesf1b45c52011-07-07 18:59:40 -0300636 u8 stk[16], r[16], rand[8];
637 __le16 ediv;
638
639 memset(rand, 0, sizeof(rand));
640 ediv = 0;
Anderson Briglia21b8a2b2011-06-09 18:50:46 -0300641
Brian Gixa68668b2011-08-11 15:49:36 -0700642 swap128(hcon->prnd, r);
Anderson Briglia21b8a2b2011-06-09 18:50:46 -0300643 smp_send_cmd(conn, SMP_CMD_PAIRING_RANDOM, sizeof(r), r);
644
Brian Gixa68668b2011-08-11 15:49:36 -0700645 smp_s1(tfm, hcon->tk, hcon->prnd, random, key);
Vinicius Costa Gomesf1b45c52011-07-07 18:59:40 -0300646 swap128(key, stk);
Vinicius Costa Gomes397d9ae2011-06-14 13:37:42 -0300647
Brian Gixa68668b2011-08-11 15:49:36 -0700648 memset(stk + hcon->smp_key_size, 0,
649 SMP_MAX_ENC_KEY_SIZE - hcon->smp_key_size);
Vinicius Costa Gomesf1b45c52011-07-07 18:59:40 -0300650
Brian Gixcf956772011-10-20 15:18:51 -0700651 hci_add_ltk(conn->hcon->hdev, 0, conn->dst, hcon->dst_type,
652 hcon->smp_key_size, hcon->auth, ediv, rand, stk);
Anderson Briglia13b48392011-06-09 18:50:42 -0300653 }
Vinicius Costa Gomesda85e5e2011-06-09 18:50:53 -0300654
655 return 0;
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300656}
657
Brian Gix372257b2011-10-25 09:06:30 -0700658static int smp_encrypt_link(struct hci_conn *hcon, struct link_key *key)
Vinicius Costa Gomes988c5992011-08-25 20:02:28 -0300659{
Brian Gix372257b2011-10-25 09:06:30 -0700660 struct key_master_id *master;
Brian Gix80fb3a92012-01-31 13:15:20 -0800661 u8 sec_level;
Brian Gix372257b2011-10-25 09:06:30 -0700662 u8 zerobuf[8];
Vinicius Costa Gomes988c5992011-08-25 20:02:28 -0300663
Brian Gix372257b2011-10-25 09:06:30 -0700664 if (!hcon || !key || !key->data)
665 return -EINVAL;
Vinicius Costa Gomes988c5992011-08-25 20:02:28 -0300666
Brian Gix372257b2011-10-25 09:06:30 -0700667 memset(zerobuf, 0, sizeof(zerobuf));
Vinicius Costa Gomes988c5992011-08-25 20:02:28 -0300668
Brian Gix372257b2011-10-25 09:06:30 -0700669 master = (void *) key->data;
Vinicius Costa Gomes988c5992011-08-25 20:02:28 -0300670
Brian Gix372257b2011-10-25 09:06:30 -0700671 if (!master->ediv && !memcmp(master->rand, zerobuf, sizeof(zerobuf)))
672 return -EINVAL;
Vinicius Costa Gomes988c5992011-08-25 20:02:28 -0300673
Brian Gix372257b2011-10-25 09:06:30 -0700674 hcon->enc_key_size = key->pin_len;
675 hcon->sec_req = TRUE;
Brian Gix80fb3a92012-01-31 13:15:20 -0800676 sec_level = authreq_to_seclevel(key->auth);
677
678 BT_DBG("cur %d, req: %d", hcon->sec_level, sec_level);
679
680 if (sec_level > hcon->sec_level)
681 hcon->pending_sec_level = sec_level;
682
683
684 if (!(hcon->link_mode & HCI_LM_ENCRYPT))
685 hci_conn_hold(hcon);
686
Brian Gix372257b2011-10-25 09:06:30 -0700687 hci_le_start_enc(hcon, master->ediv, master->rand, key->val);
688
689 return 0;
Vinicius Costa Gomes988c5992011-08-25 20:02:28 -0300690}
Brian Gix372257b2011-10-25 09:06:30 -0700691
Vinicius Costa Gomesda85e5e2011-06-09 18:50:53 -0300692static u8 smp_cmd_security_req(struct l2cap_conn *conn, struct sk_buff *skb)
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300693{
Brian Gixa68668b2011-08-11 15:49:36 -0700694 struct hci_conn *hcon = conn->hcon;
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300695 struct smp_cmd_security_req *rp = (void *) skb->data;
696 struct smp_cmd_pairing cp;
Brian Gixa68668b2011-08-11 15:49:36 -0700697 struct link_key *key;
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300698
699 BT_DBG("conn %p", conn);
700
Vinicius Costa Gomesa5474a82011-01-26 21:42:57 -0300701 if (test_bit(HCI_CONN_ENCRYPT_PEND, &hcon->pend))
Vinicius Costa Gomes988c5992011-08-25 20:02:28 -0300702 return 0;
703
Brian Gixa68668b2011-08-11 15:49:36 -0700704 key = hci_find_link_key_type(hcon->hdev, conn->dst, KEY_TYPE_LTK);
705 if (key && ((key->auth & SMP_AUTH_MITM) ||
706 !(rp->auth_req & SMP_AUTH_MITM))) {
Vinicius Costa Gomesf1cb9af2011-01-26 21:42:57 -0300707
Brian Gix372257b2011-10-25 09:06:30 -0700708 if (smp_encrypt_link(hcon, key) < 0)
709 goto invalid_key;
Brian Gixa68668b2011-08-11 15:49:36 -0700710
Brian Gixa68668b2011-08-11 15:49:36 -0700711 return 0;
712 }
713
Brian Gix372257b2011-10-25 09:06:30 -0700714invalid_key:
Brian Gixa68668b2011-08-11 15:49:36 -0700715 hcon->sec_req = FALSE;
716
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300717 skb_pull(skb, sizeof(*rp));
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300718
Vinicius Costa Gomesda85e5e2011-06-09 18:50:53 -0300719 memset(&cp, 0, sizeof(cp));
Vinicius Costa Gomes54790f72011-07-07 18:59:38 -0300720 build_pairing_cmd(conn, &cp, NULL, rp->auth_req);
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300721
Brian Gix27a795c2012-04-19 11:05:06 -0700722 hcon->pending_sec_level = authreq_to_seclevel(rp->auth_req);
Brian Gixa68668b2011-08-11 15:49:36 -0700723 hcon->preq[0] = SMP_CMD_PAIRING_REQ;
724 memcpy(&hcon->preq[1], &cp, sizeof(cp));
Anderson Brigliaf01ead32011-06-09 18:50:45 -0300725
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300726 smp_send_cmd(conn, SMP_CMD_PAIRING_REQ, sizeof(cp), &cp);
Vinicius Costa Gomesf1cb9af2011-01-26 21:42:57 -0300727
Brian Gixe9ceb522011-09-22 10:46:35 -0700728 mod_timer(&hcon->smp_timer, jiffies + msecs_to_jiffies(SMP_TIMEOUT));
Vinicius Costa Gomesb19d5ce2011-06-14 13:37:41 -0300729
Vinicius Costa Gomesa5474a82011-01-26 21:42:57 -0300730 set_bit(HCI_CONN_ENCRYPT_PEND, &hcon->pend);
Vinicius Costa Gomesa5474a82011-01-26 21:42:57 -0300731
Brian Gix8d0b7d62011-10-12 15:12:42 -0700732 hci_conn_hold(hcon);
733
Vinicius Costa Gomesda85e5e2011-06-09 18:50:53 -0300734 return 0;
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300735}
736
Anderson Brigliaeb492e02011-06-09 18:50:40 -0300737int smp_conn_security(struct l2cap_conn *conn, __u8 sec_level)
738{
Vinicius Costa Gomes3a0259b2011-06-09 18:50:43 -0300739 struct hci_conn *hcon = conn->hcon;
Brian Gix2b64d152011-12-21 16:12:12 -0800740 __u8 authreq;
Anderson Brigliaeb492e02011-06-09 18:50:40 -0300741
Brian Gix80fb3a92012-01-31 13:15:20 -0800742 BT_DBG("conn %p hcon %p %d req: %d",
743 conn, hcon, hcon->sec_level, sec_level);
Vinicius Costa Gomes3a0259b2011-06-09 18:50:43 -0300744
Brian Gix80fb3a92012-01-31 13:15:20 -0800745 if (IS_ERR(hcon->hdev->tfm))
Andre Guedes2e65c9d2011-06-30 19:20:56 -0300746 return 1;
747
Brian Gix80fb3a92012-01-31 13:15:20 -0800748 if (test_bit(HCI_CONN_ENCRYPT_PEND, &hcon->pend))
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700749 return -EINPROGRESS;
Anderson Briglia133e14c2011-06-09 18:50:40 -0300750
Vinicius Costa Gomesf1cb9af2011-01-26 21:42:57 -0300751 if (sec_level == BT_SECURITY_LOW)
Anderson Brigliaeb492e02011-06-09 18:50:40 -0300752 return 1;
Vinicius Costa Gomesf1cb9af2011-01-26 21:42:57 -0300753
Brian Gix80fb3a92012-01-31 13:15:20 -0800754
Vinicius Costa Gomesf1cb9af2011-01-26 21:42:57 -0300755 if (hcon->sec_level >= sec_level)
756 return 1;
757
Brian Gix2b64d152011-12-21 16:12:12 -0800758 authreq = seclevel_to_authreq(sec_level);
Vinicius Costa Gomesd26a2342011-08-19 21:06:51 -0300759
Brian Gixa68668b2011-08-11 15:49:36 -0700760 hcon->smp_conn = conn;
Brian Gix80fb3a92012-01-31 13:15:20 -0800761 hcon->pending_sec_level = sec_level;
Subramanian Srinivasan3e7c75d2012-10-08 17:22:43 -0700762 if (hcon->link_mode & HCI_LM_MASTER) {
Vinicius Costa Gomes5d873ca2011-07-07 18:59:41 -0300763 struct link_key *key;
764
765 key = hci_find_link_key_type(hcon->hdev, conn->dst,
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700766 KEY_TYPE_LTK);
Vinicius Costa Gomes5d873ca2011-07-07 18:59:41 -0300767
Brian Gix372257b2011-10-25 09:06:30 -0700768 if (smp_encrypt_link(hcon, key) == 0)
Vinicius Costa Gomes5d873ca2011-07-07 18:59:41 -0300769 goto done;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700770 }
771
Brian Gixa68668b2011-08-11 15:49:36 -0700772 hcon->sec_req = FALSE;
773
Vinicius Costa Gomesd26a2342011-08-19 21:06:51 -0300774 if (hcon->link_mode & HCI_LM_MASTER) {
775 struct smp_cmd_pairing cp;
Anderson Brigliaf01ead32011-06-09 18:50:45 -0300776
Brian Gix2b64d152011-12-21 16:12:12 -0800777 build_pairing_cmd(conn, &cp, NULL, authreq);
Brian Gixa68668b2011-08-11 15:49:36 -0700778 hcon->preq[0] = SMP_CMD_PAIRING_REQ;
779 memcpy(&hcon->preq[1], &cp, sizeof(cp));
Anderson Brigliac8e856e2011-06-09 18:50:45 -0300780
Brian Gixe9ceb522011-09-22 10:46:35 -0700781 mod_timer(&hcon->smp_timer, jiffies +
Vinicius Costa Gomesb19d5ce2011-06-14 13:37:41 -0300782 msecs_to_jiffies(SMP_TIMEOUT));
Anderson Brigliaf01ead32011-06-09 18:50:45 -0300783
Anderson Brigliaeb492e02011-06-09 18:50:40 -0300784 smp_send_cmd(conn, SMP_CMD_PAIRING_REQ, sizeof(cp), &cp);
Brian Gix80fb3a92012-01-31 13:15:20 -0800785 hci_conn_hold(hcon);
Anderson Brigliaeb492e02011-06-09 18:50:40 -0300786 } else {
787 struct smp_cmd_security_req cp;
Brian Gix2b64d152011-12-21 16:12:12 -0800788 cp.auth_req = authreq;
Anderson Brigliaeb492e02011-06-09 18:50:40 -0300789 smp_send_cmd(conn, SMP_CMD_SECURITY_REQ, sizeof(cp), &cp);
790 }
791
Vinicius Costa Gomes02bc7452011-07-07 18:59:41 -0300792done:
Vinicius Costa Gomesa5474a82011-01-26 21:42:57 -0300793 set_bit(HCI_CONN_ENCRYPT_PEND, &hcon->pend);
Vinicius Costa Gomesf1cb9af2011-01-26 21:42:57 -0300794
Anderson Brigliaeb492e02011-06-09 18:50:40 -0300795 return 0;
796}
797
Vinicius Costa Gomes7034b912011-07-07 18:59:34 -0300798static int smp_cmd_encrypt_info(struct l2cap_conn *conn, struct sk_buff *skb)
799{
Brian Gixa68668b2011-08-11 15:49:36 -0700800 struct hci_conn *hcon = conn->hcon;
Vinicius Costa Gomes16b90832011-07-07 18:59:39 -0300801 struct smp_cmd_encrypt_info *rp = (void *) skb->data;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700802 u8 rand[8];
803 int err;
Vinicius Costa Gomes16b90832011-07-07 18:59:39 -0300804
805 skb_pull(skb, sizeof(*rp));
806
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700807 BT_DBG("conn %p", conn);
808
809 memset(rand, 0, sizeof(rand));
810
Brian Gixcf956772011-10-20 15:18:51 -0700811 err = hci_add_ltk(hcon->hdev, 0, conn->dst, hcon->dst_type,
812 0, 0, 0, rand, rp->ltk);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700813 if (err)
814 return SMP_UNSPECIFIED;
Vinicius Costa Gomes16b90832011-07-07 18:59:39 -0300815
Vinicius Costa Gomes7034b912011-07-07 18:59:34 -0300816 return 0;
817}
818
819static int smp_cmd_master_ident(struct l2cap_conn *conn, struct sk_buff *skb)
820{
Vinicius Costa Gomesc9839a12012-02-02 21:08:01 -0300821 struct hci_conn *hcon = conn->hcon;
Vinicius Costa Gomese56cede2011-07-07 18:59:39 -0300822 struct smp_cmd_master_ident *rp = (void *) skb->data;
Brian Gixa68668b2011-08-11 15:49:36 -0700823 struct smp_cmd_pairing *paircmd = (void *) &hcon->prsp[1];
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700824 struct link_key *key;
Brian Gixa68668b2011-08-11 15:49:36 -0700825 u8 *keydist;
Vinicius Costa Gomes7034b912011-07-07 18:59:34 -0300826
Vinicius Costa Gomes16b90832011-07-07 18:59:39 -0300827 skb_pull(skb, sizeof(*rp));
828
Brian Gixa68668b2011-08-11 15:49:36 -0700829 key = hci_find_link_key_type(hcon->hdev, conn->dst, KEY_TYPE_LTK);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700830 if (key == NULL)
831 return SMP_UNSPECIFIED;
832
Brian Gixa68668b2011-08-11 15:49:36 -0700833 if (hcon->out)
834 keydist = &paircmd->resp_key_dist;
835 else
836 keydist = &paircmd->init_key_dist;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700837
Brian Gixa68668b2011-08-11 15:49:36 -0700838 BT_DBG("keydist 0x%x", *keydist);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700839
Brian Gixcf956772011-10-20 15:18:51 -0700840 hci_add_ltk(hcon->hdev, 1, conn->dst, hcon->dst_type,
841 hcon->smp_key_size, hcon->auth, rp->ediv,
842 rp->rand, key->val);
Vinicius Costa Gomesc1d5e1d2011-07-07 18:59:34 -0300843
Brian Gixa68668b2011-08-11 15:49:36 -0700844 *keydist &= ~SMP_DIST_ENC_KEY;
845 if (hcon->out) {
846 if (!(*keydist))
847 smp_distribute_keys(conn, 1);
848 }
Vinicius Costa Gomes7034b912011-07-07 18:59:34 -0300849
850 return 0;
851}
852
Anderson Brigliaeb492e02011-06-09 18:50:40 -0300853int smp_sig_channel(struct l2cap_conn *conn, struct sk_buff *skb)
854{
Brian Gixa68668b2011-08-11 15:49:36 -0700855 struct hci_conn *hcon = conn->hcon;
Anderson Brigliaeb492e02011-06-09 18:50:40 -0300856 __u8 code = skb->data[0];
857 __u8 reason;
858 int err = 0;
859
Brian Gixa68668b2011-08-11 15:49:36 -0700860 if (IS_ERR(hcon->hdev->tfm)) {
861 err = PTR_ERR(hcon->hdev->tfm);
Andre Guedes2e65c9d2011-06-30 19:20:56 -0300862 reason = SMP_PAIRING_NOTSUPP;
Brian Gixa68668b2011-08-11 15:49:36 -0700863 BT_ERR("SMP_PAIRING_NOTSUPP %p", hcon->hdev->tfm);
Andre Guedes2e65c9d2011-06-30 19:20:56 -0300864 goto done;
865 }
866
Brian Gixa68668b2011-08-11 15:49:36 -0700867 hcon->smp_conn = conn;
Anderson Brigliaeb492e02011-06-09 18:50:40 -0300868 skb_pull(skb, sizeof(code));
869
870 switch (code) {
871 case SMP_CMD_PAIRING_REQ:
Vinicius Costa Gomesda85e5e2011-06-09 18:50:53 -0300872 reason = smp_cmd_pairing_req(conn, skb);
Anderson Brigliaeb492e02011-06-09 18:50:40 -0300873 break;
874
875 case SMP_CMD_PAIRING_FAIL:
Vinicius Costa Gomesda85e5e2011-06-09 18:50:53 -0300876 reason = 0;
877 err = -EPERM;
Brian Gixe9ceb522011-09-22 10:46:35 -0700878 del_timer(&hcon->smp_timer);
Brian Gix8d0b7d62011-10-12 15:12:42 -0700879 clear_bit(HCI_CONN_ENCRYPT_PEND, &hcon->pend);
Brian Gix570efc92011-10-13 15:59:51 -0700880 mgmt_auth_failed(hcon->hdev->id, conn->dst, skb->data[0]);
Brian Gix6d5fb8a2011-09-09 14:53:04 -0700881 hci_conn_put(hcon);
Anderson Brigliaeb492e02011-06-09 18:50:40 -0300882 break;
883
884 case SMP_CMD_PAIRING_RSP:
Vinicius Costa Gomesda85e5e2011-06-09 18:50:53 -0300885 reason = smp_cmd_pairing_rsp(conn, skb);
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300886 break;
887
888 case SMP_CMD_SECURITY_REQ:
Vinicius Costa Gomesda85e5e2011-06-09 18:50:53 -0300889 reason = smp_cmd_security_req(conn, skb);
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300890 break;
891
Anderson Brigliaeb492e02011-06-09 18:50:40 -0300892 case SMP_CMD_PAIRING_CONFIRM:
Vinicius Costa Gomesda85e5e2011-06-09 18:50:53 -0300893 reason = smp_cmd_pairing_confirm(conn, skb);
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300894 break;
895
Anderson Brigliaeb492e02011-06-09 18:50:40 -0300896 case SMP_CMD_PAIRING_RANDOM:
Vinicius Costa Gomesda85e5e2011-06-09 18:50:53 -0300897 reason = smp_cmd_pairing_random(conn, skb);
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300898 break;
899
Anderson Brigliaeb492e02011-06-09 18:50:40 -0300900 case SMP_CMD_ENCRYPT_INFO:
Vinicius Costa Gomes7034b912011-07-07 18:59:34 -0300901 reason = smp_cmd_encrypt_info(conn, skb);
902 break;
903
Anderson Brigliaeb492e02011-06-09 18:50:40 -0300904 case SMP_CMD_MASTER_IDENT:
Vinicius Costa Gomes7034b912011-07-07 18:59:34 -0300905 reason = smp_cmd_master_ident(conn, skb);
906 break;
907
Anderson Brigliaeb492e02011-06-09 18:50:40 -0300908 case SMP_CMD_IDENT_INFO:
909 case SMP_CMD_IDENT_ADDR_INFO:
910 case SMP_CMD_SIGN_INFO:
Vinicius Costa Gomes7034b912011-07-07 18:59:34 -0300911 /* Just ignored */
912 reason = 0;
913 break;
914
Anderson Brigliaeb492e02011-06-09 18:50:40 -0300915 default:
916 BT_DBG("Unknown command code 0x%2.2x", code);
917
918 reason = SMP_CMD_NOTSUPP;
Vinicius Costa Gomes3a0259b2011-06-09 18:50:43 -0300919 err = -EOPNOTSUPP;
920 goto done;
921 }
922
923done:
Brian Gixa68668b2011-08-11 15:49:36 -0700924 if (reason) {
925 BT_ERR("SMP_CMD_PAIRING_FAIL: %d", reason);
Anderson Briglia133e14c2011-06-09 18:50:40 -0300926 smp_send_cmd(conn, SMP_CMD_PAIRING_FAIL, sizeof(reason),
927 &reason);
Brian Gixe9ceb522011-09-22 10:46:35 -0700928 del_timer(&hcon->smp_timer);
Brian Gix8d0b7d62011-10-12 15:12:42 -0700929 clear_bit(HCI_CONN_ENCRYPT_PEND, &hcon->pend);
Brian Gix58ba0772011-09-23 13:40:16 -0700930 mgmt_auth_failed(hcon->hdev->id, conn->dst, reason);
Brian Gix6d5fb8a2011-09-09 14:53:04 -0700931 hci_conn_put(hcon);
Brian Gixa68668b2011-08-11 15:49:36 -0700932 }
Anderson Brigliaeb492e02011-06-09 18:50:40 -0300933
934 kfree_skb(skb);
935 return err;
936}
Vinicius Costa Gomes7034b912011-07-07 18:59:34 -0300937
Brian Gixa68668b2011-08-11 15:49:36 -0700938static int smp_distribute_keys(struct l2cap_conn *conn, __u8 force)
Vinicius Costa Gomes7034b912011-07-07 18:59:34 -0300939{
Brian Gixa68668b2011-08-11 15:49:36 -0700940 struct hci_conn *hcon = conn->hcon;
Vinicius Costa Gomes7034b912011-07-07 18:59:34 -0300941 struct smp_cmd_pairing *req, *rsp;
942 __u8 *keydist;
943
944 BT_DBG("conn %p force %d", conn, force);
945
Brian Gixa68668b2011-08-11 15:49:36 -0700946 if (IS_ERR(hcon->hdev->tfm))
947 return PTR_ERR(hcon->hdev->tfm);
Vinicius Costa Gomesd26a2342011-08-19 21:06:51 -0300948
Brian Gixa68668b2011-08-11 15:49:36 -0700949 rsp = (void *) &hcon->prsp[1];
Vinicius Costa Gomes7034b912011-07-07 18:59:34 -0300950
951 /* The responder sends its keys first */
Brian Gixa68668b2011-08-11 15:49:36 -0700952 if (!force && hcon->out && (rsp->resp_key_dist & 0x07))
Vinicius Costa Gomes7034b912011-07-07 18:59:34 -0300953 return 0;
954
Brian Gixa68668b2011-08-11 15:49:36 -0700955 req = (void *) &hcon->preq[1];
Vinicius Costa Gomes7034b912011-07-07 18:59:34 -0300956
Brian Gixa68668b2011-08-11 15:49:36 -0700957 if (hcon->out) {
Vinicius Costa Gomes7034b912011-07-07 18:59:34 -0300958 keydist = &rsp->init_key_dist;
959 *keydist &= req->init_key_dist;
960 } else {
961 keydist = &rsp->resp_key_dist;
962 *keydist &= req->resp_key_dist;
963 }
964
965
966 BT_DBG("keydist 0x%x", *keydist);
967
968 if (*keydist & SMP_DIST_ENC_KEY) {
969 struct smp_cmd_encrypt_info enc;
970 struct smp_cmd_master_ident ident;
971 __le16 ediv;
972
973 get_random_bytes(enc.ltk, sizeof(enc.ltk));
974 get_random_bytes(&ediv, sizeof(ediv));
975 get_random_bytes(ident.rand, sizeof(ident.rand));
976
977 smp_send_cmd(conn, SMP_CMD_ENCRYPT_INFO, sizeof(enc), &enc);
978
Brian Gixcf956772011-10-20 15:18:51 -0700979 hci_add_ltk(hcon->hdev, 1, conn->dst, hcon->dst_type,
980 hcon->smp_key_size, hcon->auth, ediv,
981 ident.rand, enc.ltk);
Vinicius Costa Gomes16b90832011-07-07 18:59:39 -0300982
Vinicius Costa Gomes7034b912011-07-07 18:59:34 -0300983 ident.ediv = cpu_to_le16(ediv);
984
985 smp_send_cmd(conn, SMP_CMD_MASTER_IDENT, sizeof(ident), &ident);
986
987 *keydist &= ~SMP_DIST_ENC_KEY;
988 }
989
990 if (*keydist & SMP_DIST_ID_KEY) {
991 struct smp_cmd_ident_addr_info addrinfo;
992 struct smp_cmd_ident_info idinfo;
993
994 /* Send a dummy key */
995 get_random_bytes(idinfo.irk, sizeof(idinfo.irk));
996
997 smp_send_cmd(conn, SMP_CMD_IDENT_INFO, sizeof(idinfo), &idinfo);
998
999 /* Just public address */
1000 memset(&addrinfo, 0, sizeof(addrinfo));
1001 bacpy(&addrinfo.bdaddr, conn->src);
1002
1003 smp_send_cmd(conn, SMP_CMD_IDENT_ADDR_INFO, sizeof(addrinfo),
1004 &addrinfo);
1005
1006 *keydist &= ~SMP_DIST_ID_KEY;
1007 }
1008
1009 if (*keydist & SMP_DIST_SIGN) {
1010 struct smp_cmd_sign_info sign;
1011
1012 /* Send a dummy key */
1013 get_random_bytes(sign.csrk, sizeof(sign.csrk));
1014
1015 smp_send_cmd(conn, SMP_CMD_SIGN_INFO, sizeof(sign), &sign);
1016
1017 *keydist &= ~SMP_DIST_SIGN;
1018 }
1019
Brian Gix2a335262011-11-17 12:59:23 -08001020 if (hcon->out) {
Brian Gixe57c1672011-09-13 12:34:59 -07001021 if (hcon->disconn_cfm_cb)
1022 hcon->disconn_cfm_cb(hcon, 0);
Brian Gixe9ceb522011-09-22 10:46:35 -07001023 del_timer(&hcon->smp_timer);
Brian Gix8d0b7d62011-10-12 15:12:42 -07001024 clear_bit(HCI_CONN_ENCRYPT_PEND, &hcon->pend);
Brian Gix2a335262011-11-17 12:59:23 -08001025 hci_conn_put(hcon);
1026 } else if (rsp->resp_key_dist) {
1027 if (hcon->disconn_cfm_cb)
1028 hcon->disconn_cfm_cb(hcon, SMP_UNSPECIFIED);
1029 clear_bit(HCI_CONN_ENCRYPT_PEND, &hcon->pend);
Brian Gix58ba0772011-09-23 13:40:16 -07001030 mgmt_auth_failed(hcon->hdev->id, conn->dst, SMP_UNSPECIFIED);
Brian Gix6d5fb8a2011-09-09 14:53:04 -07001031 hci_conn_put(hcon);
Vinicius Costa Gomesd26a2342011-08-19 21:06:51 -03001032 }
1033
Vinicius Costa Gomes7034b912011-07-07 18:59:34 -03001034 return 0;
1035}
Brian Gixa68668b2011-08-11 15:49:36 -07001036
1037int smp_link_encrypt_cmplt(struct l2cap_conn *conn, u8 status, u8 encrypt)
1038{
1039 struct hci_conn *hcon = conn->hcon;
1040
1041 BT_DBG("smp: %d %d %d", status, encrypt, hcon->sec_req);
1042
Brian Gix8d0b7d62011-10-12 15:12:42 -07001043 clear_bit(HCI_CONN_ENCRYPT_PEND, &hcon->pend);
1044
Brian Gix80fb3a92012-01-31 13:15:20 -08001045 if (!status && encrypt && hcon->sec_level < hcon->pending_sec_level)
1046 hcon->sec_level = hcon->pending_sec_level;
1047
Brian Gixa68668b2011-08-11 15:49:36 -07001048 if (!status && encrypt && !hcon->sec_req)
Brian Gix80fb3a92012-01-31 13:15:20 -08001049 return smp_distribute_keys(conn, 0);
Brian Gixa68668b2011-08-11 15:49:36 -07001050
1051 /* Fall back to Pairing request if failed a Link Security request */
1052 else if (hcon->sec_req && (status || !encrypt))
Brian Gix80fb3a92012-01-31 13:15:20 -08001053 smp_conn_security(conn, hcon->pending_sec_level);
Brian Gixa68668b2011-08-11 15:49:36 -07001054
Brian Gix80fb3a92012-01-31 13:15:20 -08001055 hci_conn_put(hcon);
Brian Gix8d0b7d62011-10-12 15:12:42 -07001056
Vinicius Costa Gomesc1d5e1d2011-07-07 18:59:34 -03001057 return 0;
1058}
Brian Gixe9ceb522011-09-22 10:46:35 -07001059
1060void smp_timeout(unsigned long arg)
1061{
1062 struct l2cap_conn *conn = (void *) arg;
1063 u8 reason = SMP_UNSPECIFIED;
1064
1065 BT_DBG("%p", conn);
1066
1067 smp_send_cmd(conn, SMP_CMD_PAIRING_FAIL, sizeof(reason), &reason);
Brian Gix8d0b7d62011-10-12 15:12:42 -07001068 clear_bit(HCI_CONN_ENCRYPT_PEND, &conn->hcon->pend);
Brian Gix58ba0772011-09-23 13:40:16 -07001069 mgmt_auth_failed(conn->hcon->hdev->id, conn->dst, SMP_UNSPECIFIED);
Brian Gixe9ceb522011-09-22 10:46:35 -07001070 hci_conn_put(conn->hcon);
1071}