Blame view

net/bluetooth/smp.c 22.4 KB
eb492e016   Anderson Briglia   Bluetooth: Implem...
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
  /*
     BlueZ - Bluetooth protocol stack for Linux
     Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
  
     This program is free software; you can redistribute it and/or modify
     it under the terms of the GNU General Public License version 2 as
     published by the Free Software Foundation;
  
     THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
     OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
     FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF THIRD PARTY RIGHTS.
     IN NO EVENT SHALL THE COPYRIGHT HOLDER(S) AND AUTHOR(S) BE LIABLE FOR ANY
     CLAIM, OR ANY SPECIAL INDIRECT OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES
     WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
     ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
     OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  
     ALL LIABILITY, INCLUDING LIABILITY FOR INFRINGEMENT OF ANY PATENTS,
     COPYRIGHTS, TRADEMARKS OR OTHER RIGHTS, RELATING TO USE OF THIS
     SOFTWARE IS DISCLAIMED.
  */
  
  #include <net/bluetooth/bluetooth.h>
  #include <net/bluetooth/hci_core.h>
  #include <net/bluetooth/l2cap.h>
2b64d153a   Brian Gix   Bluetooth: Add MI...
26
  #include <net/bluetooth/mgmt.h>
eb492e016   Anderson Briglia   Bluetooth: Implem...
27
  #include <net/bluetooth/smp.h>
d22ef0bc8   Anderson Briglia   Bluetooth: Add LE...
28
  #include <linux/crypto.h>
f70490e60   Stephen Rothwell   Bluetooth: includ...
29
  #include <linux/scatterlist.h>
d22ef0bc8   Anderson Briglia   Bluetooth: Add LE...
30
  #include <crypto/b128ops.h>
5d3de7df1   Vinicius Costa Gomes   Bluetooth: Add su...
31
  #define SMP_TIMEOUT 30000 /* 30 seconds */
d22ef0bc8   Anderson Briglia   Bluetooth: Add LE...
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
  static inline void swap128(u8 src[16], u8 dst[16])
  {
  	int i;
  	for (i = 0; i < 16; i++)
  		dst[15 - i] = src[i];
  }
  
  static inline void swap56(u8 src[7], u8 dst[7])
  {
  	int i;
  	for (i = 0; i < 7; i++)
  		dst[6 - i] = src[i];
  }
  
  static int smp_e(struct crypto_blkcipher *tfm, const u8 *k, u8 *r)
  {
  	struct blkcipher_desc desc;
  	struct scatterlist sg;
  	int err, iv_len;
  	unsigned char iv[128];
  
  	if (tfm == NULL) {
  		BT_ERR("tfm %p", tfm);
  		return -EINVAL;
  	}
  
  	desc.tfm = tfm;
  	desc.flags = 0;
  
  	err = crypto_blkcipher_setkey(tfm, k, 16);
  	if (err) {
  		BT_ERR("cipher setkey failed: %d", err);
  		return err;
  	}
  
  	sg_init_one(&sg, r, 16);
  
  	iv_len = crypto_blkcipher_ivsize(tfm);
  	if (iv_len) {
  		memset(&iv, 0xff, iv_len);
  		crypto_blkcipher_set_iv(tfm, iv, iv_len);
  	}
  
  	err = crypto_blkcipher_encrypt(&desc, &sg, &sg, 16);
  	if (err)
  		BT_ERR("Encrypt data error %d", err);
  
  	return err;
  }
  
  static int smp_c1(struct crypto_blkcipher *tfm, u8 k[16], u8 r[16],
  		u8 preq[7], u8 pres[7], u8 _iat, bdaddr_t *ia,
  		u8 _rat, bdaddr_t *ra, u8 res[16])
  {
  	u8 p1[16], p2[16];
  	int err;
  
  	memset(p1, 0, 16);
  
  	/* p1 = pres || preq || _rat || _iat */
  	swap56(pres, p1);
  	swap56(preq, p1 + 7);
  	p1[14] = _rat;
  	p1[15] = _iat;
  
  	memset(p2, 0, 16);
  
  	/* p2 = padding || ia || ra */
  	baswap((bdaddr_t *) (p2 + 4), ia);
  	baswap((bdaddr_t *) (p2 + 10), ra);
  
  	/* res = r XOR p1 */
  	u128_xor((u128 *) res, (u128 *) r, (u128 *) p1);
  
  	/* res = e(k, res) */
  	err = smp_e(tfm, k, res);
  	if (err) {
  		BT_ERR("Encrypt data error");
  		return err;
  	}
  
  	/* res = res XOR p2 */
  	u128_xor((u128 *) res, (u128 *) res, (u128 *) p2);
  
  	/* res = e(k, res) */
  	err = smp_e(tfm, k, res);
  	if (err)
  		BT_ERR("Encrypt data error");
  
  	return err;
  }
  
  static int smp_s1(struct crypto_blkcipher *tfm, u8 k[16],
  			u8 r1[16], u8 r2[16], u8 _r[16])
  {
  	int err;
  
  	/* Just least significant octets from r1 and r2 are considered */
  	memcpy(_r, r1 + 8, 8);
  	memcpy(_r + 8, r2 + 8, 8);
  
  	err = smp_e(tfm, k, _r);
  	if (err)
  		BT_ERR("Encrypt data error");
  
  	return err;
  }
  
  static int smp_rand(u8 *buf)
  {
  	get_random_bytes(buf, 16);
  
  	return 0;
  }
eb492e016   Anderson Briglia   Bluetooth: Implem...
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
  
  static struct sk_buff *smp_build_cmd(struct l2cap_conn *conn, u8 code,
  						u16 dlen, void *data)
  {
  	struct sk_buff *skb;
  	struct l2cap_hdr *lh;
  	int len;
  
  	len = L2CAP_HDR_SIZE + sizeof(code) + dlen;
  
  	if (len > conn->mtu)
  		return NULL;
  
  	skb = bt_skb_alloc(len, GFP_ATOMIC);
  	if (!skb)
  		return NULL;
  
  	lh = (struct l2cap_hdr *) skb_put(skb, L2CAP_HDR_SIZE);
  	lh->len = cpu_to_le16(sizeof(code) + dlen);
  	lh->cid = cpu_to_le16(L2CAP_CID_SMP);
  
  	memcpy(skb_put(skb, sizeof(code)), &code, sizeof(code));
  
  	memcpy(skb_put(skb, dlen), data, dlen);
  
  	return skb;
  }
  
  static void smp_send_cmd(struct l2cap_conn *conn, u8 code, u16 len, void *data)
  {
  	struct sk_buff *skb = smp_build_cmd(conn, code, len, data);
  
  	BT_DBG("code 0x%2.2x", code);
  
  	if (!skb)
  		return;
73d80deb7   Luiz Augusto von Dentz   Bluetooth: priori...
182
183
  	skb->priority = HCI_PRIO_MAX;
  	hci_send_acl(conn->hchan, skb, 0);
e2dcd113d   Vinicius Costa Gomes   Bluetooth: Reset ...
184

6c9d42a16   Gustavo F. Padovan   Bluetooth: conver...
185
186
  	cancel_delayed_work_sync(&conn->security_timer);
  	schedule_delayed_work(&conn->security_timer,
e2dcd113d   Vinicius Costa Gomes   Bluetooth: Reset ...
187
  					msecs_to_jiffies(SMP_TIMEOUT));
eb492e016   Anderson Briglia   Bluetooth: Implem...
188
  }
