blob: f99352d1aa4308bfa54296306189912b0a708b22 [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
Gustavo Padovan8c520a52012-05-23 04:04:22 -030023#include <linux/crypto.h>
24#include <linux/scatterlist.h>
25#include <crypto/b128ops.h>
26
Anderson Brigliaeb492e02011-06-09 18:50:40 -030027#include <net/bluetooth/bluetooth.h>
28#include <net/bluetooth/hci_core.h>
29#include <net/bluetooth/l2cap.h>
Brian Gix2b64d152011-12-21 16:12:12 -080030#include <net/bluetooth/mgmt.h>
Marcel Holtmannac4b7232013-10-10 14:54:16 -070031
32#include "smp.h"
Anderson Brigliad22ef0b2011-06-09 18:50:44 -030033
Marcel Holtmann17b02e62012-03-01 14:32:37 -080034#define SMP_TIMEOUT msecs_to_jiffies(30000)
Vinicius Costa Gomes5d3de7d2011-06-14 13:37:41 -030035
Johan Hedberg065a13e2012-10-11 16:26:06 +020036#define AUTH_REQ_MASK 0x07
37
Anderson Brigliad22ef0b2011-06-09 18:50:44 -030038static inline void swap128(u8 src[16], u8 dst[16])
39{
40 int i;
41 for (i = 0; i < 16; i++)
42 dst[15 - i] = src[i];
43}
44
45static inline void swap56(u8 src[7], u8 dst[7])
46{
47 int i;
48 for (i = 0; i < 7; i++)
49 dst[6 - i] = src[i];
50}
51
52static int smp_e(struct crypto_blkcipher *tfm, const u8 *k, u8 *r)
53{
54 struct blkcipher_desc desc;
55 struct scatterlist sg;
56 int err, iv_len;
57 unsigned char iv[128];
58
59 if (tfm == NULL) {
60 BT_ERR("tfm %p", tfm);
61 return -EINVAL;
62 }
63
64 desc.tfm = tfm;
65 desc.flags = 0;
66
67 err = crypto_blkcipher_setkey(tfm, k, 16);
68 if (err) {
69 BT_ERR("cipher setkey failed: %d", err);
70 return err;
71 }
72
73 sg_init_one(&sg, r, 16);
74
75 iv_len = crypto_blkcipher_ivsize(tfm);
76 if (iv_len) {
77 memset(&iv, 0xff, iv_len);
78 crypto_blkcipher_set_iv(tfm, iv, iv_len);
79 }
80
81 err = crypto_blkcipher_encrypt(&desc, &sg, &sg, 16);
82 if (err)
83 BT_ERR("Encrypt data error %d", err);
84
85 return err;
86}
87
88static int smp_c1(struct crypto_blkcipher *tfm, u8 k[16], u8 r[16],
Marcel Holtmannf1560462013-10-13 05:43:25 -070089 u8 preq[7], u8 pres[7], u8 _iat, bdaddr_t *ia,
90 u8 _rat, bdaddr_t *ra, u8 res[16])
Anderson Brigliad22ef0b2011-06-09 18:50:44 -030091{
92 u8 p1[16], p2[16];
93 int err;
94
95 memset(p1, 0, 16);
96
97 /* p1 = pres || preq || _rat || _iat */
98 swap56(pres, p1);
99 swap56(preq, p1 + 7);
100 p1[14] = _rat;
101 p1[15] = _iat;
102
103 memset(p2, 0, 16);
104
105 /* p2 = padding || ia || ra */
106 baswap((bdaddr_t *) (p2 + 4), ia);
107 baswap((bdaddr_t *) (p2 + 10), ra);
108
109 /* res = r XOR p1 */
110 u128_xor((u128 *) res, (u128 *) r, (u128 *) p1);
111
112 /* res = e(k, res) */
113 err = smp_e(tfm, k, res);
114 if (err) {
115 BT_ERR("Encrypt data error");
116 return err;
117 }
118
119 /* res = res XOR p2 */
120 u128_xor((u128 *) res, (u128 *) res, (u128 *) p2);
121
122 /* res = e(k, res) */
123 err = smp_e(tfm, k, res);
124 if (err)
125 BT_ERR("Encrypt data error");
126
127 return err;
128}
129
Marcel Holtmannf1560462013-10-13 05:43:25 -0700130static int smp_s1(struct crypto_blkcipher *tfm, u8 k[16], u8 r1[16],
131 u8 r2[16], u8 _r[16])
Anderson Brigliad22ef0b2011-06-09 18:50:44 -0300132{
133 int err;
134
135 /* Just least significant octets from r1 and r2 are considered */
136 memcpy(_r, r1 + 8, 8);
137 memcpy(_r + 8, r2 + 8, 8);
138
139 err = smp_e(tfm, k, _r);
140 if (err)
141 BT_ERR("Encrypt data error");
142
143 return err;
144}
145
146static int smp_rand(u8 *buf)
147{
148 get_random_bytes(buf, 16);
149
150 return 0;
151}
Anderson Brigliaeb492e02011-06-09 18:50:40 -0300152
153static struct sk_buff *smp_build_cmd(struct l2cap_conn *conn, u8 code,
Marcel Holtmannf1560462013-10-13 05:43:25 -0700154 u16 dlen, void *data)
Anderson Brigliaeb492e02011-06-09 18:50:40 -0300155{
156 struct sk_buff *skb;
157 struct l2cap_hdr *lh;
158 int len;
159
160 len = L2CAP_HDR_SIZE + sizeof(code) + dlen;
161
162 if (len > conn->mtu)
163 return NULL;
164
165 skb = bt_skb_alloc(len, GFP_ATOMIC);
166 if (!skb)
167 return NULL;
168
169 lh = (struct l2cap_hdr *) skb_put(skb, L2CAP_HDR_SIZE);
170 lh->len = cpu_to_le16(sizeof(code) + dlen);
Syam Sidhardhand8aece22012-10-10 22:09:28 +0530171 lh->cid = __constant_cpu_to_le16(L2CAP_CID_SMP);
Anderson Brigliaeb492e02011-06-09 18:50:40 -0300172
173 memcpy(skb_put(skb, sizeof(code)), &code, sizeof(code));
174
175 memcpy(skb_put(skb, dlen), data, dlen);
176
177 return skb;
178}
179
180static void smp_send_cmd(struct l2cap_conn *conn, u8 code, u16 len, void *data)
181{
182 struct sk_buff *skb = smp_build_cmd(conn, code, len, data);
183
184 BT_DBG("code 0x%2.2x", code);
185
186 if (!skb)
187 return;
188
Luiz Augusto von Dentz73d80de2011-11-02 15:52:01 +0200189 skb->priority = HCI_PRIO_MAX;
190 hci_send_acl(conn->hchan, skb, 0);
Vinicius Costa Gomese2dcd112011-08-19 21:06:50 -0300191
Gustavo F. Padovan6c9d42a2011-12-20 10:57:27 -0200192 cancel_delayed_work_sync(&conn->security_timer);
Marcel Holtmann17b02e62012-03-01 14:32:37 -0800193 schedule_delayed_work(&conn->security_timer, SMP_TIMEOUT);
Anderson Brigliaeb492e02011-06-09 18:50:40 -0300194}
195
Brian Gix2b64d152011-12-21 16:12:12 -0800196static __u8 authreq_to_seclevel(__u8 authreq)
197{
198 if (authreq & SMP_AUTH_MITM)
199 return BT_SECURITY_HIGH;
200 else
201 return BT_SECURITY_MEDIUM;
202}
203
204static __u8 seclevel_to_authreq(__u8 sec_level)
205{
206 switch (sec_level) {
207 case BT_SECURITY_HIGH:
208 return SMP_AUTH_MITM | SMP_AUTH_BONDING;
209 case BT_SECURITY_MEDIUM:
210 return SMP_AUTH_BONDING;
211 default:
212 return SMP_AUTH_NONE;
213 }
214}
215
Vinicius Costa Gomesb8e66ea2011-06-09 18:50:52 -0300216static void build_pairing_cmd(struct l2cap_conn *conn,
Marcel Holtmannf1560462013-10-13 05:43:25 -0700217 struct smp_cmd_pairing *req,
218 struct smp_cmd_pairing *rsp, __u8 authreq)
Vinicius Costa Gomesb8e66ea2011-06-09 18:50:52 -0300219{
Brian Gix2b64d152011-12-21 16:12:12 -0800220 u8 dist_keys = 0;
Vinicius Costa Gomes54790f72011-07-07 18:59:38 -0300221
Johan Hedberga8b2d5c2012-01-08 23:11:15 +0200222 if (test_bit(HCI_PAIRABLE, &conn->hcon->hdev->dev_flags)) {
Vinicius Costa Gomesca10b5e2011-08-25 20:02:37 -0300223 dist_keys = SMP_DIST_ENC_KEY;
Vinicius Costa Gomes54790f72011-07-07 18:59:38 -0300224 authreq |= SMP_AUTH_BONDING;
Brian Gix2b64d152011-12-21 16:12:12 -0800225 } else {
226 authreq &= ~SMP_AUTH_BONDING;
Vinicius Costa Gomes54790f72011-07-07 18:59:38 -0300227 }
228
229 if (rsp == NULL) {
230 req->io_capability = conn->hcon->io_capability;
231 req->oob_flag = SMP_OOB_NOT_PRESENT;
232 req->max_key_size = SMP_MAX_ENC_KEY_SIZE;
Brian Gix2b64d152011-12-21 16:12:12 -0800233 req->init_key_dist = 0;
Vinicius Costa Gomes54790f72011-07-07 18:59:38 -0300234 req->resp_key_dist = dist_keys;
Johan Hedberg065a13e2012-10-11 16:26:06 +0200235 req->auth_req = (authreq & AUTH_REQ_MASK);
Vinicius Costa Gomes54790f72011-07-07 18:59:38 -0300236 return;
237 }
238
239 rsp->io_capability = conn->hcon->io_capability;
240 rsp->oob_flag = SMP_OOB_NOT_PRESENT;
241 rsp->max_key_size = SMP_MAX_ENC_KEY_SIZE;
Brian Gix2b64d152011-12-21 16:12:12 -0800242 rsp->init_key_dist = 0;
Vinicius Costa Gomes54790f72011-07-07 18:59:38 -0300243 rsp->resp_key_dist = req->resp_key_dist & dist_keys;
Johan Hedberg065a13e2012-10-11 16:26:06 +0200244 rsp->auth_req = (authreq & AUTH_REQ_MASK);
Vinicius Costa Gomesb8e66ea2011-06-09 18:50:52 -0300245}
246
Vinicius Costa Gomes3158c502011-06-14 13:37:42 -0300247static u8 check_enc_key_size(struct l2cap_conn *conn, __u8 max_key_size)
248{
Vinicius Costa Gomes1c1def02011-09-05 14:31:30 -0300249 struct smp_chan *smp = conn->smp_chan;
250
Vinicius Costa Gomes3158c502011-06-14 13:37:42 -0300251 if ((max_key_size > SMP_MAX_ENC_KEY_SIZE) ||
Marcel Holtmannf1560462013-10-13 05:43:25 -0700252 (max_key_size < SMP_MIN_ENC_KEY_SIZE))
Vinicius Costa Gomes3158c502011-06-14 13:37:42 -0300253 return SMP_ENC_KEY_SIZE;
254
Vinicius Costa Gomesf7aa6112012-01-30 19:29:12 -0300255 smp->enc_key_size = max_key_size;
Vinicius Costa Gomes3158c502011-06-14 13:37:42 -0300256
257 return 0;
258}
259
Johan Hedberg84794e12013-11-06 11:24:57 +0200260static void smp_failure(struct l2cap_conn *conn, u8 reason)
Brian Gix4f957a72011-11-23 08:28:36 -0800261{
Johan Hedbergbab73cb2012-02-09 16:07:29 +0200262 struct hci_conn *hcon = conn->hcon;
263
Johan Hedberg84794e12013-11-06 11:24:57 +0200264 if (reason)
Brian Gix4f957a72011-11-23 08:28:36 -0800265 smp_send_cmd(conn, SMP_CMD_PAIRING_FAIL, sizeof(reason),
Marcel Holtmannf1560462013-10-13 05:43:25 -0700266 &reason);
Brian Gix4f957a72011-11-23 08:28:36 -0800267
Marcel Holtmannce39fb42013-10-13 02:23:39 -0700268 clear_bit(HCI_CONN_ENCRYPT_PEND, &hcon->flags);
269 mgmt_auth_failed(hcon->hdev, &hcon->dst, hcon->type, hcon->dst_type,
270 HCI_ERROR_AUTH_FAILURE);
Vinicius Costa Gomesf1c09c02012-02-01 18:27:56 -0300271
Andre Guedes61a0cfb2012-08-01 20:34:15 -0300272 cancel_delayed_work_sync(&conn->security_timer);
273
Marcel Holtmannce39fb42013-10-13 02:23:39 -0700274 if (test_and_clear_bit(HCI_CONN_LE_SMP_PEND, &hcon->flags))
Vinicius Costa Gomesf1c09c02012-02-01 18:27:56 -0300275 smp_chan_destroy(conn);
Brian Gix4f957a72011-11-23 08:28:36 -0800276}
277
Brian Gix2b64d152011-12-21 16:12:12 -0800278#define JUST_WORKS 0x00
279#define JUST_CFM 0x01
280#define REQ_PASSKEY 0x02
281#define CFM_PASSKEY 0x03
282#define REQ_OOB 0x04
283#define OVERLAP 0xFF
284
285static const u8 gen_method[5][5] = {
286 { JUST_WORKS, JUST_CFM, REQ_PASSKEY, JUST_WORKS, REQ_PASSKEY },
287 { JUST_WORKS, JUST_CFM, REQ_PASSKEY, JUST_WORKS, REQ_PASSKEY },
288 { CFM_PASSKEY, CFM_PASSKEY, REQ_PASSKEY, JUST_WORKS, CFM_PASSKEY },
289 { JUST_WORKS, JUST_CFM, JUST_WORKS, JUST_WORKS, JUST_CFM },
290 { CFM_PASSKEY, CFM_PASSKEY, REQ_PASSKEY, JUST_WORKS, OVERLAP },
291};
292
293static int tk_request(struct l2cap_conn *conn, u8 remote_oob, u8 auth,
294 u8 local_io, u8 remote_io)
295{
296 struct hci_conn *hcon = conn->hcon;
297 struct smp_chan *smp = conn->smp_chan;
298 u8 method;
299 u32 passkey = 0;
300 int ret = 0;
301
302 /* Initialize key for JUST WORKS */
303 memset(smp->tk, 0, sizeof(smp->tk));
304 clear_bit(SMP_FLAG_TK_VALID, &smp->smp_flags);
305
306 BT_DBG("tk_request: auth:%d lcl:%d rem:%d", auth, local_io, remote_io);
307
308 /* If neither side wants MITM, use JUST WORKS */
309 /* If either side has unknown io_caps, use JUST WORKS */
310 /* Otherwise, look up method from the table */
311 if (!(auth & SMP_AUTH_MITM) ||
Marcel Holtmannf1560462013-10-13 05:43:25 -0700312 local_io > SMP_IO_KEYBOARD_DISPLAY ||
313 remote_io > SMP_IO_KEYBOARD_DISPLAY)
Brian Gix2b64d152011-12-21 16:12:12 -0800314 method = JUST_WORKS;
315 else
Ido Yarivb3ff53f2012-03-05 20:07:08 +0200316 method = gen_method[remote_io][local_io];
Brian Gix2b64d152011-12-21 16:12:12 -0800317
318 /* If not bonding, don't ask user to confirm a Zero TK */
319 if (!(auth & SMP_AUTH_BONDING) && method == JUST_CFM)
320 method = JUST_WORKS;
321
322 /* If Just Works, Continue with Zero TK */
323 if (method == JUST_WORKS) {
324 set_bit(SMP_FLAG_TK_VALID, &smp->smp_flags);
325 return 0;
326 }
327
328 /* Not Just Works/Confirm results in MITM Authentication */
329 if (method != JUST_CFM)
330 set_bit(SMP_FLAG_MITM_AUTH, &smp->smp_flags);
331
332 /* If both devices have Keyoard-Display I/O, the master
333 * Confirms and the slave Enters the passkey.
334 */
335 if (method == OVERLAP) {
336 if (hcon->link_mode & HCI_LM_MASTER)
337 method = CFM_PASSKEY;
338 else
339 method = REQ_PASSKEY;
340 }
341
342 /* Generate random passkey. Not valid until confirmed. */
343 if (method == CFM_PASSKEY) {
344 u8 key[16];
345
346 memset(key, 0, sizeof(key));
347 get_random_bytes(&passkey, sizeof(passkey));
348 passkey %= 1000000;
349 put_unaligned_le32(passkey, key);
350 swap128(key, smp->tk);
351 BT_DBG("PassKey: %d", passkey);
352 }
353
354 hci_dev_lock(hcon->hdev);
355
356 if (method == REQ_PASSKEY)
Marcel Holtmannce39fb42013-10-13 02:23:39 -0700357 ret = mgmt_user_passkey_request(hcon->hdev, &hcon->dst,
Johan Hedberg272d90d2012-02-09 15:26:12 +0200358 hcon->type, hcon->dst_type);
Brian Gix2b64d152011-12-21 16:12:12 -0800359 else
Marcel Holtmannce39fb42013-10-13 02:23:39 -0700360 ret = mgmt_user_confirm_request(hcon->hdev, &hcon->dst,
Johan Hedberg272d90d2012-02-09 15:26:12 +0200361 hcon->type, hcon->dst_type,
Brian Gix2b64d152011-12-21 16:12:12 -0800362 cpu_to_le32(passkey), 0);
363
364 hci_dev_unlock(hcon->hdev);
365
366 return ret;
367}
368
Vinicius Costa Gomes8aab4752011-09-05 14:31:31 -0300369static void confirm_work(struct work_struct *work)
370{
371 struct smp_chan *smp = container_of(work, struct smp_chan, confirm);
372 struct l2cap_conn *conn = smp->conn;
373 struct crypto_blkcipher *tfm;
374 struct smp_cmd_pairing_confirm cp;
375 int ret;
376 u8 res[16], reason;
377
378 BT_DBG("conn %p", conn);
379
380 tfm = crypto_alloc_blkcipher("ecb(aes)", 0, CRYPTO_ALG_ASYNC);
381 if (IS_ERR(tfm)) {
382 reason = SMP_UNSPECIFIED;
383 goto error;
384 }
385
386 smp->tfm = tfm;
387
388 if (conn->hcon->out)
Marcel Holtmannc8462ca2013-10-13 05:24:02 -0700389 ret = smp_c1(tfm, smp->tk, smp->prnd, smp->preq, smp->prsp,
390 conn->hcon->src_type, &conn->hcon->src,
391 conn->hcon->dst_type, &conn->hcon->dst, res);
Vinicius Costa Gomes8aab4752011-09-05 14:31:31 -0300392 else
393 ret = smp_c1(tfm, smp->tk, smp->prnd, smp->preq, smp->prsp,
Marcel Holtmannc8462ca2013-10-13 05:24:02 -0700394 conn->hcon->dst_type, &conn->hcon->dst,
395 conn->hcon->src_type, &conn->hcon->src, res);
Vinicius Costa Gomes8aab4752011-09-05 14:31:31 -0300396 if (ret) {
397 reason = SMP_UNSPECIFIED;
398 goto error;
399 }
400
Brian Gix2b64d152011-12-21 16:12:12 -0800401 clear_bit(SMP_FLAG_CFM_PENDING, &smp->smp_flags);
402
Vinicius Costa Gomes8aab4752011-09-05 14:31:31 -0300403 swap128(res, cp.confirm_val);
404 smp_send_cmd(smp->conn, SMP_CMD_PAIRING_CONFIRM, sizeof(cp), &cp);
405
406 return;
407
408error:
Johan Hedberg84794e12013-11-06 11:24:57 +0200409 smp_failure(conn, reason);
Vinicius Costa Gomes8aab4752011-09-05 14:31:31 -0300410}
411
412static void random_work(struct work_struct *work)
413{
414 struct smp_chan *smp = container_of(work, struct smp_chan, random);
415 struct l2cap_conn *conn = smp->conn;
416 struct hci_conn *hcon = conn->hcon;
417 struct crypto_blkcipher *tfm = smp->tfm;
418 u8 reason, confirm[16], res[16], key[16];
419 int ret;
420
421 if (IS_ERR_OR_NULL(tfm)) {
422 reason = SMP_UNSPECIFIED;
423 goto error;
424 }
425
426 BT_DBG("conn %p %s", conn, conn->hcon->out ? "master" : "slave");
427
428 if (hcon->out)
Marcel Holtmannc8462ca2013-10-13 05:24:02 -0700429 ret = smp_c1(tfm, smp->tk, smp->rrnd, smp->preq, smp->prsp,
430 hcon->src_type, &hcon->src,
431 hcon->dst_type, &hcon->dst, res);
Vinicius Costa Gomes8aab4752011-09-05 14:31:31 -0300432 else
433 ret = smp_c1(tfm, smp->tk, smp->rrnd, smp->preq, smp->prsp,
Marcel Holtmannc8462ca2013-10-13 05:24:02 -0700434 hcon->dst_type, &hcon->dst,
435 hcon->src_type, &hcon->src, res);
Vinicius Costa Gomes8aab4752011-09-05 14:31:31 -0300436 if (ret) {
437 reason = SMP_UNSPECIFIED;
438 goto error;
439 }
440
441 swap128(res, confirm);
442
443 if (memcmp(smp->pcnf, confirm, sizeof(smp->pcnf)) != 0) {
444 BT_ERR("Pairing failed (confirmation values mismatch)");
445 reason = SMP_CONFIRM_FAILED;
446 goto error;
447 }
448
449 if (hcon->out) {
450 u8 stk[16], rand[8];
451 __le16 ediv;
452
453 memset(rand, 0, sizeof(rand));
454 ediv = 0;
455
456 smp_s1(tfm, smp->tk, smp->rrnd, smp->prnd, key);
457 swap128(key, stk);
458
Vinicius Costa Gomesf7aa6112012-01-30 19:29:12 -0300459 memset(stk + smp->enc_key_size, 0,
Gustavo F. Padovan04124682012-03-08 01:25:00 -0300460 SMP_MAX_ENC_KEY_SIZE - smp->enc_key_size);
Vinicius Costa Gomes8aab4752011-09-05 14:31:31 -0300461
Johan Hedberg51a8efd2012-01-16 06:10:31 +0200462 if (test_and_set_bit(HCI_CONN_ENCRYPT_PEND, &hcon->flags)) {
Vinicius Costa Gomes8aab4752011-09-05 14:31:31 -0300463 reason = SMP_UNSPECIFIED;
464 goto error;
465 }
466
467 hci_le_start_enc(hcon, ediv, rand, stk);
Vinicius Costa Gomesf7aa6112012-01-30 19:29:12 -0300468 hcon->enc_key_size = smp->enc_key_size;
Vinicius Costa Gomes8aab4752011-09-05 14:31:31 -0300469 } else {
470 u8 stk[16], r[16], rand[8];
471 __le16 ediv;
472
473 memset(rand, 0, sizeof(rand));
474 ediv = 0;
475
476 swap128(smp->prnd, r);
477 smp_send_cmd(conn, SMP_CMD_PAIRING_RANDOM, sizeof(r), r);
478
479 smp_s1(tfm, smp->tk, smp->prnd, smp->rrnd, key);
480 swap128(key, stk);
481
Vinicius Costa Gomesf7aa6112012-01-30 19:29:12 -0300482 memset(stk + smp->enc_key_size, 0,
Marcel Holtmannf1560462013-10-13 05:43:25 -0700483 SMP_MAX_ENC_KEY_SIZE - smp->enc_key_size);
Vinicius Costa Gomes8aab4752011-09-05 14:31:31 -0300484
Marcel Holtmannce39fb42013-10-13 02:23:39 -0700485 hci_add_ltk(hcon->hdev, &hcon->dst, hcon->dst_type,
Gustavo F. Padovan04124682012-03-08 01:25:00 -0300486 HCI_SMP_STK_SLAVE, 0, 0, stk, smp->enc_key_size,
487 ediv, rand);
Vinicius Costa Gomes8aab4752011-09-05 14:31:31 -0300488 }
489
490 return;
491
492error:
Johan Hedberg84794e12013-11-06 11:24:57 +0200493 smp_failure(conn, reason);
Vinicius Costa Gomes8aab4752011-09-05 14:31:31 -0300494}
495
496static struct smp_chan *smp_chan_create(struct l2cap_conn *conn)
497{
498 struct smp_chan *smp;
499
Marcel Holtmannf1560462013-10-13 05:43:25 -0700500 smp = kzalloc(sizeof(*smp), GFP_ATOMIC);
Vinicius Costa Gomes8aab4752011-09-05 14:31:31 -0300501 if (!smp)
502 return NULL;
503
504 INIT_WORK(&smp->confirm, confirm_work);
505 INIT_WORK(&smp->random, random_work);
506
507 smp->conn = conn;
508 conn->smp_chan = smp;
Brian Gix2b64d152011-12-21 16:12:12 -0800509 conn->hcon->smp_conn = conn;
Vinicius Costa Gomes8aab4752011-09-05 14:31:31 -0300510
511 hci_conn_hold(conn->hcon);
512
513 return smp;
514}
515
516void smp_chan_destroy(struct l2cap_conn *conn)
517{
Brian Gixc8eb9692011-11-23 08:28:35 -0800518 struct smp_chan *smp = conn->smp_chan;
519
Vinicius Costa Gomesf1c09c02012-02-01 18:27:56 -0300520 BUG_ON(!smp);
Brian Gixc8eb9692011-11-23 08:28:35 -0800521
522 if (smp->tfm)
523 crypto_free_blkcipher(smp->tfm);
524
525 kfree(smp);
526 conn->smp_chan = NULL;
Brian Gix2b64d152011-12-21 16:12:12 -0800527 conn->hcon->smp_conn = NULL;
David Herrmann76a68ba2013-04-06 20:28:37 +0200528 hci_conn_drop(conn->hcon);
Vinicius Costa Gomes8aab4752011-09-05 14:31:31 -0300529}
530
Brian Gix2b64d152011-12-21 16:12:12 -0800531int smp_user_confirm_reply(struct hci_conn *hcon, u16 mgmt_op, __le32 passkey)
532{
533 struct l2cap_conn *conn = hcon->smp_conn;
534 struct smp_chan *smp;
535 u32 value;
536 u8 key[16];
537
538 BT_DBG("");
539
540 if (!conn)
541 return -ENOTCONN;
542
543 smp = conn->smp_chan;
544
545 switch (mgmt_op) {
546 case MGMT_OP_USER_PASSKEY_REPLY:
547 value = le32_to_cpu(passkey);
548 memset(key, 0, sizeof(key));
549 BT_DBG("PassKey: %d", value);
550 put_unaligned_le32(value, key);
551 swap128(key, smp->tk);
552 /* Fall Through */
553 case MGMT_OP_USER_CONFIRM_REPLY:
554 set_bit(SMP_FLAG_TK_VALID, &smp->smp_flags);
555 break;
556 case MGMT_OP_USER_PASSKEY_NEG_REPLY:
557 case MGMT_OP_USER_CONFIRM_NEG_REPLY:
Johan Hedberg84794e12013-11-06 11:24:57 +0200558 smp_failure(conn, SMP_PASSKEY_ENTRY_FAILED);
Brian Gix2b64d152011-12-21 16:12:12 -0800559 return 0;
560 default:
Johan Hedberg84794e12013-11-06 11:24:57 +0200561 smp_failure(conn, SMP_PASSKEY_ENTRY_FAILED);
Brian Gix2b64d152011-12-21 16:12:12 -0800562 return -EOPNOTSUPP;
563 }
564
565 /* If it is our turn to send Pairing Confirm, do so now */
566 if (test_bit(SMP_FLAG_CFM_PENDING, &smp->smp_flags))
567 queue_work(hcon->hdev->workqueue, &smp->confirm);
568
569 return 0;
570}
571
Vinicius Costa Gomesda85e5e2011-06-09 18:50:53 -0300572static u8 smp_cmd_pairing_req(struct l2cap_conn *conn, struct sk_buff *skb)
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300573{
Vinicius Costa Gomes3158c502011-06-14 13:37:42 -0300574 struct smp_cmd_pairing rsp, *req = (void *) skb->data;
Vinicius Costa Gomes8aab4752011-09-05 14:31:31 -0300575 struct smp_chan *smp;
Vinicius Costa Gomes3158c502011-06-14 13:37:42 -0300576 u8 key_size;
Brian Gix2b64d152011-12-21 16:12:12 -0800577 u8 auth = SMP_AUTH_NONE;
Vinicius Costa Gomes8aab4752011-09-05 14:31:31 -0300578 int ret;
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300579
580 BT_DBG("conn %p", conn);
581
Brian Gix2b64d152011-12-21 16:12:12 -0800582 if (conn->hcon->link_mode & HCI_LM_MASTER)
583 return SMP_CMD_NOTSUPP;
584
Johan Hedberg51a8efd2012-01-16 06:10:31 +0200585 if (!test_and_set_bit(HCI_CONN_LE_SMP_PEND, &conn->hcon->flags))
Vinicius Costa Gomes8aab4752011-09-05 14:31:31 -0300586 smp = smp_chan_create(conn);
Andrei Emeltchenkod08fd0e2012-07-19 17:03:43 +0300587 else
588 smp = conn->smp_chan;
Vinicius Costa Gomes8aab4752011-09-05 14:31:31 -0300589
Andrei Emeltchenkod08fd0e2012-07-19 17:03:43 +0300590 if (!smp)
591 return SMP_UNSPECIFIED;
Vinicius Costa Gomesd26a2342011-08-19 21:06:51 -0300592
Vinicius Costa Gomes1c1def02011-09-05 14:31:30 -0300593 smp->preq[0] = SMP_CMD_PAIRING_REQ;
594 memcpy(&smp->preq[1], req, sizeof(*req));
Vinicius Costa Gomes3158c502011-06-14 13:37:42 -0300595 skb_pull(skb, sizeof(*req));
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300596
Brian Gix2b64d152011-12-21 16:12:12 -0800597 /* We didn't start the pairing, so match remote */
598 if (req->auth_req & SMP_AUTH_BONDING)
599 auth = req->auth_req;
Vinicius Costa Gomesda85e5e2011-06-09 18:50:53 -0300600
Ido Yarivfdde0a22012-03-05 20:09:38 +0200601 conn->hcon->pending_sec_level = authreq_to_seclevel(auth);
602
Brian Gix2b64d152011-12-21 16:12:12 -0800603 build_pairing_cmd(conn, req, &rsp, auth);
Vinicius Costa Gomes3158c502011-06-14 13:37:42 -0300604
605 key_size = min(req->max_key_size, rsp.max_key_size);
606 if (check_enc_key_size(conn, key_size))
607 return SMP_ENC_KEY_SIZE;
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300608
Vinicius Costa Gomes8aab4752011-09-05 14:31:31 -0300609 ret = smp_rand(smp->prnd);
610 if (ret)
611 return SMP_UNSPECIFIED;
612
Vinicius Costa Gomes1c1def02011-09-05 14:31:30 -0300613 smp->prsp[0] = SMP_CMD_PAIRING_RSP;
614 memcpy(&smp->prsp[1], &rsp, sizeof(rsp));
Anderson Brigliaf01ead32011-06-09 18:50:45 -0300615
Vinicius Costa Gomes3158c502011-06-14 13:37:42 -0300616 smp_send_cmd(conn, SMP_CMD_PAIRING_RSP, sizeof(rsp), &rsp);
Vinicius Costa Gomesda85e5e2011-06-09 18:50:53 -0300617
Brian Gix2b64d152011-12-21 16:12:12 -0800618 /* Request setup of TK */
619 ret = tk_request(conn, 0, auth, rsp.io_capability, req->io_capability);
620 if (ret)
621 return SMP_UNSPECIFIED;
622
Vinicius Costa Gomesda85e5e2011-06-09 18:50:53 -0300623 return 0;
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300624}
625
Vinicius Costa Gomesda85e5e2011-06-09 18:50:53 -0300626static u8 smp_cmd_pairing_rsp(struct l2cap_conn *conn, struct sk_buff *skb)
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300627{
Vinicius Costa Gomes3158c502011-06-14 13:37:42 -0300628 struct smp_cmd_pairing *req, *rsp = (void *) skb->data;
Vinicius Costa Gomes1c1def02011-09-05 14:31:30 -0300629 struct smp_chan *smp = conn->smp_chan;
Vinicius Costa Gomes8aab4752011-09-05 14:31:31 -0300630 struct hci_dev *hdev = conn->hcon->hdev;
Brian Gix2b64d152011-12-21 16:12:12 -0800631 u8 key_size, auth = SMP_AUTH_NONE;
Anderson Briglia7d24ddc2011-06-09 18:50:46 -0300632 int ret;
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300633
634 BT_DBG("conn %p", conn);
635
Brian Gix2b64d152011-12-21 16:12:12 -0800636 if (!(conn->hcon->link_mode & HCI_LM_MASTER))
637 return SMP_CMD_NOTSUPP;
638
Vinicius Costa Gomes3158c502011-06-14 13:37:42 -0300639 skb_pull(skb, sizeof(*rsp));
Vinicius Costa Gomesda85e5e2011-06-09 18:50:53 -0300640
Vinicius Costa Gomes1c1def02011-09-05 14:31:30 -0300641 req = (void *) &smp->preq[1];
Vinicius Costa Gomes3158c502011-06-14 13:37:42 -0300642
643 key_size = min(req->max_key_size, rsp->max_key_size);
644 if (check_enc_key_size(conn, key_size))
645 return SMP_ENC_KEY_SIZE;
646
Vinicius Costa Gomes1c1def02011-09-05 14:31:30 -0300647 ret = smp_rand(smp->prnd);
Anderson Briglia7d24ddc2011-06-09 18:50:46 -0300648 if (ret)
Vinicius Costa Gomesda85e5e2011-06-09 18:50:53 -0300649 return SMP_UNSPECIFIED;
Anderson Briglia7d24ddc2011-06-09 18:50:46 -0300650
Vinicius Costa Gomes8aab4752011-09-05 14:31:31 -0300651 smp->prsp[0] = SMP_CMD_PAIRING_RSP;
652 memcpy(&smp->prsp[1], rsp, sizeof(*rsp));
Anderson Briglia7d24ddc2011-06-09 18:50:46 -0300653
Brian Gix2b64d152011-12-21 16:12:12 -0800654 if ((req->auth_req & SMP_AUTH_BONDING) &&
Marcel Holtmannf1560462013-10-13 05:43:25 -0700655 (rsp->auth_req & SMP_AUTH_BONDING))
Brian Gix2b64d152011-12-21 16:12:12 -0800656 auth = SMP_AUTH_BONDING;
657
658 auth |= (req->auth_req | rsp->auth_req) & SMP_AUTH_MITM;
659
Johan Hedberg476585e2012-06-06 18:54:15 +0800660 ret = tk_request(conn, 0, auth, req->io_capability, rsp->io_capability);
Brian Gix2b64d152011-12-21 16:12:12 -0800661 if (ret)
662 return SMP_UNSPECIFIED;
663
664 set_bit(SMP_FLAG_CFM_PENDING, &smp->smp_flags);
665
666 /* Can't compose response until we have been confirmed */
667 if (!test_bit(SMP_FLAG_TK_VALID, &smp->smp_flags))
668 return 0;
669
Vinicius Costa Gomes8aab4752011-09-05 14:31:31 -0300670 queue_work(hdev->workqueue, &smp->confirm);
Vinicius Costa Gomesda85e5e2011-06-09 18:50:53 -0300671
672 return 0;
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300673}
674
Vinicius Costa Gomesda85e5e2011-06-09 18:50:53 -0300675static u8 smp_cmd_pairing_confirm(struct l2cap_conn *conn, struct sk_buff *skb)
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300676{
Vinicius Costa Gomes1c1def02011-09-05 14:31:30 -0300677 struct smp_chan *smp = conn->smp_chan;
Vinicius Costa Gomes8aab4752011-09-05 14:31:31 -0300678 struct hci_dev *hdev = conn->hcon->hdev;
Anderson Briglia7d24ddc2011-06-09 18:50:46 -0300679
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300680 BT_DBG("conn %p %s", conn, conn->hcon->out ? "master" : "slave");
681
Vinicius Costa Gomes1c1def02011-09-05 14:31:30 -0300682 memcpy(smp->pcnf, skb->data, sizeof(smp->pcnf));
683 skb_pull(skb, sizeof(smp->pcnf));
Anderson Briglia7d24ddc2011-06-09 18:50:46 -0300684
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300685 if (conn->hcon->out) {
Anderson Briglia7d24ddc2011-06-09 18:50:46 -0300686 u8 random[16];
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300687
Vinicius Costa Gomes1c1def02011-09-05 14:31:30 -0300688 swap128(smp->prnd, random);
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300689 smp_send_cmd(conn, SMP_CMD_PAIRING_RANDOM, sizeof(random),
Marcel Holtmannf1560462013-10-13 05:43:25 -0700690 random);
Brian Gix2b64d152011-12-21 16:12:12 -0800691 } else if (test_bit(SMP_FLAG_TK_VALID, &smp->smp_flags)) {
Vinicius Costa Gomes8aab4752011-09-05 14:31:31 -0300692 queue_work(hdev->workqueue, &smp->confirm);
Brian Gix2b64d152011-12-21 16:12:12 -0800693 } else {
694 set_bit(SMP_FLAG_CFM_PENDING, &smp->smp_flags);
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300695 }
Vinicius Costa Gomesda85e5e2011-06-09 18:50:53 -0300696
697 return 0;
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300698}
699
Vinicius Costa Gomesda85e5e2011-06-09 18:50:53 -0300700static u8 smp_cmd_pairing_random(struct l2cap_conn *conn, struct sk_buff *skb)
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300701{
Vinicius Costa Gomes1c1def02011-09-05 14:31:30 -0300702 struct smp_chan *smp = conn->smp_chan;
Vinicius Costa Gomes8aab4752011-09-05 14:31:31 -0300703 struct hci_dev *hdev = conn->hcon->hdev;
Anderson Briglia7d24ddc2011-06-09 18:50:46 -0300704
Vinicius Costa Gomes8aab4752011-09-05 14:31:31 -0300705 BT_DBG("conn %p", conn);
Anderson Briglia7d24ddc2011-06-09 18:50:46 -0300706
Vinicius Costa Gomes8aab4752011-09-05 14:31:31 -0300707 swap128(skb->data, smp->rrnd);
708 skb_pull(skb, sizeof(smp->rrnd));
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300709
Vinicius Costa Gomes8aab4752011-09-05 14:31:31 -0300710 queue_work(hdev->workqueue, &smp->random);
Vinicius Costa Gomesda85e5e2011-06-09 18:50:53 -0300711
712 return 0;
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300713}
714
Johan Hedberg4dab7862012-06-07 14:58:37 +0800715static u8 smp_ltk_encrypt(struct l2cap_conn *conn, u8 sec_level)
Vinicius Costa Gomes988c5992011-08-25 20:02:28 -0300716{
Vinicius Costa Gomesc9839a12012-02-02 21:08:01 -0300717 struct smp_ltk *key;
Vinicius Costa Gomes988c5992011-08-25 20:02:28 -0300718 struct hci_conn *hcon = conn->hcon;
719
Marcel Holtmannce39fb42013-10-13 02:23:39 -0700720 key = hci_find_ltk_by_addr(hcon->hdev, &hcon->dst, hcon->dst_type);
Vinicius Costa Gomes988c5992011-08-25 20:02:28 -0300721 if (!key)
722 return 0;
723
Johan Hedberg4dab7862012-06-07 14:58:37 +0800724 if (sec_level > BT_SECURITY_MEDIUM && !key->authenticated)
725 return 0;
726
Johan Hedberg51a8efd2012-01-16 06:10:31 +0200727 if (test_and_set_bit(HCI_CONN_ENCRYPT_PEND, &hcon->flags))
Vinicius Costa Gomes988c5992011-08-25 20:02:28 -0300728 return 1;
729
Vinicius Costa Gomesc9839a12012-02-02 21:08:01 -0300730 hci_le_start_enc(hcon, key->ediv, key->rand, key->val);
731 hcon->enc_key_size = key->enc_size;
Vinicius Costa Gomes988c5992011-08-25 20:02:28 -0300732
733 return 1;
Vinicius Costa Gomes988c5992011-08-25 20:02:28 -0300734}
Marcel Holtmannf1560462013-10-13 05:43:25 -0700735
Vinicius Costa Gomesda85e5e2011-06-09 18:50:53 -0300736static u8 smp_cmd_security_req(struct l2cap_conn *conn, struct sk_buff *skb)
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300737{
738 struct smp_cmd_security_req *rp = (void *) skb->data;
739 struct smp_cmd_pairing cp;
Vinicius Costa Gomesf1cb9af2011-01-26 21:42:57 -0300740 struct hci_conn *hcon = conn->hcon;
Vinicius Costa Gomes8aab4752011-09-05 14:31:31 -0300741 struct smp_chan *smp;
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300742
743 BT_DBG("conn %p", conn);
744
Johan Hedberg86ca9ea2013-11-05 11:30:39 +0200745 if (!(conn->hcon->link_mode & HCI_LM_MASTER))
746 return SMP_CMD_NOTSUPP;
747
Brian Gix2b64d152011-12-21 16:12:12 -0800748 hcon->pending_sec_level = authreq_to_seclevel(rp->auth_req);
Vinicius Costa Gomesfeb45eb2011-08-25 20:02:35 -0300749
Johan Hedberg4dab7862012-06-07 14:58:37 +0800750 if (smp_ltk_encrypt(conn, hcon->pending_sec_level))
Vinicius Costa Gomes988c5992011-08-25 20:02:28 -0300751 return 0;
752
Johan Hedberg51a8efd2012-01-16 06:10:31 +0200753 if (test_and_set_bit(HCI_CONN_LE_SMP_PEND, &hcon->flags))
Vinicius Costa Gomesda85e5e2011-06-09 18:50:53 -0300754 return 0;
Vinicius Costa Gomesf1cb9af2011-01-26 21:42:57 -0300755
Vinicius Costa Gomes8aab4752011-09-05 14:31:31 -0300756 smp = smp_chan_create(conn);
Vinicius Costa Gomesd26a2342011-08-19 21:06:51 -0300757
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300758 skb_pull(skb, sizeof(*rp));
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300759
Vinicius Costa Gomesda85e5e2011-06-09 18:50:53 -0300760 memset(&cp, 0, sizeof(cp));
Vinicius Costa Gomes54790f72011-07-07 18:59:38 -0300761 build_pairing_cmd(conn, &cp, NULL, rp->auth_req);
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300762
Vinicius Costa Gomes1c1def02011-09-05 14:31:30 -0300763 smp->preq[0] = SMP_CMD_PAIRING_REQ;
764 memcpy(&smp->preq[1], &cp, sizeof(cp));
Anderson Brigliaf01ead32011-06-09 18:50:45 -0300765
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300766 smp_send_cmd(conn, SMP_CMD_PAIRING_REQ, sizeof(cp), &cp);
Vinicius Costa Gomesf1cb9af2011-01-26 21:42:57 -0300767
Vinicius Costa Gomesda85e5e2011-06-09 18:50:53 -0300768 return 0;
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300769}
770
Vinicius Costa Gomescc110922012-08-23 21:32:43 -0300771int smp_conn_security(struct hci_conn *hcon, __u8 sec_level)
Anderson Brigliaeb492e02011-06-09 18:50:40 -0300772{
Vinicius Costa Gomescc110922012-08-23 21:32:43 -0300773 struct l2cap_conn *conn = hcon->l2cap_data;
Vinicius Costa Gomes1c1def02011-09-05 14:31:30 -0300774 struct smp_chan *smp = conn->smp_chan;
Brian Gix2b64d152011-12-21 16:12:12 -0800775 __u8 authreq;
Anderson Brigliaeb492e02011-06-09 18:50:40 -0300776
Vinicius Costa Gomes3a0259b2011-06-09 18:50:43 -0300777 BT_DBG("conn %p hcon %p level 0x%2.2x", conn, hcon, sec_level);
778
Johan Hedberg757aee02013-04-24 13:05:32 +0300779 if (!test_bit(HCI_LE_ENABLED, &hcon->hdev->dev_flags))
Andre Guedes2e65c9d2011-06-30 19:20:56 -0300780 return 1;
781
Vinicius Costa Gomesf1cb9af2011-01-26 21:42:57 -0300782 if (sec_level == BT_SECURITY_LOW)
Anderson Brigliaeb492e02011-06-09 18:50:40 -0300783 return 1;
Vinicius Costa Gomesf1cb9af2011-01-26 21:42:57 -0300784
785 if (hcon->sec_level >= sec_level)
786 return 1;
787
Vinicius Costa Gomes988c5992011-08-25 20:02:28 -0300788 if (hcon->link_mode & HCI_LM_MASTER)
Johan Hedberg4dab7862012-06-07 14:58:37 +0800789 if (smp_ltk_encrypt(conn, sec_level))
Vinicius Costa Gomes02bc7452011-07-07 18:59:41 -0300790 goto done;
Vinicius Costa Gomesd26a2342011-08-19 21:06:51 -0300791
Johan Hedberg51a8efd2012-01-16 06:10:31 +0200792 if (test_and_set_bit(HCI_CONN_LE_SMP_PEND, &hcon->flags))
Vinicius Costa Gomesd26a2342011-08-19 21:06:51 -0300793 return 0;
794
Vinicius Costa Gomes8aab4752011-09-05 14:31:31 -0300795 smp = smp_chan_create(conn);
Brian Gix2b64d152011-12-21 16:12:12 -0800796 if (!smp)
797 return 1;
798
799 authreq = seclevel_to_authreq(sec_level);
Vinicius Costa Gomesd26a2342011-08-19 21:06:51 -0300800
Vinicius Costa Gomesd26a2342011-08-19 21:06:51 -0300801 if (hcon->link_mode & HCI_LM_MASTER) {
802 struct smp_cmd_pairing cp;
Anderson Brigliaf01ead32011-06-09 18:50:45 -0300803
Brian Gix2b64d152011-12-21 16:12:12 -0800804 build_pairing_cmd(conn, &cp, NULL, authreq);
Vinicius Costa Gomes1c1def02011-09-05 14:31:30 -0300805 smp->preq[0] = SMP_CMD_PAIRING_REQ;
806 memcpy(&smp->preq[1], &cp, sizeof(cp));
Anderson Brigliaf01ead32011-06-09 18:50:45 -0300807
Anderson Brigliaeb492e02011-06-09 18:50:40 -0300808 smp_send_cmd(conn, SMP_CMD_PAIRING_REQ, sizeof(cp), &cp);
809 } else {
810 struct smp_cmd_security_req cp;
Brian Gix2b64d152011-12-21 16:12:12 -0800811 cp.auth_req = authreq;
Anderson Brigliaeb492e02011-06-09 18:50:40 -0300812 smp_send_cmd(conn, SMP_CMD_SECURITY_REQ, sizeof(cp), &cp);
813 }
814
Vinicius Costa Gomes02bc7452011-07-07 18:59:41 -0300815done:
Vinicius Costa Gomesf1cb9af2011-01-26 21:42:57 -0300816 hcon->pending_sec_level = sec_level;
Vinicius Costa Gomesf1cb9af2011-01-26 21:42:57 -0300817
Anderson Brigliaeb492e02011-06-09 18:50:40 -0300818 return 0;
819}
820
Vinicius Costa Gomes7034b912011-07-07 18:59:34 -0300821static int smp_cmd_encrypt_info(struct l2cap_conn *conn, struct sk_buff *skb)
822{
Vinicius Costa Gomes16b90832011-07-07 18:59:39 -0300823 struct smp_cmd_encrypt_info *rp = (void *) skb->data;
Vinicius Costa Gomes1c1def02011-09-05 14:31:30 -0300824 struct smp_chan *smp = conn->smp_chan;
Vinicius Costa Gomes16b90832011-07-07 18:59:39 -0300825
826 skb_pull(skb, sizeof(*rp));
827
Vinicius Costa Gomes1c1def02011-09-05 14:31:30 -0300828 memcpy(smp->tk, rp->ltk, sizeof(smp->tk));
Vinicius Costa Gomes16b90832011-07-07 18:59:39 -0300829
Vinicius Costa Gomes7034b912011-07-07 18:59:34 -0300830 return 0;
831}
832
833static int smp_cmd_master_ident(struct l2cap_conn *conn, struct sk_buff *skb)
834{
Vinicius Costa Gomes16b90832011-07-07 18:59:39 -0300835 struct smp_cmd_master_ident *rp = (void *) skb->data;
Vinicius Costa Gomes1c1def02011-09-05 14:31:30 -0300836 struct smp_chan *smp = conn->smp_chan;
Vinicius Costa Gomesc9839a12012-02-02 21:08:01 -0300837 struct hci_dev *hdev = conn->hcon->hdev;
838 struct hci_conn *hcon = conn->hcon;
839 u8 authenticated;
Vinicius Costa Gomes7034b912011-07-07 18:59:34 -0300840
Vinicius Costa Gomes16b90832011-07-07 18:59:39 -0300841 skb_pull(skb, sizeof(*rp));
842
Vinicius Costa Gomesc9839a12012-02-02 21:08:01 -0300843 hci_dev_lock(hdev);
Marcel Holtmannce39fb42013-10-13 02:23:39 -0700844 authenticated = (hcon->sec_level == BT_SECURITY_HIGH);
845 hci_add_ltk(hdev, &hcon->dst, hcon->dst_type, HCI_SMP_LTK, 1,
846 authenticated, smp->tk, smp->enc_key_size,
Gustavo F. Padovan04124682012-03-08 01:25:00 -0300847 rp->ediv, rp->rand);
Vinicius Costa Gomes7034b912011-07-07 18:59:34 -0300848 smp_distribute_keys(conn, 1);
Vinicius Costa Gomesc9839a12012-02-02 21:08:01 -0300849 hci_dev_unlock(hdev);
Vinicius Costa Gomes7034b912011-07-07 18:59:34 -0300850
851 return 0;
852}
853
Anderson Brigliaeb492e02011-06-09 18:50:40 -0300854int smp_sig_channel(struct l2cap_conn *conn, struct sk_buff *skb)
855{
Marcel Holtmann7b9899d2013-10-03 00:00:57 -0700856 struct hci_conn *hcon = conn->hcon;
Marcel Holtmann92381f52013-10-03 01:23:08 -0700857 __u8 code, reason;
Anderson Brigliaeb492e02011-06-09 18:50:40 -0300858 int err = 0;
859
Marcel Holtmann7b9899d2013-10-03 00:00:57 -0700860 if (hcon->type != LE_LINK) {
861 kfree_skb(skb);
Johan Hedberg34327112013-10-16 11:37:01 +0300862 return 0;
Marcel Holtmann7b9899d2013-10-03 00:00:57 -0700863 }
864
Marcel Holtmann92381f52013-10-03 01:23:08 -0700865 if (skb->len < 1) {
866 kfree_skb(skb);
867 return -EILSEQ;
868 }
869
Marcel Holtmann06ae3312013-10-18 03:43:00 -0700870 if (!test_bit(HCI_LE_ENABLED, &hcon->hdev->dev_flags)) {
Andre Guedes2e65c9d2011-06-30 19:20:56 -0300871 err = -ENOTSUPP;
872 reason = SMP_PAIRING_NOTSUPP;
873 goto done;
874 }
875
Marcel Holtmann92381f52013-10-03 01:23:08 -0700876 code = skb->data[0];
Anderson Brigliaeb492e02011-06-09 18:50:40 -0300877 skb_pull(skb, sizeof(code));
878
Johan Hedberg8cf9fa12013-01-29 10:44:23 -0600879 /*
880 * The SMP context must be initialized for all other PDUs except
881 * pairing and security requests. If we get any other PDU when
882 * not initialized simply disconnect (done if this function
883 * returns an error).
884 */
885 if (code != SMP_CMD_PAIRING_REQ && code != SMP_CMD_SECURITY_REQ &&
886 !conn->smp_chan) {
887 BT_ERR("Unexpected SMP command 0x%02x. Disconnecting.", code);
888 kfree_skb(skb);
889 return -ENOTSUPP;
890 }
891
Anderson Brigliaeb492e02011-06-09 18:50:40 -0300892 switch (code) {
893 case SMP_CMD_PAIRING_REQ:
Vinicius Costa Gomesda85e5e2011-06-09 18:50:53 -0300894 reason = smp_cmd_pairing_req(conn, skb);
Anderson Brigliaeb492e02011-06-09 18:50:40 -0300895 break;
896
897 case SMP_CMD_PAIRING_FAIL:
Johan Hedberg84794e12013-11-06 11:24:57 +0200898 smp_failure(conn, 0);
Vinicius Costa Gomesda85e5e2011-06-09 18:50:53 -0300899 reason = 0;
900 err = -EPERM;
Anderson Brigliaeb492e02011-06-09 18:50:40 -0300901 break;
902
903 case SMP_CMD_PAIRING_RSP:
Vinicius Costa Gomesda85e5e2011-06-09 18:50:53 -0300904 reason = smp_cmd_pairing_rsp(conn, skb);
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300905 break;
906
907 case SMP_CMD_SECURITY_REQ:
Vinicius Costa Gomesda85e5e2011-06-09 18:50:53 -0300908 reason = smp_cmd_security_req(conn, skb);
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300909 break;
910
Anderson Brigliaeb492e02011-06-09 18:50:40 -0300911 case SMP_CMD_PAIRING_CONFIRM:
Vinicius Costa Gomesda85e5e2011-06-09 18:50:53 -0300912 reason = smp_cmd_pairing_confirm(conn, skb);
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300913 break;
914
Anderson Brigliaeb492e02011-06-09 18:50:40 -0300915 case SMP_CMD_PAIRING_RANDOM:
Vinicius Costa Gomesda85e5e2011-06-09 18:50:53 -0300916 reason = smp_cmd_pairing_random(conn, skb);
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300917 break;
918
Anderson Brigliaeb492e02011-06-09 18:50:40 -0300919 case SMP_CMD_ENCRYPT_INFO:
Vinicius Costa Gomes7034b912011-07-07 18:59:34 -0300920 reason = smp_cmd_encrypt_info(conn, skb);
921 break;
922
Anderson Brigliaeb492e02011-06-09 18:50:40 -0300923 case SMP_CMD_MASTER_IDENT:
Vinicius Costa Gomes7034b912011-07-07 18:59:34 -0300924 reason = smp_cmd_master_ident(conn, skb);
925 break;
926
Anderson Brigliaeb492e02011-06-09 18:50:40 -0300927 case SMP_CMD_IDENT_INFO:
928 case SMP_CMD_IDENT_ADDR_INFO:
929 case SMP_CMD_SIGN_INFO:
Vinicius Costa Gomes7034b912011-07-07 18:59:34 -0300930 /* Just ignored */
931 reason = 0;
932 break;
933
Anderson Brigliaeb492e02011-06-09 18:50:40 -0300934 default:
935 BT_DBG("Unknown command code 0x%2.2x", code);
936
937 reason = SMP_CMD_NOTSUPP;
Vinicius Costa Gomes3a0259b2011-06-09 18:50:43 -0300938 err = -EOPNOTSUPP;
939 goto done;
940 }
941
942done:
943 if (reason)
Johan Hedberg84794e12013-11-06 11:24:57 +0200944 smp_failure(conn, reason);
Anderson Brigliaeb492e02011-06-09 18:50:40 -0300945
946 kfree_skb(skb);
947 return err;
948}
Vinicius Costa Gomes7034b912011-07-07 18:59:34 -0300949
950int smp_distribute_keys(struct l2cap_conn *conn, __u8 force)
951{
952 struct smp_cmd_pairing *req, *rsp;
Vinicius Costa Gomes1c1def02011-09-05 14:31:30 -0300953 struct smp_chan *smp = conn->smp_chan;
Vinicius Costa Gomes7034b912011-07-07 18:59:34 -0300954 __u8 *keydist;
955
956 BT_DBG("conn %p force %d", conn, force);
957
Johan Hedberg51a8efd2012-01-16 06:10:31 +0200958 if (!test_bit(HCI_CONN_LE_SMP_PEND, &conn->hcon->flags))
Vinicius Costa Gomesd26a2342011-08-19 21:06:51 -0300959 return 0;
960
Vinicius Costa Gomes1c1def02011-09-05 14:31:30 -0300961 rsp = (void *) &smp->prsp[1];
Vinicius Costa Gomes7034b912011-07-07 18:59:34 -0300962
963 /* The responder sends its keys first */
964 if (!force && conn->hcon->out && (rsp->resp_key_dist & 0x07))
965 return 0;
966
Vinicius Costa Gomes1c1def02011-09-05 14:31:30 -0300967 req = (void *) &smp->preq[1];
Vinicius Costa Gomes7034b912011-07-07 18:59:34 -0300968
969 if (conn->hcon->out) {
970 keydist = &rsp->init_key_dist;
971 *keydist &= req->init_key_dist;
972 } else {
973 keydist = &rsp->resp_key_dist;
974 *keydist &= req->resp_key_dist;
975 }
976
977
978 BT_DBG("keydist 0x%x", *keydist);
979
980 if (*keydist & SMP_DIST_ENC_KEY) {
981 struct smp_cmd_encrypt_info enc;
982 struct smp_cmd_master_ident ident;
Vinicius Costa Gomesc9839a12012-02-02 21:08:01 -0300983 struct hci_conn *hcon = conn->hcon;
984 u8 authenticated;
Vinicius Costa Gomes7034b912011-07-07 18:59:34 -0300985 __le16 ediv;
986
987 get_random_bytes(enc.ltk, sizeof(enc.ltk));
988 get_random_bytes(&ediv, sizeof(ediv));
989 get_random_bytes(ident.rand, sizeof(ident.rand));
990
991 smp_send_cmd(conn, SMP_CMD_ENCRYPT_INFO, sizeof(enc), &enc);
992
Vinicius Costa Gomesc9839a12012-02-02 21:08:01 -0300993 authenticated = hcon->sec_level == BT_SECURITY_HIGH;
Marcel Holtmannce39fb42013-10-13 02:23:39 -0700994 hci_add_ltk(hcon->hdev, &hcon->dst, hcon->dst_type,
Gustavo F. Padovan04124682012-03-08 01:25:00 -0300995 HCI_SMP_LTK_SLAVE, 1, authenticated,
996 enc.ltk, smp->enc_key_size, ediv, ident.rand);
Vinicius Costa Gomes16b90832011-07-07 18:59:39 -0300997
Andrei Emeltchenko58115372012-03-12 12:13:06 +0200998 ident.ediv = ediv;
Vinicius Costa Gomes7034b912011-07-07 18:59:34 -0300999
1000 smp_send_cmd(conn, SMP_CMD_MASTER_IDENT, sizeof(ident), &ident);
1001
1002 *keydist &= ~SMP_DIST_ENC_KEY;
1003 }
1004
1005 if (*keydist & SMP_DIST_ID_KEY) {
1006 struct smp_cmd_ident_addr_info addrinfo;
1007 struct smp_cmd_ident_info idinfo;
1008
1009 /* Send a dummy key */
1010 get_random_bytes(idinfo.irk, sizeof(idinfo.irk));
1011
1012 smp_send_cmd(conn, SMP_CMD_IDENT_INFO, sizeof(idinfo), &idinfo);
1013
1014 /* Just public address */
1015 memset(&addrinfo, 0, sizeof(addrinfo));
Marcel Holtmann2b36a562013-10-13 05:24:00 -07001016 bacpy(&addrinfo.bdaddr, &conn->hcon->src);
Vinicius Costa Gomes7034b912011-07-07 18:59:34 -03001017
1018 smp_send_cmd(conn, SMP_CMD_IDENT_ADDR_INFO, sizeof(addrinfo),
Marcel Holtmannf1560462013-10-13 05:43:25 -07001019 &addrinfo);
Vinicius Costa Gomes7034b912011-07-07 18:59:34 -03001020
1021 *keydist &= ~SMP_DIST_ID_KEY;
1022 }
1023
1024 if (*keydist & SMP_DIST_SIGN) {
1025 struct smp_cmd_sign_info sign;
1026
1027 /* Send a dummy key */
1028 get_random_bytes(sign.csrk, sizeof(sign.csrk));
1029
1030 smp_send_cmd(conn, SMP_CMD_SIGN_INFO, sizeof(sign), &sign);
1031
1032 *keydist &= ~SMP_DIST_SIGN;
1033 }
1034
Vinicius Costa Gomesd26a2342011-08-19 21:06:51 -03001035 if (conn->hcon->out || force) {
Johan Hedberg51a8efd2012-01-16 06:10:31 +02001036 clear_bit(HCI_CONN_LE_SMP_PEND, &conn->hcon->flags);
Gustavo F. Padovan6c9d42a2011-12-20 10:57:27 -02001037 cancel_delayed_work_sync(&conn->security_timer);
Vinicius Costa Gomes8aab4752011-09-05 14:31:31 -03001038 smp_chan_destroy(conn);
Vinicius Costa Gomesd26a2342011-08-19 21:06:51 -03001039 }
1040
Vinicius Costa Gomes7034b912011-07-07 18:59:34 -03001041 return 0;
1042}