diff options
author | Vinicius Costa Gomes <vinicius.gomes@openbossa.org> | 2011-09-05 13:31:31 -0400 |
---|---|---|
committer | Gustavo F. Padovan <padovan@profusion.mobi> | 2011-09-21 11:58:12 -0400 |
commit | 8aab47574a7f5b46a4cdbc6fd820ab34e6c5dbf9 (patch) | |
tree | 69f31fec9ff2266d848f5e1f974928a65030c4e4 /net/bluetooth | |
parent | 1c1def09c446aae441410b70e6439ffe44dee866 (diff) |
Bluetooth: Move SMP crypto functions to a workqueue
The function crypto_blkcipher_setkey() called by smp_e()
can sleep, so all the crypto work has to be moved to
hci_dev workqueue.
Signed-off-by: Vinicius Costa Gomes <vinicius.gomes@openbossa.org>
Signed-off-by: Gustavo F. Padovan <padovan@profusion.mobi>
Diffstat (limited to 'net/bluetooth')
-rw-r--r-- | net/bluetooth/l2cap_core.c | 2 | ||||
-rw-r--r-- | net/bluetooth/smp.c | 277 |
2 files changed, 177 insertions, 102 deletions
diff --git a/net/bluetooth/l2cap_core.c b/net/bluetooth/l2cap_core.c index e699837c3b8c..4bfb7d22d171 100644 --- a/net/bluetooth/l2cap_core.c +++ b/net/bluetooth/l2cap_core.c | |||
@@ -991,7 +991,7 @@ static void l2cap_conn_del(struct hci_conn *hcon, int err) | |||
991 | 991 | ||
992 | if (test_and_clear_bit(HCI_CONN_LE_SMP_PEND, &hcon->pend)) { | 992 | if (test_and_clear_bit(HCI_CONN_LE_SMP_PEND, &hcon->pend)) { |
993 | del_timer(&conn->security_timer); | 993 | del_timer(&conn->security_timer); |
994 | hci_conn_put(hcon); | 994 | smp_chan_destroy(conn); |
995 | } | 995 | } |
996 | 996 | ||
997 | hcon->l2cap_data = NULL; | 997 | hcon->l2cap_data = NULL; |
diff --git a/net/bluetooth/smp.c b/net/bluetooth/smp.c index b5e1b4a300cc..03489e5815ef 100644 --- a/net/bluetooth/smp.c +++ b/net/bluetooth/smp.c | |||
@@ -243,16 +243,170 @@ static u8 check_enc_key_size(struct l2cap_conn *conn, __u8 max_key_size) | |||
243 | return 0; | 243 | return 0; |
244 | } | 244 | } |
245 | 245 | ||
246 | static void confirm_work(struct work_struct *work) | ||
247 | { | ||
248 | struct smp_chan *smp = container_of(work, struct smp_chan, confirm); | ||
249 | struct l2cap_conn *conn = smp->conn; | ||
250 | struct crypto_blkcipher *tfm; | ||
251 | struct smp_cmd_pairing_confirm cp; | ||
252 | int ret; | ||
253 | u8 res[16], reason; | ||
254 | |||
255 | BT_DBG("conn %p", conn); | ||
256 | |||
257 | tfm = crypto_alloc_blkcipher("ecb(aes)", 0, CRYPTO_ALG_ASYNC); | ||
258 | if (IS_ERR(tfm)) { | ||
259 | reason = SMP_UNSPECIFIED; | ||
260 | goto error; | ||
261 | } | ||
262 | |||
263 | smp->tfm = tfm; | ||
264 | |||
265 | if (conn->hcon->out) | ||
266 | ret = smp_c1(tfm, smp->tk, smp->prnd, smp->preq, smp->prsp, 0, | ||
267 | conn->src, conn->hcon->dst_type, conn->dst, | ||
268 | res); | ||
269 | else | ||
270 | ret = smp_c1(tfm, smp->tk, smp->prnd, smp->preq, smp->prsp, | ||
271 | conn->hcon->dst_type, conn->dst, 0, conn->src, | ||
272 | res); | ||
273 | if (ret) { | ||
274 | reason = SMP_UNSPECIFIED; | ||
275 | goto error; | ||
276 | } | ||
277 | |||
278 | swap128(res, cp.confirm_val); | ||
279 | smp_send_cmd(smp->conn, SMP_CMD_PAIRING_CONFIRM, sizeof(cp), &cp); | ||
280 | |||
281 | return; | ||
282 | |||
283 | error: | ||
284 | smp_send_cmd(conn, SMP_CMD_PAIRING_FAIL, sizeof(reason), &reason); | ||
285 | smp_chan_destroy(conn); | ||
286 | } | ||
287 | |||
288 | static void random_work(struct work_struct *work) | ||
289 | { | ||
290 | struct smp_chan *smp = container_of(work, struct smp_chan, random); | ||
291 | struct l2cap_conn *conn = smp->conn; | ||
292 | struct hci_conn *hcon = conn->hcon; | ||
293 | struct crypto_blkcipher *tfm = smp->tfm; | ||
294 | u8 reason, confirm[16], res[16], key[16]; | ||
295 | int ret; | ||
296 | |||
297 | if (IS_ERR_OR_NULL(tfm)) { | ||
298 | reason = SMP_UNSPECIFIED; | ||
299 | goto error; | ||
300 | } | ||
301 | |||
302 | BT_DBG("conn %p %s", conn, conn->hcon->out ? "master" : "slave"); | ||
303 | |||
304 | if (hcon->out) | ||
305 | ret = smp_c1(tfm, smp->tk, smp->rrnd, smp->preq, smp->prsp, 0, | ||
306 | conn->src, hcon->dst_type, conn->dst, | ||
307 | res); | ||
308 | else | ||
309 | ret = smp_c1(tfm, smp->tk, smp->rrnd, smp->preq, smp->prsp, | ||
310 | hcon->dst_type, conn->dst, 0, conn->src, | ||
311 | res); | ||
312 | if (ret) { | ||
313 | reason = SMP_UNSPECIFIED; | ||
314 | goto error; | ||
315 | } | ||
316 | |||
317 | swap128(res, confirm); | ||
318 | |||
319 | if (memcmp(smp->pcnf, confirm, sizeof(smp->pcnf)) != 0) { | ||
320 | BT_ERR("Pairing failed (confirmation values mismatch)"); | ||
321 | reason = SMP_CONFIRM_FAILED; | ||
322 | goto error; | ||
323 | } | ||
324 | |||
325 | if (hcon->out) { | ||
326 | u8 stk[16], rand[8]; | ||
327 | __le16 ediv; | ||
328 | |||
329 | memset(rand, 0, sizeof(rand)); | ||
330 | ediv = 0; | ||
331 | |||
332 | smp_s1(tfm, smp->tk, smp->rrnd, smp->prnd, key); | ||
333 | swap128(key, stk); | ||
334 | |||
335 | memset(stk + smp->smp_key_size, 0, | ||
336 | SMP_MAX_ENC_KEY_SIZE - smp->smp_key_size); | ||
337 | |||
338 | if (test_and_set_bit(HCI_CONN_ENCRYPT_PEND, &hcon->pend)) { | ||
339 | reason = SMP_UNSPECIFIED; | ||
340 | goto error; | ||
341 | } | ||
342 | |||
343 | hci_le_start_enc(hcon, ediv, rand, stk); | ||
344 | hcon->enc_key_size = smp->smp_key_size; | ||
345 | } else { | ||
346 | u8 stk[16], r[16], rand[8]; | ||
347 | __le16 ediv; | ||
348 | |||
349 | memset(rand, 0, sizeof(rand)); | ||
350 | ediv = 0; | ||
351 | |||
352 | swap128(smp->prnd, r); | ||
353 | smp_send_cmd(conn, SMP_CMD_PAIRING_RANDOM, sizeof(r), r); | ||
354 | |||
355 | smp_s1(tfm, smp->tk, smp->prnd, smp->rrnd, key); | ||
356 | swap128(key, stk); | ||
357 | |||
358 | memset(stk + smp->smp_key_size, 0, | ||
359 | SMP_MAX_ENC_KEY_SIZE - smp->smp_key_size); | ||
360 | |||
361 | hci_add_ltk(hcon->hdev, 0, conn->dst, smp->smp_key_size, | ||
362 | ediv, rand, stk); | ||
363 | } | ||
364 | |||
365 | return; | ||
366 | |||
367 | error: | ||
368 | smp_send_cmd(conn, SMP_CMD_PAIRING_FAIL, sizeof(reason), &reason); | ||
369 | smp_chan_destroy(conn); | ||
370 | } | ||
371 | |||
372 | static struct smp_chan *smp_chan_create(struct l2cap_conn *conn) | ||
373 | { | ||
374 | struct smp_chan *smp; | ||
375 | |||
376 | smp = kzalloc(sizeof(struct smp_chan), GFP_ATOMIC); | ||
377 | if (!smp) | ||
378 | return NULL; | ||
379 | |||
380 | INIT_WORK(&smp->confirm, confirm_work); | ||
381 | INIT_WORK(&smp->random, random_work); | ||
382 | |||
383 | smp->conn = conn; | ||
384 | conn->smp_chan = smp; | ||
385 | |||
386 | hci_conn_hold(conn->hcon); | ||
387 | |||
388 | return smp; | ||
389 | } | ||
390 | |||
391 | void smp_chan_destroy(struct l2cap_conn *conn) | ||
392 | { | ||
393 | kfree(conn->smp_chan); | ||
394 | hci_conn_put(conn->hcon); | ||
395 | } | ||
396 | |||
246 | static u8 smp_cmd_pairing_req(struct l2cap_conn *conn, struct sk_buff *skb) | 397 | static u8 smp_cmd_pairing_req(struct l2cap_conn *conn, struct sk_buff *skb) |
247 | { | 398 | { |
248 | struct smp_cmd_pairing rsp, *req = (void *) skb->data; | 399 | struct smp_cmd_pairing rsp, *req = (void *) skb->data; |
249 | struct smp_chan *smp = conn->smp_chan; | 400 | struct smp_chan *smp; |
250 | u8 key_size; | 401 | u8 key_size; |
402 | int ret; | ||
251 | 403 | ||
252 | BT_DBG("conn %p", conn); | 404 | BT_DBG("conn %p", conn); |
253 | 405 | ||
254 | if (!test_and_set_bit(HCI_CONN_LE_SMP_PEND, &conn->hcon->pend)) | 406 | if (!test_and_set_bit(HCI_CONN_LE_SMP_PEND, &conn->hcon->pend)) |
255 | hci_conn_hold(conn->hcon); | 407 | smp = smp_chan_create(conn); |
408 | |||
409 | smp = conn->smp_chan; | ||
256 | 410 | ||
257 | smp->preq[0] = SMP_CMD_PAIRING_REQ; | 411 | smp->preq[0] = SMP_CMD_PAIRING_REQ; |
258 | memcpy(&smp->preq[1], req, sizeof(*req)); | 412 | memcpy(&smp->preq[1], req, sizeof(*req)); |
@@ -271,6 +425,10 @@ static u8 smp_cmd_pairing_req(struct l2cap_conn *conn, struct sk_buff *skb) | |||
271 | /* Just works */ | 425 | /* Just works */ |
272 | memset(smp->tk, 0, sizeof(smp->tk)); | 426 | memset(smp->tk, 0, sizeof(smp->tk)); |
273 | 427 | ||
428 | ret = smp_rand(smp->prnd); | ||
429 | if (ret) | ||
430 | return SMP_UNSPECIFIED; | ||
431 | |||
274 | smp->prsp[0] = SMP_CMD_PAIRING_RSP; | 432 | smp->prsp[0] = SMP_CMD_PAIRING_RSP; |
275 | memcpy(&smp->prsp[1], &rsp, sizeof(rsp)); | 433 | memcpy(&smp->prsp[1], &rsp, sizeof(rsp)); |
276 | 434 | ||
@@ -282,12 +440,10 @@ static u8 smp_cmd_pairing_req(struct l2cap_conn *conn, struct sk_buff *skb) | |||
282 | static u8 smp_cmd_pairing_rsp(struct l2cap_conn *conn, struct sk_buff *skb) | 440 | static u8 smp_cmd_pairing_rsp(struct l2cap_conn *conn, struct sk_buff *skb) |
283 | { | 441 | { |
284 | struct smp_cmd_pairing *req, *rsp = (void *) skb->data; | 442 | struct smp_cmd_pairing *req, *rsp = (void *) skb->data; |
285 | struct smp_cmd_pairing_confirm cp; | ||
286 | struct smp_chan *smp = conn->smp_chan; | 443 | struct smp_chan *smp = conn->smp_chan; |
287 | struct crypto_blkcipher *tfm = smp->tfm; | 444 | struct hci_dev *hdev = conn->hcon->hdev; |
288 | 445 | u8 key_size; | |
289 | int ret; | 446 | int ret; |
290 | u8 res[16], key_size; | ||
291 | 447 | ||
292 | BT_DBG("conn %p", conn); | 448 | BT_DBG("conn %p", conn); |
293 | 449 | ||
@@ -305,21 +461,14 @@ static u8 smp_cmd_pairing_rsp(struct l2cap_conn *conn, struct sk_buff *skb) | |||
305 | /* Just works */ | 461 | /* Just works */ |
306 | memset(smp->tk, 0, sizeof(smp->tk)); | 462 | memset(smp->tk, 0, sizeof(smp->tk)); |
307 | 463 | ||
308 | smp->prsp[0] = SMP_CMD_PAIRING_RSP; | ||
309 | memcpy(&smp->prsp[1], rsp, sizeof(*rsp)); | ||
310 | |||
311 | ret = smp_rand(smp->prnd); | 464 | ret = smp_rand(smp->prnd); |
312 | if (ret) | 465 | if (ret) |
313 | return SMP_UNSPECIFIED; | 466 | return SMP_UNSPECIFIED; |
314 | 467 | ||
315 | ret = smp_c1(tfm, smp->tk, smp->prnd, smp->preq, smp->prsp, 0, | 468 | smp->prsp[0] = SMP_CMD_PAIRING_RSP; |
316 | conn->src, conn->hcon->dst_type, conn->dst, res); | 469 | memcpy(&smp->prsp[1], rsp, sizeof(*rsp)); |
317 | if (ret) | ||
318 | return SMP_UNSPECIFIED; | ||
319 | |||
320 | swap128(res, cp.confirm_val); | ||
321 | 470 | ||
322 | smp_send_cmd(conn, SMP_CMD_PAIRING_CONFIRM, sizeof(cp), &cp); | 471 | queue_work(hdev->workqueue, &smp->confirm); |
323 | 472 | ||
324 | return 0; | 473 | return 0; |
325 | } | 474 | } |
@@ -327,7 +476,7 @@ static u8 smp_cmd_pairing_rsp(struct l2cap_conn *conn, struct sk_buff *skb) | |||
327 | static u8 smp_cmd_pairing_confirm(struct l2cap_conn *conn, struct sk_buff *skb) | 476 | static u8 smp_cmd_pairing_confirm(struct l2cap_conn *conn, struct sk_buff *skb) |
328 | { | 477 | { |
329 | struct smp_chan *smp = conn->smp_chan; | 478 | struct smp_chan *smp = conn->smp_chan; |
330 | struct crypto_blkcipher *tfm = smp->tfm; | 479 | struct hci_dev *hdev = conn->hcon->hdev; |
331 | 480 | ||
332 | BT_DBG("conn %p %s", conn, conn->hcon->out ? "master" : "slave"); | 481 | BT_DBG("conn %p %s", conn, conn->hcon->out ? "master" : "slave"); |
333 | 482 | ||
@@ -341,23 +490,7 @@ static u8 smp_cmd_pairing_confirm(struct l2cap_conn *conn, struct sk_buff *skb) | |||
341 | smp_send_cmd(conn, SMP_CMD_PAIRING_RANDOM, sizeof(random), | 490 | smp_send_cmd(conn, SMP_CMD_PAIRING_RANDOM, sizeof(random), |
342 | random); | 491 | random); |
343 | } else { | 492 | } else { |
344 | struct smp_cmd_pairing_confirm cp; | 493 | queue_work(hdev->workqueue, &smp->confirm); |
345 | int ret; | ||
346 | u8 res[16]; | ||
347 | |||
348 | ret = smp_rand(smp->prnd); | ||
349 | if (ret) | ||
350 | return SMP_UNSPECIFIED; | ||
351 | |||
352 | ret = smp_c1(tfm, smp->tk, smp->prnd, smp->preq, smp->prsp, | ||
353 | conn->hcon->dst_type, conn->dst, | ||
354 | 0, conn->src, res); | ||
355 | if (ret) | ||
356 | return SMP_CONFIRM_FAILED; | ||
357 | |||
358 | swap128(res, cp.confirm_val); | ||
359 | |||
360 | smp_send_cmd(conn, SMP_CMD_PAIRING_CONFIRM, sizeof(cp), &cp); | ||
361 | } | 494 | } |
362 | 495 | ||
363 | return 0; | 496 | return 0; |
@@ -365,72 +498,15 @@ static u8 smp_cmd_pairing_confirm(struct l2cap_conn *conn, struct sk_buff *skb) | |||
365 | 498 | ||
366 | static u8 smp_cmd_pairing_random(struct l2cap_conn *conn, struct sk_buff *skb) | 499 | static u8 smp_cmd_pairing_random(struct l2cap_conn *conn, struct sk_buff *skb) |
367 | { | 500 | { |
368 | struct hci_conn *hcon = conn->hcon; | ||
369 | struct smp_chan *smp = conn->smp_chan; | 501 | struct smp_chan *smp = conn->smp_chan; |
370 | struct crypto_blkcipher *tfm = smp->tfm; | 502 | struct hci_dev *hdev = conn->hcon->hdev; |
371 | int ret; | ||
372 | u8 key[16], res[16], random[16], confirm[16]; | ||
373 | |||
374 | swap128(skb->data, random); | ||
375 | skb_pull(skb, sizeof(random)); | ||
376 | 503 | ||
377 | if (conn->hcon->out) | 504 | BT_DBG("conn %p", conn); |
378 | ret = smp_c1(tfm, smp->tk, random, smp->preq, smp->prsp, 0, | ||
379 | conn->src, conn->hcon->dst_type, conn->dst, | ||
380 | res); | ||
381 | else | ||
382 | ret = smp_c1(tfm, smp->tk, random, smp->preq, smp->prsp, | ||
383 | conn->hcon->dst_type, conn->dst, 0, conn->src, | ||
384 | res); | ||
385 | if (ret) | ||
386 | return SMP_UNSPECIFIED; | ||
387 | |||
388 | BT_DBG("conn %p %s", conn, conn->hcon->out ? "master" : "slave"); | ||
389 | |||
390 | swap128(res, confirm); | ||
391 | |||
392 | if (memcmp(smp->pcnf, confirm, sizeof(smp->pcnf)) != 0) { | ||
393 | BT_ERR("Pairing failed (confirmation values mismatch)"); | ||
394 | return SMP_CONFIRM_FAILED; | ||
395 | } | ||
396 | |||
397 | if (conn->hcon->out) { | ||
398 | u8 stk[16], rand[8]; | ||
399 | __le16 ediv; | ||
400 | |||
401 | memset(rand, 0, sizeof(rand)); | ||
402 | ediv = 0; | ||
403 | |||
404 | smp_s1(tfm, smp->tk, random, smp->prnd, key); | ||
405 | swap128(key, stk); | ||
406 | |||
407 | memset(stk + smp->smp_key_size, 0, | ||
408 | SMP_MAX_ENC_KEY_SIZE - smp->smp_key_size); | ||
409 | |||
410 | if (test_and_set_bit(HCI_CONN_ENCRYPT_PEND, &hcon->pend)) | ||
411 | return SMP_UNSPECIFIED; | ||
412 | |||
413 | hci_le_start_enc(hcon, ediv, rand, stk); | ||
414 | hcon->enc_key_size = smp->smp_key_size; | ||
415 | } else { | ||
416 | u8 stk[16], r[16], rand[8]; | ||
417 | __le16 ediv; | ||
418 | |||
419 | memset(rand, 0, sizeof(rand)); | ||
420 | ediv = 0; | ||
421 | |||
422 | swap128(smp->prnd, r); | ||
423 | smp_send_cmd(conn, SMP_CMD_PAIRING_RANDOM, sizeof(r), r); | ||
424 | |||
425 | smp_s1(tfm, smp->tk, smp->prnd, random, key); | ||
426 | swap128(key, stk); | ||
427 | 505 | ||
428 | memset(stk + smp->smp_key_size, 0, | 506 | swap128(skb->data, smp->rrnd); |
429 | SMP_MAX_ENC_KEY_SIZE - smp->smp_key_size); | 507 | skb_pull(skb, sizeof(smp->rrnd)); |
430 | 508 | ||
431 | hci_add_ltk(conn->hcon->hdev, 0, conn->dst, smp->smp_key_size, | 509 | queue_work(hdev->workqueue, &smp->random); |
432 | ediv, rand, stk); | ||
433 | } | ||
434 | 510 | ||
435 | return 0; | 511 | return 0; |
436 | } | 512 | } |
@@ -440,14 +516,14 @@ static u8 smp_cmd_security_req(struct l2cap_conn *conn, struct sk_buff *skb) | |||
440 | struct smp_cmd_security_req *rp = (void *) skb->data; | 516 | struct smp_cmd_security_req *rp = (void *) skb->data; |
441 | struct smp_cmd_pairing cp; | 517 | struct smp_cmd_pairing cp; |
442 | struct hci_conn *hcon = conn->hcon; | 518 | struct hci_conn *hcon = conn->hcon; |
443 | struct smp_chan *smp = conn->smp_chan; | 519 | struct smp_chan *smp; |
444 | 520 | ||
445 | BT_DBG("conn %p", conn); | 521 | BT_DBG("conn %p", conn); |
446 | 522 | ||
447 | if (test_and_set_bit(HCI_CONN_LE_SMP_PEND, &hcon->pend)) | 523 | if (test_and_set_bit(HCI_CONN_LE_SMP_PEND, &hcon->pend)) |
448 | return 0; | 524 | return 0; |
449 | 525 | ||
450 | hci_conn_hold(hcon); | 526 | smp = smp_chan_create(conn); |
451 | 527 | ||
452 | skb_pull(skb, sizeof(*rp)); | 528 | skb_pull(skb, sizeof(*rp)); |
453 | 529 | ||
@@ -502,8 +578,7 @@ int smp_conn_security(struct l2cap_conn *conn, __u8 sec_level) | |||
502 | if (test_and_set_bit(HCI_CONN_LE_SMP_PEND, &hcon->pend)) | 578 | if (test_and_set_bit(HCI_CONN_LE_SMP_PEND, &hcon->pend)) |
503 | return 0; | 579 | return 0; |
504 | 580 | ||
505 | /* While SMP is going on */ | 581 | smp = smp_chan_create(conn); |
506 | hci_conn_hold(hcon); | ||
507 | 582 | ||
508 | authreq = seclevel_to_authreq(sec_level); | 583 | authreq = seclevel_to_authreq(sec_level); |
509 | 584 | ||
@@ -710,7 +785,7 @@ int smp_distribute_keys(struct l2cap_conn *conn, __u8 force) | |||
710 | if (conn->hcon->out || force) { | 785 | if (conn->hcon->out || force) { |
711 | clear_bit(HCI_CONN_LE_SMP_PEND, &conn->hcon->pend); | 786 | clear_bit(HCI_CONN_LE_SMP_PEND, &conn->hcon->pend); |
712 | del_timer(&conn->security_timer); | 787 | del_timer(&conn->security_timer); |
713 | hci_conn_put(conn->hcon); | 788 | smp_chan_destroy(conn); |
714 | } | 789 | } |
715 | 790 | ||
716 | return 0; | 791 | return 0; |