2b64d153a   Brian Gix   Bluetooth: Add MI...
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
  static __u8 authreq_to_seclevel(__u8 authreq)
  {
  	if (authreq & SMP_AUTH_MITM)
  		return BT_SECURITY_HIGH;
  	else
  		return BT_SECURITY_MEDIUM;
  }
  
  static __u8 seclevel_to_authreq(__u8 sec_level)
  {
  	switch (sec_level) {
  	case BT_SECURITY_HIGH:
  		return SMP_AUTH_MITM | SMP_AUTH_BONDING;
  	case BT_SECURITY_MEDIUM:
  		return SMP_AUTH_BONDING;
  	default:
  		return SMP_AUTH_NONE;
  	}
  }
b8e66eaca   Vinicius Costa Gomes   Bluetooth: Add su...
208
  static void build_pairing_cmd(struct l2cap_conn *conn,
54790f73a   Vinicius Costa Gomes   Bluetooth: Fix SM...
209
210
211
  				struct smp_cmd_pairing *req,
  				struct smp_cmd_pairing *rsp,
  				__u8 authreq)
b8e66eaca   Vinicius Costa Gomes   Bluetooth: Add su...
212
  {
2b64d153a   Brian Gix   Bluetooth: Add MI...
213
  	u8 dist_keys = 0;
54790f73a   Vinicius Costa Gomes   Bluetooth: Fix SM...
214

54790f73a   Vinicius Costa Gomes   Bluetooth: Fix SM...
215
  	if (test_bit(HCI_PAIRABLE, &conn->hcon->hdev->flags)) {
ca10b5ee0   Vinicius Costa Gomes   Bluetooth: Remove...
216
  		dist_keys = SMP_DIST_ENC_KEY;
54790f73a   Vinicius Costa Gomes   Bluetooth: Fix SM...
217
  		authreq |= SMP_AUTH_BONDING;
2b64d153a   Brian Gix   Bluetooth: Add MI...
218
219
  	} else {
  		authreq &= ~SMP_AUTH_BONDING;
54790f73a   Vinicius Costa Gomes   Bluetooth: Fix SM...
220
221
222
223
224
225
  	}
  
  	if (rsp == NULL) {
  		req->io_capability = conn->hcon->io_capability;
  		req->oob_flag = SMP_OOB_NOT_PRESENT;
  		req->max_key_size = SMP_MAX_ENC_KEY_SIZE;
2b64d153a   Brian Gix   Bluetooth: Add MI...
226
  		req->init_key_dist = 0;
54790f73a   Vinicius Costa Gomes   Bluetooth: Fix SM...
227
228
229
230
231
232
233
234
  		req->resp_key_dist = dist_keys;
  		req->auth_req = authreq;
  		return;
  	}
  
  	rsp->io_capability = conn->hcon->io_capability;
  	rsp->oob_flag = SMP_OOB_NOT_PRESENT;
  	rsp->max_key_size = SMP_MAX_ENC_KEY_SIZE;
2b64d153a   Brian Gix   Bluetooth: Add MI...
235
  	rsp->init_key_dist = 0;
54790f73a   Vinicius Costa Gomes   Bluetooth: Fix SM...
236
237
  	rsp->resp_key_dist = req->resp_key_dist & dist_keys;
  	rsp->auth_req = authreq;
b8e66eaca   Vinicius Costa Gomes   Bluetooth: Add su...
238
  }
3158c50c3   Vinicius Costa Gomes   Bluetooth: Add ke...
239
240
  static u8 check_enc_key_size(struct l2cap_conn *conn, __u8 max_key_size)
  {
1c1def09c   Vinicius Costa Gomes   Bluetooth: Move S...
241
  	struct smp_chan *smp = conn->smp_chan;
3158c50c3   Vinicius Costa Gomes   Bluetooth: Add ke...
242
243
244
  	if ((max_key_size > SMP_MAX_ENC_KEY_SIZE) ||
  			(max_key_size < SMP_MIN_ENC_KEY_SIZE))
  		return SMP_ENC_KEY_SIZE;
1c1def09c   Vinicius Costa Gomes   Bluetooth: Move S...
245
  	smp->smp_key_size = max_key_size;
3158c50c3   Vinicius Costa Gomes   Bluetooth: Add ke...
246
247
248
  
  	return 0;
  }
4f957a760   Brian Gix   Bluetooth: Centra...
249
250
251
252
253
254
255
256
  static void smp_failure(struct l2cap_conn *conn, u8 reason, u8 send)
  {
  	if (send)
  		smp_send_cmd(conn, SMP_CMD_PAIRING_FAIL, sizeof(reason),
  								&reason);
  
  	clear_bit(HCI_CONN_ENCRYPT_PEND, &conn->hcon->pend);
  	mgmt_auth_failed(conn->hcon->hdev, conn->dst, reason);
6c9d42a16   Gustavo F. Padovan   Bluetooth: conver...
257
  	cancel_delayed_work_sync(&conn->security_timer);
4f957a760   Brian Gix   Bluetooth: Centra...
258
259
  	smp_chan_destroy(conn);
  }
