blob: 5f500b479f45ead68a28cc1853923b83997d77e0 [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;
Johan Hedberg201a5922013-12-02 10:49:04 +020056 int err;
Anderson Brigliad22ef0b2011-06-09 18:50:44 -030057
58 if (tfm == NULL) {
59 BT_ERR("tfm %p", tfm);
60 return -EINVAL;
61 }
62
63 desc.tfm = tfm;
64 desc.flags = 0;
65
66 err = crypto_blkcipher_setkey(tfm, k, 16);
67 if (err) {
68 BT_ERR("cipher setkey failed: %d", err);
69 return err;
70 }
71
72 sg_init_one(&sg, r, 16);
73
Anderson Brigliad22ef0b2011-06-09 18:50:44 -030074 err = crypto_blkcipher_encrypt(&desc, &sg, &sg, 16);
75 if (err)
76 BT_ERR("Encrypt data error %d", err);
77
78 return err;
79}
80
Johan Hedberg60478052014-02-18 10:19:31 +020081static int smp_ah(struct crypto_blkcipher *tfm, u8 irk[16], u8 r[3], u8 res[3])
82{
83 u8 _res[16], k[16];
84 int err;
85
86 /* r' = padding || r */
87 memset(_res, 0, 13);
88 _res[13] = r[2];
89 _res[14] = r[1];
90 _res[15] = r[0];
91
92 swap128(irk, k);
93 err = smp_e(tfm, k, _res);
94 if (err) {
95 BT_ERR("Encrypt error");
96 return err;
97 }
98
99 /* The output of the random address function ah is:
100 * ah(h, r) = e(k, r') mod 2^24
101 * The output of the security function e is then truncated to 24 bits
102 * by taking the least significant 24 bits of the output of e as the
103 * result of ah.
104 */
105 res[0] = _res[15];
106 res[1] = _res[14];
107 res[2] = _res[13];
108
109 return 0;
110}
111
112bool smp_irk_matches(struct crypto_blkcipher *tfm, u8 irk[16],
113 bdaddr_t *bdaddr)
114{
115 u8 hash[3];
116 int err;
117
118 BT_DBG("RPA %pMR IRK %*phN", bdaddr, 16, irk);
119
120 err = smp_ah(tfm, irk, &bdaddr->b[3], hash);
121 if (err)
122 return false;
123
124 return !memcmp(bdaddr->b, hash, 3);
125}
126
Anderson Brigliad22ef0b2011-06-09 18:50:44 -0300127static int smp_c1(struct crypto_blkcipher *tfm, u8 k[16], u8 r[16],
Marcel Holtmannf1560462013-10-13 05:43:25 -0700128 u8 preq[7], u8 pres[7], u8 _iat, bdaddr_t *ia,
129 u8 _rat, bdaddr_t *ra, u8 res[16])
Anderson Brigliad22ef0b2011-06-09 18:50:44 -0300130{
131 u8 p1[16], p2[16];
132 int err;
133
134 memset(p1, 0, 16);
135
136 /* p1 = pres || preq || _rat || _iat */
137 swap56(pres, p1);
138 swap56(preq, p1 + 7);
139 p1[14] = _rat;
140 p1[15] = _iat;
141
142 memset(p2, 0, 16);
143
144 /* p2 = padding || ia || ra */
145 baswap((bdaddr_t *) (p2 + 4), ia);
146 baswap((bdaddr_t *) (p2 + 10), ra);
147
148 /* res = r XOR p1 */
149 u128_xor((u128 *) res, (u128 *) r, (u128 *) p1);
150
151 /* res = e(k, res) */
152 err = smp_e(tfm, k, res);
153 if (err) {
154 BT_ERR("Encrypt data error");
155 return err;
156 }
157
158 /* res = res XOR p2 */
159 u128_xor((u128 *) res, (u128 *) res, (u128 *) p2);
160
161 /* res = e(k, res) */
162 err = smp_e(tfm, k, res);
163 if (err)
164 BT_ERR("Encrypt data error");
165
166 return err;
167}
168
Marcel Holtmannf1560462013-10-13 05:43:25 -0700169static int smp_s1(struct crypto_blkcipher *tfm, u8 k[16], u8 r1[16],
170 u8 r2[16], u8 _r[16])
Anderson Brigliad22ef0b2011-06-09 18:50:44 -0300171{
172 int err;
173
174 /* Just least significant octets from r1 and r2 are considered */
175 memcpy(_r, r1 + 8, 8);
176 memcpy(_r + 8, r2 + 8, 8);
177
178 err = smp_e(tfm, k, _r);
179 if (err)
180 BT_ERR("Encrypt data error");
181
182 return err;
183}
184
Anderson Brigliaeb492e02011-06-09 18:50:40 -0300185static struct sk_buff *smp_build_cmd(struct l2cap_conn *conn, u8 code,
Marcel Holtmannf1560462013-10-13 05:43:25 -0700186 u16 dlen, void *data)
Anderson Brigliaeb492e02011-06-09 18:50:40 -0300187{
188 struct sk_buff *skb;
189 struct l2cap_hdr *lh;
190 int len;
191
192 len = L2CAP_HDR_SIZE + sizeof(code) + dlen;
193
194 if (len > conn->mtu)
195 return NULL;
196
197 skb = bt_skb_alloc(len, GFP_ATOMIC);
198 if (!skb)
199 return NULL;
200
201 lh = (struct l2cap_hdr *) skb_put(skb, L2CAP_HDR_SIZE);
202 lh->len = cpu_to_le16(sizeof(code) + dlen);
Syam Sidhardhand8aece22012-10-10 22:09:28 +0530203 lh->cid = __constant_cpu_to_le16(L2CAP_CID_SMP);
Anderson Brigliaeb492e02011-06-09 18:50:40 -0300204
205 memcpy(skb_put(skb, sizeof(code)), &code, sizeof(code));
206
207 memcpy(skb_put(skb, dlen), data, dlen);
208
209 return skb;
210}
211
212static void smp_send_cmd(struct l2cap_conn *conn, u8 code, u16 len, void *data)
213{
214 struct sk_buff *skb = smp_build_cmd(conn, code, len, data);
215
216 BT_DBG("code 0x%2.2x", code);
217
218 if (!skb)
219 return;
220
Luiz Augusto von Dentz73d80de2011-11-02 15:52:01 +0200221 skb->priority = HCI_PRIO_MAX;
222 hci_send_acl(conn->hchan, skb, 0);
Vinicius Costa Gomese2dcd112011-08-19 21:06:50 -0300223
Gustavo F. Padovan6c9d42a2011-12-20 10:57:27 -0200224 cancel_delayed_work_sync(&conn->security_timer);
Marcel Holtmann17b02e62012-03-01 14:32:37 -0800225 schedule_delayed_work(&conn->security_timer, SMP_TIMEOUT);
Anderson Brigliaeb492e02011-06-09 18:50:40 -0300226}
227
Brian Gix2b64d152011-12-21 16:12:12 -0800228static __u8 authreq_to_seclevel(__u8 authreq)
229{
230 if (authreq & SMP_AUTH_MITM)
231 return BT_SECURITY_HIGH;
232 else
233 return BT_SECURITY_MEDIUM;
234}
235
236static __u8 seclevel_to_authreq(__u8 sec_level)
237{
238 switch (sec_level) {
239 case BT_SECURITY_HIGH:
240 return SMP_AUTH_MITM | SMP_AUTH_BONDING;
241 case BT_SECURITY_MEDIUM:
242 return SMP_AUTH_BONDING;
243 default:
244 return SMP_AUTH_NONE;
245 }
246}
247
Vinicius Costa Gomesb8e66ea2011-06-09 18:50:52 -0300248static void build_pairing_cmd(struct l2cap_conn *conn,
Marcel Holtmannf1560462013-10-13 05:43:25 -0700249 struct smp_cmd_pairing *req,
250 struct smp_cmd_pairing *rsp, __u8 authreq)
Vinicius Costa Gomesb8e66ea2011-06-09 18:50:52 -0300251{
Brian Gix2b64d152011-12-21 16:12:12 -0800252 u8 dist_keys = 0;
Vinicius Costa Gomes54790f72011-07-07 18:59:38 -0300253
Johan Hedberga8b2d5c2012-01-08 23:11:15 +0200254 if (test_bit(HCI_PAIRABLE, &conn->hcon->hdev->dev_flags)) {
Vinicius Costa Gomesca10b5e2011-08-25 20:02:37 -0300255 dist_keys = SMP_DIST_ENC_KEY;
Vinicius Costa Gomes54790f72011-07-07 18:59:38 -0300256 authreq |= SMP_AUTH_BONDING;
Brian Gix2b64d152011-12-21 16:12:12 -0800257 } else {
258 authreq &= ~SMP_AUTH_BONDING;
Vinicius Costa Gomes54790f72011-07-07 18:59:38 -0300259 }
260
261 if (rsp == NULL) {
262 req->io_capability = conn->hcon->io_capability;
263 req->oob_flag = SMP_OOB_NOT_PRESENT;
264 req->max_key_size = SMP_MAX_ENC_KEY_SIZE;
Johan Hedberg0cf73b92014-01-29 13:55:59 -0800265 req->init_key_dist = dist_keys;
Vinicius Costa Gomes54790f72011-07-07 18:59:38 -0300266 req->resp_key_dist = dist_keys;
Johan Hedberg065a13e2012-10-11 16:26:06 +0200267 req->auth_req = (authreq & AUTH_REQ_MASK);
Vinicius Costa Gomes54790f72011-07-07 18:59:38 -0300268 return;
269 }
270
271 rsp->io_capability = conn->hcon->io_capability;
272 rsp->oob_flag = SMP_OOB_NOT_PRESENT;
273 rsp->max_key_size = SMP_MAX_ENC_KEY_SIZE;
Johan Hedberg0cf73b92014-01-29 13:55:59 -0800274 rsp->init_key_dist = req->init_key_dist & dist_keys;
Vinicius Costa Gomes54790f72011-07-07 18:59:38 -0300275 rsp->resp_key_dist = req->resp_key_dist & dist_keys;
Johan Hedberg065a13e2012-10-11 16:26:06 +0200276 rsp->auth_req = (authreq & AUTH_REQ_MASK);
Vinicius Costa Gomesb8e66ea2011-06-09 18:50:52 -0300277}
278
Vinicius Costa Gomes3158c502011-06-14 13:37:42 -0300279static u8 check_enc_key_size(struct l2cap_conn *conn, __u8 max_key_size)
280{
Vinicius Costa Gomes1c1def02011-09-05 14:31:30 -0300281 struct smp_chan *smp = conn->smp_chan;
282
Vinicius Costa Gomes3158c502011-06-14 13:37:42 -0300283 if ((max_key_size > SMP_MAX_ENC_KEY_SIZE) ||
Marcel Holtmannf1560462013-10-13 05:43:25 -0700284 (max_key_size < SMP_MIN_ENC_KEY_SIZE))
Vinicius Costa Gomes3158c502011-06-14 13:37:42 -0300285 return SMP_ENC_KEY_SIZE;
286
Vinicius Costa Gomesf7aa6112012-01-30 19:29:12 -0300287 smp->enc_key_size = max_key_size;
Vinicius Costa Gomes3158c502011-06-14 13:37:42 -0300288
289 return 0;
290}
291
Johan Hedberg84794e12013-11-06 11:24:57 +0200292static void smp_failure(struct l2cap_conn *conn, u8 reason)
Brian Gix4f957a72011-11-23 08:28:36 -0800293{
Johan Hedbergbab73cb2012-02-09 16:07:29 +0200294 struct hci_conn *hcon = conn->hcon;
295
Johan Hedberg84794e12013-11-06 11:24:57 +0200296 if (reason)
Brian Gix4f957a72011-11-23 08:28:36 -0800297 smp_send_cmd(conn, SMP_CMD_PAIRING_FAIL, sizeof(reason),
Marcel Holtmannf1560462013-10-13 05:43:25 -0700298 &reason);
Brian Gix4f957a72011-11-23 08:28:36 -0800299
Marcel Holtmannce39fb42013-10-13 02:23:39 -0700300 clear_bit(HCI_CONN_ENCRYPT_PEND, &hcon->flags);
301 mgmt_auth_failed(hcon->hdev, &hcon->dst, hcon->type, hcon->dst_type,
302 HCI_ERROR_AUTH_FAILURE);
Vinicius Costa Gomesf1c09c02012-02-01 18:27:56 -0300303
Andre Guedes61a0cfb2012-08-01 20:34:15 -0300304 cancel_delayed_work_sync(&conn->security_timer);
305
Marcel Holtmannce39fb42013-10-13 02:23:39 -0700306 if (test_and_clear_bit(HCI_CONN_LE_SMP_PEND, &hcon->flags))
Vinicius Costa Gomesf1c09c02012-02-01 18:27:56 -0300307 smp_chan_destroy(conn);
Brian Gix4f957a72011-11-23 08:28:36 -0800308}
309
Brian Gix2b64d152011-12-21 16:12:12 -0800310#define JUST_WORKS 0x00
311#define JUST_CFM 0x01
312#define REQ_PASSKEY 0x02
313#define CFM_PASSKEY 0x03
314#define REQ_OOB 0x04
315#define OVERLAP 0xFF
316
317static const u8 gen_method[5][5] = {
318 { JUST_WORKS, JUST_CFM, REQ_PASSKEY, JUST_WORKS, REQ_PASSKEY },
319 { JUST_WORKS, JUST_CFM, REQ_PASSKEY, JUST_WORKS, REQ_PASSKEY },
320 { CFM_PASSKEY, CFM_PASSKEY, REQ_PASSKEY, JUST_WORKS, CFM_PASSKEY },
321 { JUST_WORKS, JUST_CFM, JUST_WORKS, JUST_WORKS, JUST_CFM },
322 { CFM_PASSKEY, CFM_PASSKEY, REQ_PASSKEY, JUST_WORKS, OVERLAP },
323};
324
325static int tk_request(struct l2cap_conn *conn, u8 remote_oob, u8 auth,
326 u8 local_io, u8 remote_io)
327{
328 struct hci_conn *hcon = conn->hcon;
329 struct smp_chan *smp = conn->smp_chan;
330 u8 method;
331 u32 passkey = 0;
332 int ret = 0;
333
334 /* Initialize key for JUST WORKS */
335 memset(smp->tk, 0, sizeof(smp->tk));
336 clear_bit(SMP_FLAG_TK_VALID, &smp->smp_flags);
337
338 BT_DBG("tk_request: auth:%d lcl:%d rem:%d", auth, local_io, remote_io);
339
340 /* If neither side wants MITM, use JUST WORKS */
341 /* If either side has unknown io_caps, use JUST WORKS */
342 /* Otherwise, look up method from the table */
343 if (!(auth & SMP_AUTH_MITM) ||
Marcel Holtmannf1560462013-10-13 05:43:25 -0700344 local_io > SMP_IO_KEYBOARD_DISPLAY ||
345 remote_io > SMP_IO_KEYBOARD_DISPLAY)
Brian Gix2b64d152011-12-21 16:12:12 -0800346 method = JUST_WORKS;
347 else
Ido Yarivb3ff53f2012-03-05 20:07:08 +0200348 method = gen_method[remote_io][local_io];
Brian Gix2b64d152011-12-21 16:12:12 -0800349
350 /* If not bonding, don't ask user to confirm a Zero TK */
351 if (!(auth & SMP_AUTH_BONDING) && method == JUST_CFM)
352 method = JUST_WORKS;
353
354 /* If Just Works, Continue with Zero TK */
355 if (method == JUST_WORKS) {
356 set_bit(SMP_FLAG_TK_VALID, &smp->smp_flags);
357 return 0;
358 }
359
360 /* Not Just Works/Confirm results in MITM Authentication */
361 if (method != JUST_CFM)
362 set_bit(SMP_FLAG_MITM_AUTH, &smp->smp_flags);
363
364 /* If both devices have Keyoard-Display I/O, the master
365 * Confirms and the slave Enters the passkey.
366 */
367 if (method == OVERLAP) {
368 if (hcon->link_mode & HCI_LM_MASTER)
369 method = CFM_PASSKEY;
370 else
371 method = REQ_PASSKEY;
372 }
373
374 /* Generate random passkey. Not valid until confirmed. */
375 if (method == CFM_PASSKEY) {
376 u8 key[16];
377
378 memset(key, 0, sizeof(key));
379 get_random_bytes(&passkey, sizeof(passkey));
380 passkey %= 1000000;
381 put_unaligned_le32(passkey, key);
382 swap128(key, smp->tk);
383 BT_DBG("PassKey: %d", passkey);
384 }
385
386 hci_dev_lock(hcon->hdev);
387
388 if (method == REQ_PASSKEY)
Marcel Holtmannce39fb42013-10-13 02:23:39 -0700389 ret = mgmt_user_passkey_request(hcon->hdev, &hcon->dst,
Johan Hedberg272d90d2012-02-09 15:26:12 +0200390 hcon->type, hcon->dst_type);
Brian Gix2b64d152011-12-21 16:12:12 -0800391 else
Marcel Holtmannce39fb42013-10-13 02:23:39 -0700392 ret = mgmt_user_confirm_request(hcon->hdev, &hcon->dst,
Johan Hedberg272d90d2012-02-09 15:26:12 +0200393 hcon->type, hcon->dst_type,
Brian Gix2b64d152011-12-21 16:12:12 -0800394 cpu_to_le32(passkey), 0);
395
396 hci_dev_unlock(hcon->hdev);
397
398 return ret;
399}
400
Vinicius Costa Gomes8aab4752011-09-05 14:31:31 -0300401static void confirm_work(struct work_struct *work)
402{
403 struct smp_chan *smp = container_of(work, struct smp_chan, confirm);
404 struct l2cap_conn *conn = smp->conn;
405 struct crypto_blkcipher *tfm;
406 struct smp_cmd_pairing_confirm cp;
407 int ret;
408 u8 res[16], reason;
409
410 BT_DBG("conn %p", conn);
411
412 tfm = crypto_alloc_blkcipher("ecb(aes)", 0, CRYPTO_ALG_ASYNC);
413 if (IS_ERR(tfm)) {
414 reason = SMP_UNSPECIFIED;
415 goto error;
416 }
417
418 smp->tfm = tfm;
419
420 if (conn->hcon->out)
Marcel Holtmannc8462ca2013-10-13 05:24:02 -0700421 ret = smp_c1(tfm, smp->tk, smp->prnd, smp->preq, smp->prsp,
422 conn->hcon->src_type, &conn->hcon->src,
423 conn->hcon->dst_type, &conn->hcon->dst, res);
Vinicius Costa Gomes8aab4752011-09-05 14:31:31 -0300424 else
425 ret = smp_c1(tfm, smp->tk, smp->prnd, smp->preq, smp->prsp,
Marcel Holtmannc8462ca2013-10-13 05:24:02 -0700426 conn->hcon->dst_type, &conn->hcon->dst,
427 conn->hcon->src_type, &conn->hcon->src, res);
Vinicius Costa Gomes8aab4752011-09-05 14:31:31 -0300428 if (ret) {
429 reason = SMP_UNSPECIFIED;
430 goto error;
431 }
432
Brian Gix2b64d152011-12-21 16:12:12 -0800433 clear_bit(SMP_FLAG_CFM_PENDING, &smp->smp_flags);
434
Vinicius Costa Gomes8aab4752011-09-05 14:31:31 -0300435 swap128(res, cp.confirm_val);
436 smp_send_cmd(smp->conn, SMP_CMD_PAIRING_CONFIRM, sizeof(cp), &cp);
437
438 return;
439
440error:
Johan Hedberg84794e12013-11-06 11:24:57 +0200441 smp_failure(conn, reason);
Vinicius Costa Gomes8aab4752011-09-05 14:31:31 -0300442}
443
444static void random_work(struct work_struct *work)
445{
446 struct smp_chan *smp = container_of(work, struct smp_chan, random);
447 struct l2cap_conn *conn = smp->conn;
448 struct hci_conn *hcon = conn->hcon;
449 struct crypto_blkcipher *tfm = smp->tfm;
450 u8 reason, confirm[16], res[16], key[16];
451 int ret;
452
453 if (IS_ERR_OR_NULL(tfm)) {
454 reason = SMP_UNSPECIFIED;
455 goto error;
456 }
457
458 BT_DBG("conn %p %s", conn, conn->hcon->out ? "master" : "slave");
459
460 if (hcon->out)
Marcel Holtmannc8462ca2013-10-13 05:24:02 -0700461 ret = smp_c1(tfm, smp->tk, smp->rrnd, smp->preq, smp->prsp,
462 hcon->src_type, &hcon->src,
463 hcon->dst_type, &hcon->dst, res);
Vinicius Costa Gomes8aab4752011-09-05 14:31:31 -0300464 else
465 ret = smp_c1(tfm, smp->tk, smp->rrnd, smp->preq, smp->prsp,
Marcel Holtmannc8462ca2013-10-13 05:24:02 -0700466 hcon->dst_type, &hcon->dst,
467 hcon->src_type, &hcon->src, res);
Vinicius Costa Gomes8aab4752011-09-05 14:31:31 -0300468 if (ret) {
469 reason = SMP_UNSPECIFIED;
470 goto error;
471 }
472
473 swap128(res, confirm);
474
475 if (memcmp(smp->pcnf, confirm, sizeof(smp->pcnf)) != 0) {
476 BT_ERR("Pairing failed (confirmation values mismatch)");
477 reason = SMP_CONFIRM_FAILED;
478 goto error;
479 }
480
481 if (hcon->out) {
482 u8 stk[16], rand[8];
483 __le16 ediv;
484
485 memset(rand, 0, sizeof(rand));
486 ediv = 0;
487
488 smp_s1(tfm, smp->tk, smp->rrnd, smp->prnd, key);
489 swap128(key, stk);
490
Vinicius Costa Gomesf7aa6112012-01-30 19:29:12 -0300491 memset(stk + smp->enc_key_size, 0,
Gustavo F. Padovan04124682012-03-08 01:25:00 -0300492 SMP_MAX_ENC_KEY_SIZE - smp->enc_key_size);
Vinicius Costa Gomes8aab4752011-09-05 14:31:31 -0300493
Johan Hedberg51a8efd2012-01-16 06:10:31 +0200494 if (test_and_set_bit(HCI_CONN_ENCRYPT_PEND, &hcon->flags)) {
Vinicius Costa Gomes8aab4752011-09-05 14:31:31 -0300495 reason = SMP_UNSPECIFIED;
496 goto error;
497 }
498
499 hci_le_start_enc(hcon, ediv, rand, stk);
Vinicius Costa Gomesf7aa6112012-01-30 19:29:12 -0300500 hcon->enc_key_size = smp->enc_key_size;
Vinicius Costa Gomes8aab4752011-09-05 14:31:31 -0300501 } else {
502 u8 stk[16], r[16], rand[8];
503 __le16 ediv;
504
505 memset(rand, 0, sizeof(rand));
506 ediv = 0;
507
508 swap128(smp->prnd, r);
509 smp_send_cmd(conn, SMP_CMD_PAIRING_RANDOM, sizeof(r), r);
510
511 smp_s1(tfm, smp->tk, smp->prnd, smp->rrnd, key);
512 swap128(key, stk);
513
Vinicius Costa Gomesf7aa6112012-01-30 19:29:12 -0300514 memset(stk + smp->enc_key_size, 0,
Marcel Holtmannf1560462013-10-13 05:43:25 -0700515 SMP_MAX_ENC_KEY_SIZE - smp->enc_key_size);
Vinicius Costa Gomes8aab4752011-09-05 14:31:31 -0300516
Marcel Holtmannce39fb42013-10-13 02:23:39 -0700517 hci_add_ltk(hcon->hdev, &hcon->dst, hcon->dst_type,
Gustavo F. Padovan04124682012-03-08 01:25:00 -0300518 HCI_SMP_STK_SLAVE, 0, 0, stk, smp->enc_key_size,
519 ediv, rand);
Vinicius Costa Gomes8aab4752011-09-05 14:31:31 -0300520 }
521
522 return;
523
524error:
Johan Hedberg84794e12013-11-06 11:24:57 +0200525 smp_failure(conn, reason);
Vinicius Costa Gomes8aab4752011-09-05 14:31:31 -0300526}
527
528static struct smp_chan *smp_chan_create(struct l2cap_conn *conn)
529{
530 struct smp_chan *smp;
531
Marcel Holtmannf1560462013-10-13 05:43:25 -0700532 smp = kzalloc(sizeof(*smp), GFP_ATOMIC);
Vinicius Costa Gomes8aab4752011-09-05 14:31:31 -0300533 if (!smp)
534 return NULL;
535
536 INIT_WORK(&smp->confirm, confirm_work);
537 INIT_WORK(&smp->random, random_work);
538
539 smp->conn = conn;
540 conn->smp_chan = smp;
Brian Gix2b64d152011-12-21 16:12:12 -0800541 conn->hcon->smp_conn = conn;
Vinicius Costa Gomes8aab4752011-09-05 14:31:31 -0300542
543 hci_conn_hold(conn->hcon);
544
545 return smp;
546}
547
548void smp_chan_destroy(struct l2cap_conn *conn)
549{
Brian Gixc8eb9692011-11-23 08:28:35 -0800550 struct smp_chan *smp = conn->smp_chan;
551
Vinicius Costa Gomesf1c09c02012-02-01 18:27:56 -0300552 BUG_ON(!smp);
Brian Gixc8eb9692011-11-23 08:28:35 -0800553
554 if (smp->tfm)
555 crypto_free_blkcipher(smp->tfm);
556
557 kfree(smp);
558 conn->smp_chan = NULL;
Brian Gix2b64d152011-12-21 16:12:12 -0800559 conn->hcon->smp_conn = NULL;
David Herrmann76a68ba2013-04-06 20:28:37 +0200560 hci_conn_drop(conn->hcon);
Vinicius Costa Gomes8aab4752011-09-05 14:31:31 -0300561}
562
Brian Gix2b64d152011-12-21 16:12:12 -0800563int smp_user_confirm_reply(struct hci_conn *hcon, u16 mgmt_op, __le32 passkey)
564{
565 struct l2cap_conn *conn = hcon->smp_conn;
566 struct smp_chan *smp;
567 u32 value;
568 u8 key[16];
569
570 BT_DBG("");
571
572 if (!conn)
573 return -ENOTCONN;
574
575 smp = conn->smp_chan;
576
577 switch (mgmt_op) {
578 case MGMT_OP_USER_PASSKEY_REPLY:
579 value = le32_to_cpu(passkey);
580 memset(key, 0, sizeof(key));
581 BT_DBG("PassKey: %d", value);
582 put_unaligned_le32(value, key);
583 swap128(key, smp->tk);
584 /* Fall Through */
585 case MGMT_OP_USER_CONFIRM_REPLY:
586 set_bit(SMP_FLAG_TK_VALID, &smp->smp_flags);
587 break;
588 case MGMT_OP_USER_PASSKEY_NEG_REPLY:
589 case MGMT_OP_USER_CONFIRM_NEG_REPLY:
Johan Hedberg84794e12013-11-06 11:24:57 +0200590 smp_failure(conn, SMP_PASSKEY_ENTRY_FAILED);
Brian Gix2b64d152011-12-21 16:12:12 -0800591 return 0;
592 default:
Johan Hedberg84794e12013-11-06 11:24:57 +0200593 smp_failure(conn, SMP_PASSKEY_ENTRY_FAILED);
Brian Gix2b64d152011-12-21 16:12:12 -0800594 return -EOPNOTSUPP;
595 }
596
597 /* If it is our turn to send Pairing Confirm, do so now */
598 if (test_bit(SMP_FLAG_CFM_PENDING, &smp->smp_flags))
599 queue_work(hcon->hdev->workqueue, &smp->confirm);
600
601 return 0;
602}
603
Vinicius Costa Gomesda85e5e2011-06-09 18:50:53 -0300604static u8 smp_cmd_pairing_req(struct l2cap_conn *conn, struct sk_buff *skb)
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300605{
Vinicius Costa Gomes3158c502011-06-14 13:37:42 -0300606 struct smp_cmd_pairing rsp, *req = (void *) skb->data;
Vinicius Costa Gomes8aab4752011-09-05 14:31:31 -0300607 struct smp_chan *smp;
Vinicius Costa Gomes3158c502011-06-14 13:37:42 -0300608 u8 key_size;
Brian Gix2b64d152011-12-21 16:12:12 -0800609 u8 auth = SMP_AUTH_NONE;
Vinicius Costa Gomes8aab4752011-09-05 14:31:31 -0300610 int ret;
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300611
612 BT_DBG("conn %p", conn);
613
Johan Hedbergc46b98b2014-02-18 10:19:29 +0200614 if (skb->len < sizeof(*req))
615 return SMP_UNSPECIFIED;
616
Brian Gix2b64d152011-12-21 16:12:12 -0800617 if (conn->hcon->link_mode & HCI_LM_MASTER)
618 return SMP_CMD_NOTSUPP;
619
Johan Hedberg51a8efd2012-01-16 06:10:31 +0200620 if (!test_and_set_bit(HCI_CONN_LE_SMP_PEND, &conn->hcon->flags))
Vinicius Costa Gomes8aab4752011-09-05 14:31:31 -0300621 smp = smp_chan_create(conn);
Andrei Emeltchenkod08fd0e2012-07-19 17:03:43 +0300622 else
623 smp = conn->smp_chan;
Vinicius Costa Gomes8aab4752011-09-05 14:31:31 -0300624
Andrei Emeltchenkod08fd0e2012-07-19 17:03:43 +0300625 if (!smp)
626 return SMP_UNSPECIFIED;
Vinicius Costa Gomesd26a2342011-08-19 21:06:51 -0300627
Vinicius Costa Gomes1c1def02011-09-05 14:31:30 -0300628 smp->preq[0] = SMP_CMD_PAIRING_REQ;
629 memcpy(&smp->preq[1], req, sizeof(*req));
Vinicius Costa Gomes3158c502011-06-14 13:37:42 -0300630 skb_pull(skb, sizeof(*req));
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300631
Brian Gix2b64d152011-12-21 16:12:12 -0800632 /* We didn't start the pairing, so match remote */
633 if (req->auth_req & SMP_AUTH_BONDING)
634 auth = req->auth_req;
Vinicius Costa Gomesda85e5e2011-06-09 18:50:53 -0300635
Ido Yarivfdde0a22012-03-05 20:09:38 +0200636 conn->hcon->pending_sec_level = authreq_to_seclevel(auth);
637
Brian Gix2b64d152011-12-21 16:12:12 -0800638 build_pairing_cmd(conn, req, &rsp, auth);
Vinicius Costa Gomes3158c502011-06-14 13:37:42 -0300639
640 key_size = min(req->max_key_size, rsp.max_key_size);
641 if (check_enc_key_size(conn, key_size))
642 return SMP_ENC_KEY_SIZE;
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300643
Johan Hedberge84a6b12013-12-02 10:49:03 +0200644 get_random_bytes(smp->prnd, sizeof(smp->prnd));
Vinicius Costa Gomes8aab4752011-09-05 14:31:31 -0300645
Vinicius Costa Gomes1c1def02011-09-05 14:31:30 -0300646 smp->prsp[0] = SMP_CMD_PAIRING_RSP;
647 memcpy(&smp->prsp[1], &rsp, sizeof(rsp));
Anderson Brigliaf01ead32011-06-09 18:50:45 -0300648
Vinicius Costa Gomes3158c502011-06-14 13:37:42 -0300649 smp_send_cmd(conn, SMP_CMD_PAIRING_RSP, sizeof(rsp), &rsp);
Vinicius Costa Gomesda85e5e2011-06-09 18:50:53 -0300650
Brian Gix2b64d152011-12-21 16:12:12 -0800651 /* Request setup of TK */
652 ret = tk_request(conn, 0, auth, rsp.io_capability, req->io_capability);
653 if (ret)
654 return SMP_UNSPECIFIED;
655
Vinicius Costa Gomesda85e5e2011-06-09 18:50:53 -0300656 return 0;
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300657}
658
Vinicius Costa Gomesda85e5e2011-06-09 18:50:53 -0300659static u8 smp_cmd_pairing_rsp(struct l2cap_conn *conn, struct sk_buff *skb)
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300660{
Vinicius Costa Gomes3158c502011-06-14 13:37:42 -0300661 struct smp_cmd_pairing *req, *rsp = (void *) skb->data;
Vinicius Costa Gomes1c1def02011-09-05 14:31:30 -0300662 struct smp_chan *smp = conn->smp_chan;
Vinicius Costa Gomes8aab4752011-09-05 14:31:31 -0300663 struct hci_dev *hdev = conn->hcon->hdev;
Brian Gix2b64d152011-12-21 16:12:12 -0800664 u8 key_size, auth = SMP_AUTH_NONE;
Anderson Briglia7d24ddc2011-06-09 18:50:46 -0300665 int ret;
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300666
667 BT_DBG("conn %p", conn);
668
Johan Hedbergc46b98b2014-02-18 10:19:29 +0200669 if (skb->len < sizeof(*rsp))
670 return SMP_UNSPECIFIED;
671
Brian Gix2b64d152011-12-21 16:12:12 -0800672 if (!(conn->hcon->link_mode & HCI_LM_MASTER))
673 return SMP_CMD_NOTSUPP;
674
Vinicius Costa Gomes3158c502011-06-14 13:37:42 -0300675 skb_pull(skb, sizeof(*rsp));
Vinicius Costa Gomesda85e5e2011-06-09 18:50:53 -0300676
Vinicius Costa Gomes1c1def02011-09-05 14:31:30 -0300677 req = (void *) &smp->preq[1];
Vinicius Costa Gomes3158c502011-06-14 13:37:42 -0300678
679 key_size = min(req->max_key_size, rsp->max_key_size);
680 if (check_enc_key_size(conn, key_size))
681 return SMP_ENC_KEY_SIZE;
682
Johan Hedberge84a6b12013-12-02 10:49:03 +0200683 get_random_bytes(smp->prnd, sizeof(smp->prnd));
Anderson Briglia7d24ddc2011-06-09 18:50:46 -0300684
Vinicius Costa Gomes8aab4752011-09-05 14:31:31 -0300685 smp->prsp[0] = SMP_CMD_PAIRING_RSP;
686 memcpy(&smp->prsp[1], rsp, sizeof(*rsp));
Anderson Briglia7d24ddc2011-06-09 18:50:46 -0300687
Brian Gix2b64d152011-12-21 16:12:12 -0800688 if ((req->auth_req & SMP_AUTH_BONDING) &&
Marcel Holtmannf1560462013-10-13 05:43:25 -0700689 (rsp->auth_req & SMP_AUTH_BONDING))
Brian Gix2b64d152011-12-21 16:12:12 -0800690 auth = SMP_AUTH_BONDING;
691
692 auth |= (req->auth_req | rsp->auth_req) & SMP_AUTH_MITM;
693
Johan Hedberg476585e2012-06-06 18:54:15 +0800694 ret = tk_request(conn, 0, auth, req->io_capability, rsp->io_capability);
Brian Gix2b64d152011-12-21 16:12:12 -0800695 if (ret)
696 return SMP_UNSPECIFIED;
697
698 set_bit(SMP_FLAG_CFM_PENDING, &smp->smp_flags);
699
700 /* Can't compose response until we have been confirmed */
701 if (!test_bit(SMP_FLAG_TK_VALID, &smp->smp_flags))
702 return 0;
703
Vinicius Costa Gomes8aab4752011-09-05 14:31:31 -0300704 queue_work(hdev->workqueue, &smp->confirm);
Vinicius Costa Gomesda85e5e2011-06-09 18:50:53 -0300705
706 return 0;
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300707}
708
Vinicius Costa Gomesda85e5e2011-06-09 18:50:53 -0300709static u8 smp_cmd_pairing_confirm(struct l2cap_conn *conn, struct sk_buff *skb)
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300710{
Vinicius Costa Gomes1c1def02011-09-05 14:31:30 -0300711 struct smp_chan *smp = conn->smp_chan;
Vinicius Costa Gomes8aab4752011-09-05 14:31:31 -0300712 struct hci_dev *hdev = conn->hcon->hdev;
Anderson Briglia7d24ddc2011-06-09 18:50:46 -0300713
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300714 BT_DBG("conn %p %s", conn, conn->hcon->out ? "master" : "slave");
715
Johan Hedbergc46b98b2014-02-18 10:19:29 +0200716 if (skb->len < sizeof(smp->pcnf))
717 return SMP_UNSPECIFIED;
718
Vinicius Costa Gomes1c1def02011-09-05 14:31:30 -0300719 memcpy(smp->pcnf, skb->data, sizeof(smp->pcnf));
720 skb_pull(skb, sizeof(smp->pcnf));
Anderson Briglia7d24ddc2011-06-09 18:50:46 -0300721
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300722 if (conn->hcon->out) {
Anderson Briglia7d24ddc2011-06-09 18:50:46 -0300723 u8 random[16];
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300724
Vinicius Costa Gomes1c1def02011-09-05 14:31:30 -0300725 swap128(smp->prnd, random);
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300726 smp_send_cmd(conn, SMP_CMD_PAIRING_RANDOM, sizeof(random),
Marcel Holtmannf1560462013-10-13 05:43:25 -0700727 random);
Brian Gix2b64d152011-12-21 16:12:12 -0800728 } else if (test_bit(SMP_FLAG_TK_VALID, &smp->smp_flags)) {
Vinicius Costa Gomes8aab4752011-09-05 14:31:31 -0300729 queue_work(hdev->workqueue, &smp->confirm);
Brian Gix2b64d152011-12-21 16:12:12 -0800730 } else {
731 set_bit(SMP_FLAG_CFM_PENDING, &smp->smp_flags);
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300732 }
Vinicius Costa Gomesda85e5e2011-06-09 18:50:53 -0300733
734 return 0;
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300735}
736
Vinicius Costa Gomesda85e5e2011-06-09 18:50:53 -0300737static u8 smp_cmd_pairing_random(struct l2cap_conn *conn, struct sk_buff *skb)
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300738{
Vinicius Costa Gomes1c1def02011-09-05 14:31:30 -0300739 struct smp_chan *smp = conn->smp_chan;
Vinicius Costa Gomes8aab4752011-09-05 14:31:31 -0300740 struct hci_dev *hdev = conn->hcon->hdev;
Anderson Briglia7d24ddc2011-06-09 18:50:46 -0300741
Vinicius Costa Gomes8aab4752011-09-05 14:31:31 -0300742 BT_DBG("conn %p", conn);
Anderson Briglia7d24ddc2011-06-09 18:50:46 -0300743
Johan Hedbergc46b98b2014-02-18 10:19:29 +0200744 if (skb->len < sizeof(smp->rrnd))
745 return SMP_UNSPECIFIED;
746
Vinicius Costa Gomes8aab4752011-09-05 14:31:31 -0300747 swap128(skb->data, smp->rrnd);
748 skb_pull(skb, sizeof(smp->rrnd));
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300749
Vinicius Costa Gomes8aab4752011-09-05 14:31:31 -0300750 queue_work(hdev->workqueue, &smp->random);
Vinicius Costa Gomesda85e5e2011-06-09 18:50:53 -0300751
752 return 0;
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300753}
754
Johan Hedberg4dab7862012-06-07 14:58:37 +0800755static u8 smp_ltk_encrypt(struct l2cap_conn *conn, u8 sec_level)
Vinicius Costa Gomes988c5992011-08-25 20:02:28 -0300756{
Vinicius Costa Gomesc9839a12012-02-02 21:08:01 -0300757 struct smp_ltk *key;
Vinicius Costa Gomes988c5992011-08-25 20:02:28 -0300758 struct hci_conn *hcon = conn->hcon;
759
Johan Hedberg98a0b842014-01-30 19:40:00 -0800760 key = hci_find_ltk_by_addr(hcon->hdev, &hcon->dst, hcon->dst_type,
761 hcon->out);
Vinicius Costa Gomes988c5992011-08-25 20:02:28 -0300762 if (!key)
763 return 0;
764
Johan Hedberg4dab7862012-06-07 14:58:37 +0800765 if (sec_level > BT_SECURITY_MEDIUM && !key->authenticated)
766 return 0;
767
Johan Hedberg51a8efd2012-01-16 06:10:31 +0200768 if (test_and_set_bit(HCI_CONN_ENCRYPT_PEND, &hcon->flags))
Vinicius Costa Gomes988c5992011-08-25 20:02:28 -0300769 return 1;
770
Vinicius Costa Gomesc9839a12012-02-02 21:08:01 -0300771 hci_le_start_enc(hcon, key->ediv, key->rand, key->val);
772 hcon->enc_key_size = key->enc_size;
Vinicius Costa Gomes988c5992011-08-25 20:02:28 -0300773
774 return 1;
Vinicius Costa Gomes988c5992011-08-25 20:02:28 -0300775}
Marcel Holtmannf1560462013-10-13 05:43:25 -0700776
Vinicius Costa Gomesda85e5e2011-06-09 18:50:53 -0300777static u8 smp_cmd_security_req(struct l2cap_conn *conn, struct sk_buff *skb)
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300778{
779 struct smp_cmd_security_req *rp = (void *) skb->data;
780 struct smp_cmd_pairing cp;
Vinicius Costa Gomesf1cb9af2011-01-26 21:42:57 -0300781 struct hci_conn *hcon = conn->hcon;
Vinicius Costa Gomes8aab4752011-09-05 14:31:31 -0300782 struct smp_chan *smp;
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300783
784 BT_DBG("conn %p", conn);
785
Johan Hedbergc46b98b2014-02-18 10:19:29 +0200786 if (skb->len < sizeof(*rp))
787 return SMP_UNSPECIFIED;
788
Johan Hedberg86ca9ea2013-11-05 11:30:39 +0200789 if (!(conn->hcon->link_mode & HCI_LM_MASTER))
790 return SMP_CMD_NOTSUPP;
791
Brian Gix2b64d152011-12-21 16:12:12 -0800792 hcon->pending_sec_level = authreq_to_seclevel(rp->auth_req);
Vinicius Costa Gomesfeb45eb2011-08-25 20:02:35 -0300793
Johan Hedberg4dab7862012-06-07 14:58:37 +0800794 if (smp_ltk_encrypt(conn, hcon->pending_sec_level))
Vinicius Costa Gomes988c5992011-08-25 20:02:28 -0300795 return 0;
796
Johan Hedberg51a8efd2012-01-16 06:10:31 +0200797 if (test_and_set_bit(HCI_CONN_LE_SMP_PEND, &hcon->flags))
Vinicius Costa Gomesda85e5e2011-06-09 18:50:53 -0300798 return 0;
Vinicius Costa Gomesf1cb9af2011-01-26 21:42:57 -0300799
Vinicius Costa Gomes8aab4752011-09-05 14:31:31 -0300800 smp = smp_chan_create(conn);
Vinicius Costa Gomesd26a2342011-08-19 21:06:51 -0300801
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300802 skb_pull(skb, sizeof(*rp));
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300803
Vinicius Costa Gomesda85e5e2011-06-09 18:50:53 -0300804 memset(&cp, 0, sizeof(cp));
Vinicius Costa Gomes54790f72011-07-07 18:59:38 -0300805 build_pairing_cmd(conn, &cp, NULL, rp->auth_req);
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300806
Vinicius Costa Gomes1c1def02011-09-05 14:31:30 -0300807 smp->preq[0] = SMP_CMD_PAIRING_REQ;
808 memcpy(&smp->preq[1], &cp, sizeof(cp));
Anderson Brigliaf01ead32011-06-09 18:50:45 -0300809
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300810 smp_send_cmd(conn, SMP_CMD_PAIRING_REQ, sizeof(cp), &cp);
Vinicius Costa Gomesf1cb9af2011-01-26 21:42:57 -0300811
Vinicius Costa Gomesda85e5e2011-06-09 18:50:53 -0300812 return 0;
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300813}
814
Johan Hedbergad32a2f2013-05-14 18:05:12 +0300815bool smp_sufficient_security(struct hci_conn *hcon, u8 sec_level)
816{
817 if (sec_level == BT_SECURITY_LOW)
818 return true;
819
820 if (hcon->sec_level >= sec_level)
821 return true;
822
823 return false;
824}
825
Vinicius Costa Gomescc110922012-08-23 21:32:43 -0300826int smp_conn_security(struct hci_conn *hcon, __u8 sec_level)
Anderson Brigliaeb492e02011-06-09 18:50:40 -0300827{
Vinicius Costa Gomescc110922012-08-23 21:32:43 -0300828 struct l2cap_conn *conn = hcon->l2cap_data;
Vinicius Costa Gomes1c1def02011-09-05 14:31:30 -0300829 struct smp_chan *smp = conn->smp_chan;
Brian Gix2b64d152011-12-21 16:12:12 -0800830 __u8 authreq;
Anderson Brigliaeb492e02011-06-09 18:50:40 -0300831
Vinicius Costa Gomes3a0259b2011-06-09 18:50:43 -0300832 BT_DBG("conn %p hcon %p level 0x%2.2x", conn, hcon, sec_level);
833
Johan Hedberg757aee02013-04-24 13:05:32 +0300834 if (!test_bit(HCI_LE_ENABLED, &hcon->hdev->dev_flags))
Andre Guedes2e65c9d2011-06-30 19:20:56 -0300835 return 1;
836
Johan Hedbergad32a2f2013-05-14 18:05:12 +0300837 if (smp_sufficient_security(hcon, sec_level))
Vinicius Costa Gomesf1cb9af2011-01-26 21:42:57 -0300838 return 1;
839
Vinicius Costa Gomes988c5992011-08-25 20:02:28 -0300840 if (hcon->link_mode & HCI_LM_MASTER)
Johan Hedberg4dab7862012-06-07 14:58:37 +0800841 if (smp_ltk_encrypt(conn, sec_level))
Vinicius Costa Gomes02bc7452011-07-07 18:59:41 -0300842 goto done;
Vinicius Costa Gomesd26a2342011-08-19 21:06:51 -0300843
Johan Hedberg51a8efd2012-01-16 06:10:31 +0200844 if (test_and_set_bit(HCI_CONN_LE_SMP_PEND, &hcon->flags))
Vinicius Costa Gomesd26a2342011-08-19 21:06:51 -0300845 return 0;
846
Vinicius Costa Gomes8aab4752011-09-05 14:31:31 -0300847 smp = smp_chan_create(conn);
Brian Gix2b64d152011-12-21 16:12:12 -0800848 if (!smp)
849 return 1;
850
851 authreq = seclevel_to_authreq(sec_level);
Vinicius Costa Gomesd26a2342011-08-19 21:06:51 -0300852
Vinicius Costa Gomesd26a2342011-08-19 21:06:51 -0300853 if (hcon->link_mode & HCI_LM_MASTER) {
854 struct smp_cmd_pairing cp;
Anderson Brigliaf01ead32011-06-09 18:50:45 -0300855
Brian Gix2b64d152011-12-21 16:12:12 -0800856 build_pairing_cmd(conn, &cp, NULL, authreq);
Vinicius Costa Gomes1c1def02011-09-05 14:31:30 -0300857 smp->preq[0] = SMP_CMD_PAIRING_REQ;
858 memcpy(&smp->preq[1], &cp, sizeof(cp));
Anderson Brigliaf01ead32011-06-09 18:50:45 -0300859
Anderson Brigliaeb492e02011-06-09 18:50:40 -0300860 smp_send_cmd(conn, SMP_CMD_PAIRING_REQ, sizeof(cp), &cp);
861 } else {
862 struct smp_cmd_security_req cp;
Brian Gix2b64d152011-12-21 16:12:12 -0800863 cp.auth_req = authreq;
Anderson Brigliaeb492e02011-06-09 18:50:40 -0300864 smp_send_cmd(conn, SMP_CMD_SECURITY_REQ, sizeof(cp), &cp);
865 }
866
Vinicius Costa Gomes02bc7452011-07-07 18:59:41 -0300867done:
Vinicius Costa Gomesf1cb9af2011-01-26 21:42:57 -0300868 hcon->pending_sec_level = sec_level;
Vinicius Costa Gomesf1cb9af2011-01-26 21:42:57 -0300869
Anderson Brigliaeb492e02011-06-09 18:50:40 -0300870 return 0;
871}
872
Vinicius Costa Gomes7034b912011-07-07 18:59:34 -0300873static int smp_cmd_encrypt_info(struct l2cap_conn *conn, struct sk_buff *skb)
874{
Vinicius Costa Gomes16b90832011-07-07 18:59:39 -0300875 struct smp_cmd_encrypt_info *rp = (void *) skb->data;
Vinicius Costa Gomes1c1def02011-09-05 14:31:30 -0300876 struct smp_chan *smp = conn->smp_chan;
Vinicius Costa Gomes16b90832011-07-07 18:59:39 -0300877
Johan Hedbergc46b98b2014-02-18 10:19:29 +0200878 BT_DBG("conn %p", conn);
879
880 if (skb->len < sizeof(*rp))
881 return SMP_UNSPECIFIED;
882
Vinicius Costa Gomes16b90832011-07-07 18:59:39 -0300883 skb_pull(skb, sizeof(*rp));
884
Vinicius Costa Gomes1c1def02011-09-05 14:31:30 -0300885 memcpy(smp->tk, rp->ltk, sizeof(smp->tk));
Vinicius Costa Gomes16b90832011-07-07 18:59:39 -0300886
Vinicius Costa Gomes7034b912011-07-07 18:59:34 -0300887 return 0;
888}
889
890static int smp_cmd_master_ident(struct l2cap_conn *conn, struct sk_buff *skb)
891{
Vinicius Costa Gomes16b90832011-07-07 18:59:39 -0300892 struct smp_cmd_master_ident *rp = (void *) skb->data;
Vinicius Costa Gomes1c1def02011-09-05 14:31:30 -0300893 struct smp_chan *smp = conn->smp_chan;
Vinicius Costa Gomesc9839a12012-02-02 21:08:01 -0300894 struct hci_dev *hdev = conn->hcon->hdev;
895 struct hci_conn *hcon = conn->hcon;
896 u8 authenticated;
Vinicius Costa Gomes7034b912011-07-07 18:59:34 -0300897
Johan Hedbergc46b98b2014-02-18 10:19:29 +0200898 BT_DBG("conn %p", conn);
899
900 if (skb->len < sizeof(*rp))
901 return SMP_UNSPECIFIED;
902
Vinicius Costa Gomes16b90832011-07-07 18:59:39 -0300903 skb_pull(skb, sizeof(*rp));
904
Vinicius Costa Gomesc9839a12012-02-02 21:08:01 -0300905 hci_dev_lock(hdev);
Marcel Holtmannce39fb42013-10-13 02:23:39 -0700906 authenticated = (hcon->sec_level == BT_SECURITY_HIGH);
907 hci_add_ltk(hdev, &hcon->dst, hcon->dst_type, HCI_SMP_LTK, 1,
908 authenticated, smp->tk, smp->enc_key_size,
Gustavo F. Padovan04124682012-03-08 01:25:00 -0300909 rp->ediv, rp->rand);
Vinicius Costa Gomes7034b912011-07-07 18:59:34 -0300910 smp_distribute_keys(conn, 1);
Vinicius Costa Gomesc9839a12012-02-02 21:08:01 -0300911 hci_dev_unlock(hdev);
Vinicius Costa Gomes7034b912011-07-07 18:59:34 -0300912
913 return 0;
914}
915
Anderson Brigliaeb492e02011-06-09 18:50:40 -0300916int smp_sig_channel(struct l2cap_conn *conn, struct sk_buff *skb)
917{
Marcel Holtmann7b9899d2013-10-03 00:00:57 -0700918 struct hci_conn *hcon = conn->hcon;
Marcel Holtmann92381f52013-10-03 01:23:08 -0700919 __u8 code, reason;
Anderson Brigliaeb492e02011-06-09 18:50:40 -0300920 int err = 0;
921
Marcel Holtmann7b9899d2013-10-03 00:00:57 -0700922 if (hcon->type != LE_LINK) {
923 kfree_skb(skb);
Johan Hedberg34327112013-10-16 11:37:01 +0300924 return 0;
Marcel Holtmann7b9899d2013-10-03 00:00:57 -0700925 }
926
Marcel Holtmann92381f52013-10-03 01:23:08 -0700927 if (skb->len < 1) {
928 kfree_skb(skb);
929 return -EILSEQ;
930 }
931
Marcel Holtmann06ae3312013-10-18 03:43:00 -0700932 if (!test_bit(HCI_LE_ENABLED, &hcon->hdev->dev_flags)) {
Andre Guedes2e65c9d2011-06-30 19:20:56 -0300933 err = -ENOTSUPP;
934 reason = SMP_PAIRING_NOTSUPP;
935 goto done;
936 }
937
Marcel Holtmann92381f52013-10-03 01:23:08 -0700938 code = skb->data[0];
Anderson Brigliaeb492e02011-06-09 18:50:40 -0300939 skb_pull(skb, sizeof(code));
940
Johan Hedberg8cf9fa12013-01-29 10:44:23 -0600941 /*
942 * The SMP context must be initialized for all other PDUs except
943 * pairing and security requests. If we get any other PDU when
944 * not initialized simply disconnect (done if this function
945 * returns an error).
946 */
947 if (code != SMP_CMD_PAIRING_REQ && code != SMP_CMD_SECURITY_REQ &&
948 !conn->smp_chan) {
949 BT_ERR("Unexpected SMP command 0x%02x. Disconnecting.", code);
950 kfree_skb(skb);
951 return -ENOTSUPP;
952 }
953
Anderson Brigliaeb492e02011-06-09 18:50:40 -0300954 switch (code) {
955 case SMP_CMD_PAIRING_REQ:
Vinicius Costa Gomesda85e5e2011-06-09 18:50:53 -0300956 reason = smp_cmd_pairing_req(conn, skb);
Anderson Brigliaeb492e02011-06-09 18:50:40 -0300957 break;
958
959 case SMP_CMD_PAIRING_FAIL:
Johan Hedberg84794e12013-11-06 11:24:57 +0200960 smp_failure(conn, 0);
Vinicius Costa Gomesda85e5e2011-06-09 18:50:53 -0300961 reason = 0;
962 err = -EPERM;
Anderson Brigliaeb492e02011-06-09 18:50:40 -0300963 break;
964
965 case SMP_CMD_PAIRING_RSP:
Vinicius Costa Gomesda85e5e2011-06-09 18:50:53 -0300966 reason = smp_cmd_pairing_rsp(conn, skb);
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300967 break;
968
969 case SMP_CMD_SECURITY_REQ:
Vinicius Costa Gomesda85e5e2011-06-09 18:50:53 -0300970 reason = smp_cmd_security_req(conn, skb);
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300971 break;
972
Anderson Brigliaeb492e02011-06-09 18:50:40 -0300973 case SMP_CMD_PAIRING_CONFIRM:
Vinicius Costa Gomesda85e5e2011-06-09 18:50:53 -0300974 reason = smp_cmd_pairing_confirm(conn, skb);
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300975 break;
976
Anderson Brigliaeb492e02011-06-09 18:50:40 -0300977 case SMP_CMD_PAIRING_RANDOM:
Vinicius Costa Gomesda85e5e2011-06-09 18:50:53 -0300978 reason = smp_cmd_pairing_random(conn, skb);
Anderson Briglia88ba43b2011-06-09 18:50:42 -0300979 break;
980
Anderson Brigliaeb492e02011-06-09 18:50:40 -0300981 case SMP_CMD_ENCRYPT_INFO:
Vinicius Costa Gomes7034b912011-07-07 18:59:34 -0300982 reason = smp_cmd_encrypt_info(conn, skb);
983 break;
984
Anderson Brigliaeb492e02011-06-09 18:50:40 -0300985 case SMP_CMD_MASTER_IDENT:
Vinicius Costa Gomes7034b912011-07-07 18:59:34 -0300986 reason = smp_cmd_master_ident(conn, skb);
987 break;
988
Anderson Brigliaeb492e02011-06-09 18:50:40 -0300989 case SMP_CMD_IDENT_INFO:
990 case SMP_CMD_IDENT_ADDR_INFO:
991 case SMP_CMD_SIGN_INFO:
Vinicius Costa Gomes7034b912011-07-07 18:59:34 -0300992 /* Just ignored */
993 reason = 0;
994 break;
995
Anderson Brigliaeb492e02011-06-09 18:50:40 -0300996 default:
997 BT_DBG("Unknown command code 0x%2.2x", code);
998
999 reason = SMP_CMD_NOTSUPP;
Vinicius Costa Gomes3a0259b2011-06-09 18:50:43 -03001000 err = -EOPNOTSUPP;
1001 goto done;
1002 }
1003
1004done:
1005 if (reason)
Johan Hedberg84794e12013-11-06 11:24:57 +02001006 smp_failure(conn, reason);
Anderson Brigliaeb492e02011-06-09 18:50:40 -03001007
1008 kfree_skb(skb);
1009 return err;
1010}
Vinicius Costa Gomes7034b912011-07-07 18:59:34 -03001011
1012int smp_distribute_keys(struct l2cap_conn *conn, __u8 force)
1013{
1014 struct smp_cmd_pairing *req, *rsp;
Vinicius Costa Gomes1c1def02011-09-05 14:31:30 -03001015 struct smp_chan *smp = conn->smp_chan;
Vinicius Costa Gomes7034b912011-07-07 18:59:34 -03001016 __u8 *keydist;
1017
1018 BT_DBG("conn %p force %d", conn, force);
1019
Johan Hedberg51a8efd2012-01-16 06:10:31 +02001020 if (!test_bit(HCI_CONN_LE_SMP_PEND, &conn->hcon->flags))
Vinicius Costa Gomesd26a2342011-08-19 21:06:51 -03001021 return 0;
1022
Vinicius Costa Gomes1c1def02011-09-05 14:31:30 -03001023 rsp = (void *) &smp->prsp[1];
Vinicius Costa Gomes7034b912011-07-07 18:59:34 -03001024
1025 /* The responder sends its keys first */
1026 if (!force && conn->hcon->out && (rsp->resp_key_dist & 0x07))
1027 return 0;
1028
Vinicius Costa Gomes1c1def02011-09-05 14:31:30 -03001029 req = (void *) &smp->preq[1];
Vinicius Costa Gomes7034b912011-07-07 18:59:34 -03001030
1031 if (conn->hcon->out) {
1032 keydist = &rsp->init_key_dist;
1033 *keydist &= req->init_key_dist;
1034 } else {
1035 keydist = &rsp->resp_key_dist;
1036 *keydist &= req->resp_key_dist;
1037 }
1038
Vinicius Costa Gomes7034b912011-07-07 18:59:34 -03001039 BT_DBG("keydist 0x%x", *keydist);
1040
1041 if (*keydist & SMP_DIST_ENC_KEY) {
1042 struct smp_cmd_encrypt_info enc;
1043 struct smp_cmd_master_ident ident;
Vinicius Costa Gomesc9839a12012-02-02 21:08:01 -03001044 struct hci_conn *hcon = conn->hcon;
1045 u8 authenticated;
Vinicius Costa Gomes7034b912011-07-07 18:59:34 -03001046 __le16 ediv;
1047
1048 get_random_bytes(enc.ltk, sizeof(enc.ltk));
1049 get_random_bytes(&ediv, sizeof(ediv));
1050 get_random_bytes(ident.rand, sizeof(ident.rand));
1051
1052 smp_send_cmd(conn, SMP_CMD_ENCRYPT_INFO, sizeof(enc), &enc);
1053
Vinicius Costa Gomesc9839a12012-02-02 21:08:01 -03001054 authenticated = hcon->sec_level == BT_SECURITY_HIGH;
Marcel Holtmannce39fb42013-10-13 02:23:39 -07001055 hci_add_ltk(hcon->hdev, &hcon->dst, hcon->dst_type,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001056 HCI_SMP_LTK_SLAVE, 1, authenticated,
1057 enc.ltk, smp->enc_key_size, ediv, ident.rand);
Vinicius Costa Gomes16b90832011-07-07 18:59:39 -03001058
Andrei Emeltchenko58115372012-03-12 12:13:06 +02001059 ident.ediv = ediv;
Vinicius Costa Gomes7034b912011-07-07 18:59:34 -03001060
1061 smp_send_cmd(conn, SMP_CMD_MASTER_IDENT, sizeof(ident), &ident);
1062
1063 *keydist &= ~SMP_DIST_ENC_KEY;
1064 }
1065
1066 if (*keydist & SMP_DIST_ID_KEY) {
1067 struct smp_cmd_ident_addr_info addrinfo;
1068 struct smp_cmd_ident_info idinfo;
1069
1070 /* Send a dummy key */
1071 get_random_bytes(idinfo.irk, sizeof(idinfo.irk));
1072
1073 smp_send_cmd(conn, SMP_CMD_IDENT_INFO, sizeof(idinfo), &idinfo);
1074
1075 /* Just public address */
1076 memset(&addrinfo, 0, sizeof(addrinfo));
Marcel Holtmann2b36a562013-10-13 05:24:00 -07001077 bacpy(&addrinfo.bdaddr, &conn->hcon->src);
Vinicius Costa Gomes7034b912011-07-07 18:59:34 -03001078
1079 smp_send_cmd(conn, SMP_CMD_IDENT_ADDR_INFO, sizeof(addrinfo),
Marcel Holtmannf1560462013-10-13 05:43:25 -07001080 &addrinfo);
Vinicius Costa Gomes7034b912011-07-07 18:59:34 -03001081
1082 *keydist &= ~SMP_DIST_ID_KEY;
1083 }
1084
1085 if (*keydist & SMP_DIST_SIGN) {
1086 struct smp_cmd_sign_info sign;
1087
1088 /* Send a dummy key */
1089 get_random_bytes(sign.csrk, sizeof(sign.csrk));
1090
1091 smp_send_cmd(conn, SMP_CMD_SIGN_INFO, sizeof(sign), &sign);
1092
1093 *keydist &= ~SMP_DIST_SIGN;
1094 }
1095
Vinicius Costa Gomesd26a2342011-08-19 21:06:51 -03001096 if (conn->hcon->out || force) {
Johan Hedberg51a8efd2012-01-16 06:10:31 +02001097 clear_bit(HCI_CONN_LE_SMP_PEND, &conn->hcon->flags);
Gustavo F. Padovan6c9d42a2011-12-20 10:57:27 -02001098 cancel_delayed_work_sync(&conn->security_timer);
Vinicius Costa Gomes8aab4752011-09-05 14:31:31 -03001099 smp_chan_destroy(conn);
Vinicius Costa Gomesd26a2342011-08-19 21:06:51 -03001100 }
1101
Vinicius Costa Gomes7034b912011-07-07 18:59:34 -03001102 return 0;
1103}