2b64d153a   Brian Gix   Bluetooth: Add MI...
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
  #define JUST_WORKS	0x00
  #define JUST_CFM	0x01
  #define REQ_PASSKEY	0x02
  #define CFM_PASSKEY	0x03
  #define REQ_OOB		0x04
  #define OVERLAP		0xFF
  
  static const u8 gen_method[5][5] = {
  	{ JUST_WORKS,  JUST_CFM,    REQ_PASSKEY, JUST_WORKS, REQ_PASSKEY },
  	{ JUST_WORKS,  JUST_CFM,    REQ_PASSKEY, JUST_WORKS, REQ_PASSKEY },
  	{ CFM_PASSKEY, CFM_PASSKEY, REQ_PASSKEY, JUST_WORKS, CFM_PASSKEY },
  	{ JUST_WORKS,  JUST_CFM,    JUST_WORKS,  JUST_WORKS, JUST_CFM    },
  	{ CFM_PASSKEY, CFM_PASSKEY, REQ_PASSKEY, JUST_WORKS, OVERLAP     },
  };
  
  static int tk_request(struct l2cap_conn *conn, u8 remote_oob, u8 auth,
  						u8 local_io, u8 remote_io)
  {
  	struct hci_conn *hcon = conn->hcon;
  	struct smp_chan *smp = conn->smp_chan;
  	u8 method;
  	u32 passkey = 0;
  	int ret = 0;
  
  	/* Initialize key for JUST WORKS */
  	memset(smp->tk, 0, sizeof(smp->tk));
  	clear_bit(SMP_FLAG_TK_VALID, &smp->smp_flags);
  
  	BT_DBG("tk_request: auth:%d lcl:%d rem:%d", auth, local_io, remote_io);
  
  	/* If neither side wants MITM, use JUST WORKS */
  	/* If either side has unknown io_caps, use JUST WORKS */
  	/* Otherwise, look up method from the table */
  	if (!(auth & SMP_AUTH_MITM) ||
  			local_io > SMP_IO_KEYBOARD_DISPLAY ||
  			remote_io > SMP_IO_KEYBOARD_DISPLAY)
  		method = JUST_WORKS;
  	else
  		method = gen_method[local_io][remote_io];
  
  	/* If not bonding, don't ask user to confirm a Zero TK */
  	if (!(auth & SMP_AUTH_BONDING) && method == JUST_CFM)
  		method = JUST_WORKS;
  
  	/* If Just Works, Continue with Zero TK */
  	if (method == JUST_WORKS) {
  		set_bit(SMP_FLAG_TK_VALID, &smp->smp_flags);
  		return 0;
  	}
  
  	/* Not Just Works/Confirm results in MITM Authentication */
  	if (method != JUST_CFM)
  		set_bit(SMP_FLAG_MITM_AUTH, &smp->smp_flags);
  
  	/* If both devices have Keyoard-Display I/O, the master
  	 * Confirms and the slave Enters the passkey.
  	 */
  	if (method == OVERLAP) {
  		if (hcon->link_mode & HCI_LM_MASTER)
  			method = CFM_PASSKEY;
  		else
  			method = REQ_PASSKEY;
  	}
  
  	/* Generate random passkey. Not valid until confirmed. */
  	if (method == CFM_PASSKEY) {
  		u8 key[16];
  
  		memset(key, 0, sizeof(key));
  		get_random_bytes(&passkey, sizeof(passkey));
  		passkey %= 1000000;
  		put_unaligned_le32(passkey, key);
  		swap128(key, smp->tk);
  		BT_DBG("PassKey: %d", passkey);
  	}
  
  	hci_dev_lock(hcon->hdev);
  
  	if (method == REQ_PASSKEY)
  		ret = mgmt_user_passkey_request(hcon->hdev, conn->dst);
  	else
  		ret = mgmt_user_confirm_request(hcon->hdev, conn->dst,
  						cpu_to_le32(passkey), 0);
  
  	hci_dev_unlock(hcon->hdev);
  
  	return ret;
  }
8aab47574   Vinicius Costa Gomes   Bluetooth: Move S...
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
  static void confirm_work(struct work_struct *work)
  {
  	struct smp_chan *smp = container_of(work, struct smp_chan, confirm);
  	struct l2cap_conn *conn = smp->conn;
  	struct crypto_blkcipher *tfm;
  	struct smp_cmd_pairing_confirm cp;
  	int ret;
  	u8 res[16], reason;
  
  	BT_DBG("conn %p", conn);
  
  	tfm = crypto_alloc_blkcipher("ecb(aes)", 0, CRYPTO_ALG_ASYNC);
  	if (IS_ERR(tfm)) {
  		reason = SMP_UNSPECIFIED;
  		goto error;
  	}
  
  	smp->tfm = tfm;
  
  	if (conn->hcon->out)
  		ret = smp_c1(tfm, smp->tk, smp->prnd, smp->preq, smp->prsp, 0,
  				conn->src, conn->hcon->dst_type, conn->dst,
  				res);
  	else
  		ret = smp_c1(tfm, smp->tk, smp->prnd, smp->preq, smp->prsp,
  				conn->hcon->dst_type, conn->dst, 0, conn->src,
  				res);
  	if (ret) {
  		reason = SMP_UNSPECIFIED;
  		goto error;
  	}
2b64d153a   Brian Gix   Bluetooth: Add MI...
379
  	clear_bit(SMP_FLAG_CFM_PENDING, &smp->smp_flags);
8aab47574   Vinicius Costa Gomes   Bluetooth: Move S...
380
381
382
383
384
385
  	swap128(res, cp.confirm_val);
  	smp_send_cmd(smp->conn, SMP_CMD_PAIRING_CONFIRM, sizeof(cp), &cp);
  
  	return;
  
  error:
4f957a760   Brian Gix   Bluetooth: Centra...
386
  	smp_failure(conn, reason, 1);
8aab47574   Vinicius Costa Gomes   Bluetooth: Move S...
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
  }
  
  static void random_work(struct work_struct *work)
  {
  	struct smp_chan *smp = container_of(work, struct smp_chan, random);
  	struct l2cap_conn *conn = smp->conn;
  	struct hci_conn *hcon = conn->hcon;
  	struct crypto_blkcipher *tfm = smp->tfm;
  	u8 reason, confirm[16], res[16], key[16];
  	int ret;
  
  	if (IS_ERR_OR_NULL(tfm)) {
  		reason = SMP_UNSPECIFIED;
  		goto error;
  	}
  
  	BT_DBG("conn %p %s", conn, conn->hcon->out ? "master" : "slave");
  
  	if (hcon->out)
  		ret = smp_c1(tfm, smp->tk, smp->rrnd, smp->preq, smp->prsp, 0,
  				conn->src, hcon->dst_type, conn->dst,
  				res);
  	else
  		ret = smp_c1(tfm, smp->tk, smp->rrnd, smp->preq, smp->prsp,
  				hcon->dst_type, conn->dst, 0, conn->src,
  				res);
  	if (ret) {
  		reason = SMP_UNSPECIFIED;
  		goto error;
  	}
  
  	swap128(res, confirm);
  
  	if (memcmp(smp->pcnf, confirm, sizeof(smp->pcnf)) != 0) {
  		BT_ERR("Pairing failed (confirmation values mismatch)");
  		reason = SMP_CONFIRM_FAILED;
  		goto error;
  	}
  
  	if (hcon->out) {
  		u8 stk[16], rand[8];
  		__le16 ediv;
  
  		memset(rand, 0, sizeof(rand));
  		ediv = 0;
  
  		smp_s1(tfm, smp->tk, smp->rrnd, smp->prnd, key);
  		swap128(key, stk);
  
  		memset(stk + smp->smp_key_size, 0,
  				SMP_MAX_ENC_KEY_SIZE - smp->smp_key_size);
  
  		if (test_and_set_bit(HCI_CONN_ENCRYPT_PEND, &hcon->pend)) {
  			reason = SMP_UNSPECIFIED;
  			goto error;
  		}
  
  		hci_le_start_enc(hcon, ediv, rand, stk);
  		hcon->enc_key_size = smp->smp_key_size;
  	} else {
  		u8 stk[16], r[16], rand[8];
  		__le16 ediv;
  
  		memset(rand, 0, sizeof(rand));
  		ediv = 0;
  
  		swap128(smp->prnd, r);
  		smp_send_cmd(conn, SMP_CMD_PAIRING_RANDOM, sizeof(r), r);
  
  		smp_s1(tfm, smp->tk, smp->prnd, smp->rrnd, key);
  		swap128(key, stk);
  
  		memset(stk + smp->smp_key_size, 0,
  				SMP_MAX_ENC_KEY_SIZE - smp->smp_key_size);
  
  		hci_add_ltk(hcon->hdev, 0, conn->dst, smp->smp_key_size,
  							ediv, rand, stk);
  	}
  
  	return;
  
  error:
4f957a760   Brian Gix   Bluetooth: Centra...
469
  	smp_failure(conn, reason, 1);
8aab47574   Vinicius Costa Gomes   Bluetooth: Move S...
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
  }
  
  static struct smp_chan *smp_chan_create(struct l2cap_conn *conn)
  {
  	struct smp_chan *smp;
  
  	smp = kzalloc(sizeof(struct smp_chan), GFP_ATOMIC);
  	if (!smp)
  		return NULL;
  
  	INIT_WORK(&smp->confirm, confirm_work);
  	INIT_WORK(&smp->random, random_work);
  
  	smp->conn = conn;
  	conn->smp_chan = smp;
2b64d153a   Brian Gix   Bluetooth: Add MI...
485
  	conn->hcon->smp_conn = conn;
8aab47574   Vinicius Costa Gomes   Bluetooth: Move S...
486
487
488
489
490
491
492
493
  
  	hci_conn_hold(conn->hcon);
  
  	return smp;
  }
  
  void smp_chan_destroy(struct l2cap_conn *conn)
  {
c8eb96907   Brian Gix   Bluetooth: Cleanu...
494
495
496
497
498
499
500
501
502
  	struct smp_chan *smp = conn->smp_chan;
  
  	clear_bit(HCI_CONN_LE_SMP_PEND, &conn->hcon->pend);
  
  	if (smp->tfm)
  		crypto_free_blkcipher(smp->tfm);
  
  	kfree(smp);
  	conn->smp_chan = NULL;
2b64d153a   Brian Gix   Bluetooth: Add MI...
503
  	conn->hcon->smp_conn = NULL;
8aab47574   Vinicius Costa Gomes   Bluetooth: Move S...
504
505
  	hci_conn_put(conn->hcon);
  }
2b64d153a   Brian Gix   Bluetooth: Add MI...
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
  int smp_user_confirm_reply(struct hci_conn *hcon, u16 mgmt_op, __le32 passkey)
  {
  	struct l2cap_conn *conn = hcon->smp_conn;
  	struct smp_chan *smp;
  	u32 value;
  	u8 key[16];
  
  	BT_DBG("");
  
  	if (!conn)
  		return -ENOTCONN;
  
  	smp = conn->smp_chan;
  
  	switch (mgmt_op) {
  	case MGMT_OP_USER_PASSKEY_REPLY:
  		value = le32_to_cpu(passkey);
  		memset(key, 0, sizeof(key));
  		BT_DBG("PassKey: %d", value);
  		put_unaligned_le32(value, key);
  		swap128(key, smp->tk);
  		/* Fall Through */
  	case MGMT_OP_USER_CONFIRM_REPLY:
  		set_bit(SMP_FLAG_TK_VALID, &smp->smp_flags);
  		break;
  	case MGMT_OP_USER_PASSKEY_NEG_REPLY:
  	case MGMT_OP_USER_CONFIRM_NEG_REPLY:
  		smp_failure(conn, SMP_PASSKEY_ENTRY_FAILED, 1);
  		return 0;
  	default:
  		smp_failure(conn, SMP_PASSKEY_ENTRY_FAILED, 1);
  		return -EOPNOTSUPP;
  	}
  
  	/* If it is our turn to send Pairing Confirm, do so now */
  	if (test_bit(SMP_FLAG_CFM_PENDING, &smp->smp_flags))
  		queue_work(hcon->hdev->workqueue, &smp->confirm);
  
  	return 0;
  }
da85e5e5a   Vinicius Costa Gomes   Bluetooth: Add su...
546
  static u8 smp_cmd_pairing_req(struct l2cap_conn *conn, struct sk_buff *skb)
88ba43b66   Anderson Briglia   Bluetooth: Add si...
547
  {
3158c50c3   Vinicius Costa Gomes   Bluetooth: Add ke...
548
  	struct smp_cmd_pairing rsp, *req = (void *) skb->data;
8aab47574   Vinicius Costa Gomes   Bluetooth: Move S...
549
  	struct smp_chan *smp;
3158c50c3   Vinicius Costa Gomes   Bluetooth: Add ke...
550
  	u8 key_size;
2b64d153a   Brian Gix   Bluetooth: Add MI...
551
  	u8 auth = SMP_AUTH_NONE;
8aab47574   Vinicius Costa Gomes   Bluetooth: Move S...
552
  	int ret;
88ba43b66   Anderson Briglia   Bluetooth: Add si...
553
554
  
  	BT_DBG("conn %p", conn);
2b64d153a   Brian Gix   Bluetooth: Add MI...
555
556
  	if (conn->hcon->link_mode & HCI_LM_MASTER)
  		return SMP_CMD_NOTSUPP;
d26a23454   Vinicius Costa Gomes   Bluetooth: Add a ...
557
  	if (!test_and_set_bit(HCI_CONN_LE_SMP_PEND, &conn->hcon->pend))
8aab47574   Vinicius Costa Gomes   Bluetooth: Move S...
558
559
560
  		smp = smp_chan_create(conn);
  
  	smp = conn->smp_chan;
d26a23454   Vinicius Costa Gomes   Bluetooth: Add a ...
561

1c1def09c   Vinicius Costa Gomes   Bluetooth: Move S...
562
563
  	smp->preq[0] = SMP_CMD_PAIRING_REQ;
  	memcpy(&smp->preq[1], req, sizeof(*req));
3158c50c3   Vinicius Costa Gomes   Bluetooth: Add ke...
564
  	skb_pull(skb, sizeof(*req));
88ba43b66   Anderson Briglia   Bluetooth: Add si...
565

2b64d153a   Brian Gix   Bluetooth: Add MI...
566
567
568
  	/* We didn't start the pairing, so match remote */
  	if (req->auth_req & SMP_AUTH_BONDING)
  		auth = req->auth_req;
da85e5e5a   Vinicius Costa Gomes   Bluetooth: Add su...
569

2b64d153a   Brian Gix   Bluetooth: Add MI...
570
  	build_pairing_cmd(conn, req, &rsp, auth);
3158c50c3   Vinicius Costa Gomes   Bluetooth: Add ke...
571
572
573
574
  
  	key_size = min(req->max_key_size, rsp.max_key_size);
  	if (check_enc_key_size(conn, key_size))
  		return SMP_ENC_KEY_SIZE;
88ba43b66   Anderson Briglia   Bluetooth: Add si...
575

8aab47574   Vinicius Costa Gomes   Bluetooth: Move S...
576
577
578
  	ret = smp_rand(smp->prnd);
  	if (ret)
  		return SMP_UNSPECIFIED;
1c1def09c   Vinicius Costa Gomes   Bluetooth: Move S...
579
580
  	smp->prsp[0] = SMP_CMD_PAIRING_RSP;
  	memcpy(&smp->prsp[1], &rsp, sizeof(rsp));
f01ead315   Anderson Briglia   Bluetooth: Add SM...
581

3158c50c3   Vinicius Costa Gomes   Bluetooth: Add ke...
582
  	smp_send_cmd(conn, SMP_CMD_PAIRING_RSP, sizeof(rsp), &rsp);
da85e5e5a   Vinicius Costa Gomes   Bluetooth: Add su...
583

2b64d153a   Brian Gix   Bluetooth: Add MI...
584
585
586
587
  	/* Request setup of TK */
  	ret = tk_request(conn, 0, auth, rsp.io_capability, req->io_capability);
  	if (ret)
  		return SMP_UNSPECIFIED;
da85e5e5a   Vinicius Costa Gomes   Bluetooth: Add su...
588
  	return 0;
88ba43b66   Anderson Briglia   Bluetooth: Add si...
589
  }
da85e5e5a   Vinicius Costa Gomes   Bluetooth: Add su...
590
  static u8 smp_cmd_pairing_rsp(struct l2cap_conn *conn, struct sk_buff *skb)
88ba43b66   Anderson Briglia   Bluetooth: Add si...
591
  {
3158c50c3   Vinicius Costa Gomes   Bluetooth: Add ke...
592
  	struct smp_cmd_pairing *req, *rsp = (void *) skb->data;
1c1def09c   Vinicius Costa Gomes   Bluetooth: Move S...
593
  	struct smp_chan *smp = conn->smp_chan;
8aab47574   Vinicius Costa Gomes   Bluetooth: Move S...
594
  	struct hci_dev *hdev = conn->hcon->hdev;
2b64d153a   Brian Gix   Bluetooth: Add MI...
595
  	u8 key_size, auth = SMP_AUTH_NONE;
7d24ddcc1   Anderson Briglia   Bluetooth: Add SM...
596
  	int ret;
88ba43b66   Anderson Briglia   Bluetooth: Add si...
597
598
  
  	BT_DBG("conn %p", conn);
2b64d153a   Brian Gix   Bluetooth: Add MI...
599
600
  	if (!(conn->hcon->link_mode & HCI_LM_MASTER))
  		return SMP_CMD_NOTSUPP;
3158c50c3   Vinicius Costa Gomes   Bluetooth: Add ke...
601
  	skb_pull(skb, sizeof(*rsp));
1c1def09c   Vinicius Costa Gomes   Bluetooth: Move S...
602
  	req = (void *) &smp->preq[1];
da85e5e5a   Vinicius Costa Gomes   Bluetooth: Add su...
603

3158c50c3   Vinicius Costa Gomes   Bluetooth: Add ke...
604
605
606
  	key_size = min(req->max_key_size, rsp->max_key_size);
  	if (check_enc_key_size(conn, key_size))
  		return SMP_ENC_KEY_SIZE;
1c1def09c   Vinicius Costa Gomes   Bluetooth: Move S...
607
  	ret = smp_rand(smp->prnd);
7d24ddcc1   Anderson Briglia   Bluetooth: Add SM...
608
  	if (ret)
da85e5e5a   Vinicius Costa Gomes   Bluetooth: Add su...
609
  		return SMP_UNSPECIFIED;
7d24ddcc1   Anderson Briglia   Bluetooth: Add SM...
610

8aab47574   Vinicius Costa Gomes   Bluetooth: Move S...
611
612
  	smp->prsp[0] = SMP_CMD_PAIRING_RSP;
  	memcpy(&smp->prsp[1], rsp, sizeof(*rsp));
7d24ddcc1   Anderson Briglia   Bluetooth: Add SM...
613

2b64d153a   Brian Gix   Bluetooth: Add MI...
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
  	if ((req->auth_req & SMP_AUTH_BONDING) &&
  			(rsp->auth_req & SMP_AUTH_BONDING))
  		auth = SMP_AUTH_BONDING;
  
  	auth |= (req->auth_req | rsp->auth_req) & SMP_AUTH_MITM;
  
  	ret = tk_request(conn, 0, auth, rsp->io_capability, req->io_capability);
  	if (ret)
  		return SMP_UNSPECIFIED;
  
  	set_bit(SMP_FLAG_CFM_PENDING, &smp->smp_flags);
  
  	/* Can't compose response until we have been confirmed */
  	if (!test_bit(SMP_FLAG_TK_VALID, &smp->smp_flags))
  		return 0;
8aab47574   Vinicius Costa Gomes   Bluetooth: Move S...
629
  	queue_work(hdev->workqueue, &smp->confirm);
da85e5e5a   Vinicius Costa Gomes   Bluetooth: Add su...
630
631
  
  	return 0;
88ba43b66   Anderson Briglia   Bluetooth: Add si...
632
  }
da85e5e5a   Vinicius Costa Gomes   Bluetooth: Add su...
633
  static u8 smp_cmd_pairing_confirm(struct l2cap_conn *conn, struct sk_buff *skb)
88ba43b66   Anderson Briglia   Bluetooth: Add si...
634
  {
1c1def09c   Vinicius Costa Gomes   Bluetooth: Move S...
635
  	struct smp_chan *smp = conn->smp_chan;
8aab47574   Vinicius Costa Gomes   Bluetooth: Move S...
636
  	struct hci_dev *hdev = conn->hcon->hdev;
7d24ddcc1   Anderson Briglia   Bluetooth: Add SM...
637

88ba43b66   Anderson Briglia   Bluetooth: Add si...
638
  	BT_DBG("conn %p %s", conn, conn->hcon->out ? "master" : "slave");
1c1def09c   Vinicius Costa Gomes   Bluetooth: Move S...
639
640
  	memcpy(smp->pcnf, skb->data, sizeof(smp->pcnf));
  	skb_pull(skb, sizeof(smp->pcnf));
88ba43b66   Anderson Briglia   Bluetooth: Add si...
641

7d24ddcc1   Anderson Briglia   Bluetooth: Add SM...
642
643
  	if (conn->hcon->out) {
  		u8 random[16];
88ba43b66   Anderson Briglia   Bluetooth: Add si...
644

1c1def09c   Vinicius Costa Gomes   Bluetooth: Move S...
645
  		swap128(smp->prnd, random);
88ba43b66   Anderson Briglia   Bluetooth: Add si...
646
  		smp_send_cmd(conn, SMP_CMD_PAIRING_RANDOM, sizeof(random),
7d24ddcc1   Anderson Briglia   Bluetooth: Add SM...
647
  								random);
2b64d153a   Brian Gix   Bluetooth: Add MI...
648
  	} else if (test_bit(SMP_FLAG_TK_VALID, &smp->smp_flags)) {
8aab47574   Vinicius Costa Gomes   Bluetooth: Move S...
649
  		queue_work(hdev->workqueue, &smp->confirm);
2b64d153a   Brian Gix   Bluetooth: Add MI...
650
651
  	} else {
  		set_bit(SMP_FLAG_CFM_PENDING, &smp->smp_flags);
88ba43b66   Anderson Briglia   Bluetooth: Add si...
652
  	}
da85e5e5a   Vinicius Costa Gomes   Bluetooth: Add su...
653
654
  
  	return 0;
88ba43b66   Anderson Briglia   Bluetooth: Add si...
655
  }
da85e5e5a   Vinicius Costa Gomes   Bluetooth: Add su...
656
  static u8 smp_cmd_pairing_random(struct l2cap_conn *conn, struct sk_buff *skb)
88ba43b66   Anderson Briglia   Bluetooth: Add si...
657
  {
1c1def09c   Vinicius Costa Gomes   Bluetooth: Move S...
658
  	struct smp_chan *smp = conn->smp_chan;
8aab47574   Vinicius Costa Gomes   Bluetooth: Move S...
659
  	struct hci_dev *hdev = conn->hcon->hdev;
7d24ddcc1   Anderson Briglia   Bluetooth: Add SM...
660

8aab47574   Vinicius Costa Gomes   Bluetooth: Move S...
661
  	BT_DBG("conn %p", conn);
3158c50c3   Vinicius Costa Gomes   Bluetooth: Add ke...
662

8aab47574   Vinicius Costa Gomes   Bluetooth: Move S...
663
664
  	swap128(skb->data, smp->rrnd);
  	skb_pull(skb, sizeof(smp->rrnd));
e7e62c859   Vinicius Costa Gomes   Bluetooth: Use th...
665

8aab47574   Vinicius Costa Gomes   Bluetooth: Move S...
666
  	queue_work(hdev->workqueue, &smp->random);
da85e5e5a   Vinicius Costa Gomes   Bluetooth: Add su...
667
668
  
  	return 0;
88ba43b66   Anderson Briglia   Bluetooth: Add si...
669
  }
988c5997d   Vinicius Costa Gomes   Bluetooth: Use th...
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
  static u8 smp_ltk_encrypt(struct l2cap_conn *conn)
  {
  	struct link_key *key;
  	struct key_master_id *master;
  	struct hci_conn *hcon = conn->hcon;
  
  	key = hci_find_link_key_type(hcon->hdev, conn->dst,
  						HCI_LK_SMP_LTK);
  	if (!key)
  		return 0;
  
  	if (test_and_set_bit(HCI_CONN_ENCRYPT_PEND,
  					&hcon->pend))
  		return 1;
  
  	master = (void *) key->data;
  	hci_le_start_enc(hcon, master->ediv, master->rand,
  						key->val);
  	hcon->enc_key_size = key->pin_len;
  
  	return 1;
  
  }
da85e5e5a   Vinicius Costa Gomes   Bluetooth: Add su...
693
  static u8 smp_cmd_security_req(struct l2cap_conn *conn, struct sk_buff *skb)
88ba43b66   Anderson Briglia   Bluetooth: Add si...
694
695
696
  {
  	struct smp_cmd_security_req *rp = (void *) skb->data;
  	struct smp_cmd_pairing cp;
f1cb9af55   Vinicius Costa Gomes   Bluetooth: Add su...
697
  	struct hci_conn *hcon = conn->hcon;
8aab47574   Vinicius Costa Gomes   Bluetooth: Move S...
698
  	struct smp_chan *smp;
88ba43b66   Anderson Briglia   Bluetooth: Add si...
699
700
  
  	BT_DBG("conn %p", conn);
2b64d153a   Brian Gix   Bluetooth: Add MI...
701
  	hcon->pending_sec_level = authreq_to_seclevel(rp->auth_req);
feb45eb59   Vinicius Costa Gomes   Bluetooth: Fix no...
702

988c5997d   Vinicius Costa Gomes   Bluetooth: Use th...
703
704
  	if (smp_ltk_encrypt(conn))
  		return 0;
d26a23454   Vinicius Costa Gomes   Bluetooth: Add a ...
705
  	if (test_and_set_bit(HCI_CONN_LE_SMP_PEND, &hcon->pend))
da85e5e5a   Vinicius Costa Gomes   Bluetooth: Add su...
706
  		return 0;
f1cb9af55   Vinicius Costa Gomes   Bluetooth: Add su...
707

8aab47574   Vinicius Costa Gomes   Bluetooth: Move S...
708
  	smp = smp_chan_create(conn);
d26a23454   Vinicius Costa Gomes   Bluetooth: Add a ...
709

88ba43b66   Anderson Briglia   Bluetooth: Add si...
710
  	skb_pull(skb, sizeof(*rp));
88ba43b66   Anderson Briglia   Bluetooth: Add si...
711

da85e5e5a   Vinicius Costa Gomes   Bluetooth: Add su...
712
  	memset(&cp, 0, sizeof(cp));
54790f73a   Vinicius Costa Gomes   Bluetooth: Fix SM...
713
  	build_pairing_cmd(conn, &cp, NULL, rp->auth_req);
88ba43b66   Anderson Briglia   Bluetooth: Add si...
714

1c1def09c   Vinicius Costa Gomes   Bluetooth: Move S...
715
716
  	smp->preq[0] = SMP_CMD_PAIRING_REQ;
  	memcpy(&smp->preq[1], &cp, sizeof(cp));
f01ead315   Anderson Briglia   Bluetooth: Add SM...
717

88ba43b66   Anderson Briglia   Bluetooth: Add si...
718
  	smp_send_cmd(conn, SMP_CMD_PAIRING_REQ, sizeof(cp), &cp);
f1cb9af55   Vinicius Costa Gomes   Bluetooth: Add su...
719

da85e5e5a   Vinicius Costa Gomes   Bluetooth: Add su...
720
  	return 0;
88ba43b66   Anderson Briglia   Bluetooth: Add si...
721
  }
eb492e016   Anderson Briglia   Bluetooth: Implem...
722
723
  int smp_conn_security(struct l2cap_conn *conn, __u8 sec_level)
  {
3a0259bb8   Vinicius Costa Gomes   Bluetooth: Add su...
724
  	struct hci_conn *hcon = conn->hcon;
1c1def09c   Vinicius Costa Gomes   Bluetooth: Move S...
725
  	struct smp_chan *smp = conn->smp_chan;
2b64d153a   Brian Gix   Bluetooth: Add MI...
726
  	__u8 authreq;
eb492e016   Anderson Briglia   Bluetooth: Implem...
727

3a0259bb8   Vinicius Costa Gomes   Bluetooth: Add su...
728
  	BT_DBG("conn %p hcon %p level 0x%2.2x", conn, hcon, sec_level);
2e65c9d2c   Andre Guedes   Bluetooth: Remove...
729
730
  	if (!lmp_host_le_capable(hcon->hdev))
  		return 1;
f1cb9af55   Vinicius Costa Gomes   Bluetooth: Add su...
731
732
  	if (sec_level == BT_SECURITY_LOW)
  		return 1;
eb492e016   Anderson Briglia   Bluetooth: Implem...
733

f1cb9af55   Vinicius Costa Gomes   Bluetooth: Add su...
734
  	if (hcon->sec_level >= sec_level)
eb492e016   Anderson Briglia   Bluetooth: Implem...
735
  		return 1;
f1cb9af55   Vinicius Costa Gomes   Bluetooth: Add su...
736

988c5997d   Vinicius Costa Gomes   Bluetooth: Use th...
737
738
  	if (hcon->link_mode & HCI_LM_MASTER)
  		if (smp_ltk_encrypt(conn))
02bc74556   Vinicius Costa Gomes   Bluetooth: Use th...
739
  			goto done;
d26a23454   Vinicius Costa Gomes   Bluetooth: Add a ...
740
741
742
  
  	if (test_and_set_bit(HCI_CONN_LE_SMP_PEND, &hcon->pend))
  		return 0;
8aab47574   Vinicius Costa Gomes   Bluetooth: Move S...
743
  	smp = smp_chan_create(conn);
2b64d153a   Brian Gix   Bluetooth: Add MI...
744
745
746
747
  	if (!smp)
  		return 1;
  
  	authreq = seclevel_to_authreq(sec_level);
d26a23454   Vinicius Costa Gomes   Bluetooth: Add a ...
748

d26a23454   Vinicius Costa Gomes   Bluetooth: Add a ...
749
750
  	if (hcon->link_mode & HCI_LM_MASTER) {
  		struct smp_cmd_pairing cp;
f01ead315   Anderson Briglia   Bluetooth: Add SM...
751

2b64d153a   Brian Gix   Bluetooth: Add MI...
752
  		build_pairing_cmd(conn, &cp, NULL, authreq);
1c1def09c   Vinicius Costa Gomes   Bluetooth: Move S...
753
754
  		smp->preq[0] = SMP_CMD_PAIRING_REQ;
  		memcpy(&smp->preq[1], &cp, sizeof(cp));
f01ead315   Anderson Briglia   Bluetooth: Add SM...
755

eb492e016   Anderson Briglia   Bluetooth: Implem...
756
757
758
  		smp_send_cmd(conn, SMP_CMD_PAIRING_REQ, sizeof(cp), &cp);
  	} else {
  		struct smp_cmd_security_req cp;
2b64d153a   Brian Gix   Bluetooth: Add MI...
759
  		cp.auth_req = authreq;
eb492e016   Anderson Briglia   Bluetooth: Implem...
760
761
  		smp_send_cmd(conn, SMP_CMD_SECURITY_REQ, sizeof(cp), &cp);
  	}
02bc74556   Vinicius Costa Gomes   Bluetooth: Use th...
762
  done:
f1cb9af55   Vinicius Costa Gomes   Bluetooth: Add su...
763
  	hcon->pending_sec_level = sec_level;
f1cb9af55   Vinicius Costa Gomes   Bluetooth: Add su...
764

eb492e016   Anderson Briglia   Bluetooth: Implem...
765
766
  	return 0;
  }
7034b911a   Vinicius Costa Gomes   Bluetooth: Add su...
767
768
  static int smp_cmd_encrypt_info(struct l2cap_conn *conn, struct sk_buff *skb)
  {
16b908396   Vinicius Costa Gomes   Bluetooth: Add su...
769
  	struct smp_cmd_encrypt_info *rp = (void *) skb->data;
1c1def09c   Vinicius Costa Gomes   Bluetooth: Move S...
770
  	struct smp_chan *smp = conn->smp_chan;
16b908396   Vinicius Costa Gomes   Bluetooth: Add su...
771
772
  
  	skb_pull(skb, sizeof(*rp));
1c1def09c   Vinicius Costa Gomes   Bluetooth: Move S...
773
  	memcpy(smp->tk, rp->ltk, sizeof(smp->tk));
16b908396   Vinicius Costa Gomes   Bluetooth: Add su...
774

7034b911a   Vinicius Costa Gomes   Bluetooth: Add su...
775
776
777
778
779
  	return 0;
  }
  
  static int smp_cmd_master_ident(struct l2cap_conn *conn, struct sk_buff *skb)
  {
16b908396   Vinicius Costa Gomes   Bluetooth: Add su...
780
  	struct smp_cmd_master_ident *rp = (void *) skb->data;
1c1def09c   Vinicius Costa Gomes   Bluetooth: Move S...
781
  	struct smp_chan *smp = conn->smp_chan;
16b908396   Vinicius Costa Gomes   Bluetooth: Add su...
782
783
  
  	skb_pull(skb, sizeof(*rp));
7034b911a   Vinicius Costa Gomes   Bluetooth: Add su...
784

3573b80c4   Hemant Gupta   Bluetooth: Incorr...
785
  	hci_add_ltk(conn->hcon->hdev, 1, conn->dst, smp->smp_key_size,
1c1def09c   Vinicius Costa Gomes   Bluetooth: Move S...
786
  						rp->ediv, rp->rand, smp->tk);
7034b911a   Vinicius Costa Gomes   Bluetooth: Add su...
787
788
789
790
791
  
  	smp_distribute_keys(conn, 1);
  
  	return 0;
  }
eb492e016   Anderson Briglia   Bluetooth: Implem...
792
793
794
795
796
  int smp_sig_channel(struct l2cap_conn *conn, struct sk_buff *skb)
  {
  	__u8 code = skb->data[0];
  	__u8 reason;
  	int err = 0;
2e65c9d2c   Andre Guedes   Bluetooth: Remove...
797
798
799
800
801
  	if (!lmp_host_le_capable(conn->hcon->hdev)) {
  		err = -ENOTSUPP;
  		reason = SMP_PAIRING_NOTSUPP;
  		goto done;
  	}
eb492e016   Anderson Briglia   Bluetooth: Implem...
802
803
804
805
  	skb_pull(skb, sizeof(code));
  
  	switch (code) {
  	case SMP_CMD_PAIRING_REQ:
da85e5e5a   Vinicius Costa Gomes   Bluetooth: Add su...
806
  		reason = smp_cmd_pairing_req(conn, skb);
eb492e016   Anderson Briglia   Bluetooth: Implem...
807
808
809
  		break;
  
  	case SMP_CMD_PAIRING_FAIL:
4f957a760   Brian Gix   Bluetooth: Centra...
810
  		smp_failure(conn, skb->data[0], 0);
da85e5e5a   Vinicius Costa Gomes   Bluetooth: Add su...
811
812
  		reason = 0;
  		err = -EPERM;
eb492e016   Anderson Briglia   Bluetooth: Implem...
813
814
815
  		break;
  
  	case SMP_CMD_PAIRING_RSP:
da85e5e5a   Vinicius Costa Gomes   Bluetooth: Add su...
816
  		reason = smp_cmd_pairing_rsp(conn, skb);
88ba43b66   Anderson Briglia   Bluetooth: Add si...
817
818
819
  		break;
  
  	case SMP_CMD_SECURITY_REQ:
da85e5e5a   Vinicius Costa Gomes   Bluetooth: Add su...
820
  		reason = smp_cmd_security_req(conn, skb);
88ba43b66   Anderson Briglia   Bluetooth: Add si...
821
  		break;
eb492e016   Anderson Briglia   Bluetooth: Implem...
822
  	case SMP_CMD_PAIRING_CONFIRM:
da85e5e5a   Vinicius Costa Gomes   Bluetooth: Add su...
823
  		reason = smp_cmd_pairing_confirm(conn, skb);
88ba43b66   Anderson Briglia   Bluetooth: Add si...
824
  		break;
eb492e016   Anderson Briglia   Bluetooth: Implem...
825
  	case SMP_CMD_PAIRING_RANDOM:
da85e5e5a   Vinicius Costa Gomes   Bluetooth: Add su...
826
  		reason = smp_cmd_pairing_random(conn, skb);
88ba43b66   Anderson Briglia   Bluetooth: Add si...
827
  		break;
eb492e016   Anderson Briglia   Bluetooth: Implem...
828
  	case SMP_CMD_ENCRYPT_INFO:
7034b911a   Vinicius Costa Gomes   Bluetooth: Add su...
829
830
  		reason = smp_cmd_encrypt_info(conn, skb);
  		break;
eb492e016   Anderson Briglia   Bluetooth: Implem...
831
  	case SMP_CMD_MASTER_IDENT:
7034b911a   Vinicius Costa Gomes   Bluetooth: Add su...
832
833
  		reason = smp_cmd_master_ident(conn, skb);
  		break;
eb492e016   Anderson Briglia   Bluetooth: Implem...
834
835
836
  	case SMP_CMD_IDENT_INFO:
  	case SMP_CMD_IDENT_ADDR_INFO:
  	case SMP_CMD_SIGN_INFO:
7034b911a   Vinicius Costa Gomes   Bluetooth: Add su...
837
838
839
  		/* Just ignored */
  		reason = 0;
  		break;
eb492e016   Anderson Briglia   Bluetooth: Implem...
840
841
842
843
  	default:
  		BT_DBG("Unknown command code 0x%2.2x", code);
  
  		reason = SMP_CMD_NOTSUPP;
eb492e016   Anderson Briglia   Bluetooth: Implem...
844
  		err = -EOPNOTSUPP;
3a0259bb8   Vinicius Costa Gomes   Bluetooth: Add su...
845
  		goto done;
eb492e016   Anderson Briglia   Bluetooth: Implem...
846
  	}
3a0259bb8   Vinicius Costa Gomes   Bluetooth: Add su...
847
848
  done:
  	if (reason)
4f957a760   Brian Gix   Bluetooth: Centra...
849
  		smp_failure(conn, reason, 1);
3a0259bb8   Vinicius Costa Gomes   Bluetooth: Add su...
850

eb492e016   Anderson Briglia   Bluetooth: Implem...
851
852
853
  	kfree_skb(skb);
  	return err;
  }
7034b911a   Vinicius Costa Gomes   Bluetooth: Add su...
854
855
856
857
  
  int smp_distribute_keys(struct l2cap_conn *conn, __u8 force)
  {
  	struct smp_cmd_pairing *req, *rsp;
1c1def09c   Vinicius Costa Gomes   Bluetooth: Move S...
858
  	struct smp_chan *smp = conn->smp_chan;
7034b911a   Vinicius Costa Gomes   Bluetooth: Add su...
859
860
861
  	__u8 *keydist;
  
  	BT_DBG("conn %p force %d", conn, force);
d26a23454   Vinicius Costa Gomes   Bluetooth: Add a ...
862
863
  	if (!test_bit(HCI_CONN_LE_SMP_PEND, &conn->hcon->pend))
  		return 0;
1c1def09c   Vinicius Costa Gomes   Bluetooth: Move S...
864
  	rsp = (void *) &smp->prsp[1];
7034b911a   Vinicius Costa Gomes   Bluetooth: Add su...
865
866
867
868
  
  	/* The responder sends its keys first */
  	if (!force && conn->hcon->out && (rsp->resp_key_dist & 0x07))
  		return 0;
1c1def09c   Vinicius Costa Gomes   Bluetooth: Move S...
869
  	req = (void *) &smp->preq[1];
7034b911a   Vinicius Costa Gomes   Bluetooth: Add su...
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
  
  	if (conn->hcon->out) {
  		keydist = &rsp->init_key_dist;
  		*keydist &= req->init_key_dist;
  	} else {
  		keydist = &rsp->resp_key_dist;
  		*keydist &= req->resp_key_dist;
  	}
  
  
  	BT_DBG("keydist 0x%x", *keydist);
  
  	if (*keydist & SMP_DIST_ENC_KEY) {
  		struct smp_cmd_encrypt_info enc;
  		struct smp_cmd_master_ident ident;
  		__le16 ediv;
  
  		get_random_bytes(enc.ltk, sizeof(enc.ltk));
  		get_random_bytes(&ediv, sizeof(ediv));
  		get_random_bytes(ident.rand, sizeof(ident.rand));
  
  		smp_send_cmd(conn, SMP_CMD_ENCRYPT_INFO, sizeof(enc), &enc);
1c1def09c   Vinicius Costa Gomes   Bluetooth: Move S...
892
  		hci_add_ltk(conn->hcon->hdev, 1, conn->dst, smp->smp_key_size,
726b4ffca   Vinicius Costa Gomes   Bluetooth: Add su...
893
  						ediv, ident.rand, enc.ltk);
16b908396   Vinicius Costa Gomes   Bluetooth: Add su...
894

7034b911a   Vinicius Costa Gomes   Bluetooth: Add su...
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
  		ident.ediv = cpu_to_le16(ediv);
  
  		smp_send_cmd(conn, SMP_CMD_MASTER_IDENT, sizeof(ident), &ident);
  
  		*keydist &= ~SMP_DIST_ENC_KEY;
  	}
  
  	if (*keydist & SMP_DIST_ID_KEY) {
  		struct smp_cmd_ident_addr_info addrinfo;
  		struct smp_cmd_ident_info idinfo;
  
  		/* Send a dummy key */
  		get_random_bytes(idinfo.irk, sizeof(idinfo.irk));
  
  		smp_send_cmd(conn, SMP_CMD_IDENT_INFO, sizeof(idinfo), &idinfo);
  
  		/* Just public address */
  		memset(&addrinfo, 0, sizeof(addrinfo));
  		bacpy(&addrinfo.bdaddr, conn->src);
  
  		smp_send_cmd(conn, SMP_CMD_IDENT_ADDR_INFO, sizeof(addrinfo),
  								&addrinfo);
  
  		*keydist &= ~SMP_DIST_ID_KEY;
  	}
  
  	if (*keydist & SMP_DIST_SIGN) {
  		struct smp_cmd_sign_info sign;
  
  		/* Send a dummy key */
  		get_random_bytes(sign.csrk, sizeof(sign.csrk));
  
  		smp_send_cmd(conn, SMP_CMD_SIGN_INFO, sizeof(sign), &sign);
  
  		*keydist &= ~SMP_DIST_SIGN;
  	}
d26a23454   Vinicius Costa Gomes   Bluetooth: Add a ...
931
932
  	if (conn->hcon->out || force) {
  		clear_bit(HCI_CONN_LE_SMP_PEND, &conn->hcon->pend);
6c9d42a16   Gustavo F. Padovan   Bluetooth: conver...
933
  		cancel_delayed_work_sync(&conn->security_timer);
8aab47574   Vinicius Costa Gomes   Bluetooth: Move S...
934
  		smp_chan_destroy(conn);
d26a23454   Vinicius Costa Gomes   Bluetooth: Add a ...
935
  	}
7034b911a   Vinicius Costa Gomes   Bluetooth: Add su...
936
937
  	return 0;
  }