diff options
Diffstat (limited to 'net/bluetooth/smp.c')
-rw-r--r-- | net/bluetooth/smp.c | 69 |
1 files changed, 53 insertions, 16 deletions
diff --git a/net/bluetooth/smp.c b/net/bluetooth/smp.c index 3d1cc164557d..e33a982161c1 100644 --- a/net/bluetooth/smp.c +++ b/net/bluetooth/smp.c | |||
@@ -385,6 +385,16 @@ static const u8 gen_method[5][5] = { | |||
385 | { CFM_PASSKEY, CFM_PASSKEY, REQ_PASSKEY, JUST_WORKS, OVERLAP }, | 385 | { CFM_PASSKEY, CFM_PASSKEY, REQ_PASSKEY, JUST_WORKS, OVERLAP }, |
386 | }; | 386 | }; |
387 | 387 | ||
388 | static u8 get_auth_method(struct smp_chan *smp, u8 local_io, u8 remote_io) | ||
389 | { | ||
390 | /* If either side has unknown io_caps, use JUST WORKS */ | ||
391 | if (local_io > SMP_IO_KEYBOARD_DISPLAY || | ||
392 | remote_io > SMP_IO_KEYBOARD_DISPLAY) | ||
393 | return JUST_WORKS; | ||
394 | |||
395 | return gen_method[remote_io][local_io]; | ||
396 | } | ||
397 | |||
388 | static int tk_request(struct l2cap_conn *conn, u8 remote_oob, u8 auth, | 398 | static int tk_request(struct l2cap_conn *conn, u8 remote_oob, u8 auth, |
389 | u8 local_io, u8 remote_io) | 399 | u8 local_io, u8 remote_io) |
390 | { | 400 | { |
@@ -401,14 +411,11 @@ static int tk_request(struct l2cap_conn *conn, u8 remote_oob, u8 auth, | |||
401 | BT_DBG("tk_request: auth:%d lcl:%d rem:%d", auth, local_io, remote_io); | 411 | BT_DBG("tk_request: auth:%d lcl:%d rem:%d", auth, local_io, remote_io); |
402 | 412 | ||
403 | /* If neither side wants MITM, use JUST WORKS */ | 413 | /* If neither side wants MITM, use JUST WORKS */ |
404 | /* If either side has unknown io_caps, use JUST WORKS */ | ||
405 | /* Otherwise, look up method from the table */ | 414 | /* Otherwise, look up method from the table */ |
406 | if (!(auth & SMP_AUTH_MITM) || | 415 | if (!(auth & SMP_AUTH_MITM)) |
407 | local_io > SMP_IO_KEYBOARD_DISPLAY || | ||
408 | remote_io > SMP_IO_KEYBOARD_DISPLAY) | ||
409 | method = JUST_WORKS; | 416 | method = JUST_WORKS; |
410 | else | 417 | else |
411 | method = gen_method[remote_io][local_io]; | 418 | method = get_auth_method(smp, local_io, remote_io); |
412 | 419 | ||
413 | /* If not bonding, don't ask user to confirm a Zero TK */ | 420 | /* If not bonding, don't ask user to confirm a Zero TK */ |
414 | if (!(auth & SMP_AUTH_BONDING) && method == JUST_CFM) | 421 | if (!(auth & SMP_AUTH_BONDING) && method == JUST_CFM) |
@@ -544,7 +551,7 @@ static u8 smp_random(struct smp_chan *smp) | |||
544 | hci_le_start_enc(hcon, ediv, rand, stk); | 551 | hci_le_start_enc(hcon, ediv, rand, stk); |
545 | hcon->enc_key_size = smp->enc_key_size; | 552 | hcon->enc_key_size = smp->enc_key_size; |
546 | } else { | 553 | } else { |
547 | u8 stk[16]; | 554 | u8 stk[16], auth; |
548 | __le64 rand = 0; | 555 | __le64 rand = 0; |
549 | __le16 ediv = 0; | 556 | __le16 ediv = 0; |
550 | 557 | ||
@@ -556,8 +563,13 @@ static u8 smp_random(struct smp_chan *smp) | |||
556 | memset(stk + smp->enc_key_size, 0, | 563 | memset(stk + smp->enc_key_size, 0, |
557 | SMP_MAX_ENC_KEY_SIZE - smp->enc_key_size); | 564 | SMP_MAX_ENC_KEY_SIZE - smp->enc_key_size); |
558 | 565 | ||
566 | if (hcon->pending_sec_level == BT_SECURITY_HIGH) | ||
567 | auth = 1; | ||
568 | else | ||
569 | auth = 0; | ||
570 | |||
559 | hci_add_ltk(hcon->hdev, &hcon->dst, hcon->dst_type, | 571 | hci_add_ltk(hcon->hdev, &hcon->dst, hcon->dst_type, |
560 | HCI_SMP_STK_SLAVE, 0, stk, smp->enc_key_size, | 572 | HCI_SMP_STK_SLAVE, auth, stk, smp->enc_key_size, |
561 | ediv, rand); | 573 | ediv, rand); |
562 | } | 574 | } |
563 | 575 | ||
@@ -664,7 +676,7 @@ static u8 smp_cmd_pairing_req(struct l2cap_conn *conn, struct sk_buff *skb) | |||
664 | { | 676 | { |
665 | struct smp_cmd_pairing rsp, *req = (void *) skb->data; | 677 | struct smp_cmd_pairing rsp, *req = (void *) skb->data; |
666 | struct smp_chan *smp; | 678 | struct smp_chan *smp; |
667 | u8 key_size, auth; | 679 | u8 key_size, auth, sec_level; |
668 | int ret; | 680 | int ret; |
669 | 681 | ||
670 | BT_DBG("conn %p", conn); | 682 | BT_DBG("conn %p", conn); |
@@ -690,7 +702,19 @@ static u8 smp_cmd_pairing_req(struct l2cap_conn *conn, struct sk_buff *skb) | |||
690 | /* We didn't start the pairing, so match remote */ | 702 | /* We didn't start the pairing, so match remote */ |
691 | auth = req->auth_req; | 703 | auth = req->auth_req; |
692 | 704 | ||
693 | conn->hcon->pending_sec_level = authreq_to_seclevel(auth); | 705 | sec_level = authreq_to_seclevel(auth); |
706 | if (sec_level > conn->hcon->pending_sec_level) | ||
707 | conn->hcon->pending_sec_level = sec_level; | ||
708 | |||
709 | /* If we need MITM check that it can be acheived */ | ||
710 | if (conn->hcon->pending_sec_level >= BT_SECURITY_HIGH) { | ||
711 | u8 method; | ||
712 | |||
713 | method = get_auth_method(smp, conn->hcon->io_capability, | ||
714 | req->io_capability); | ||
715 | if (method == JUST_WORKS || method == JUST_CFM) | ||
716 | return SMP_AUTH_REQUIREMENTS; | ||
717 | } | ||
694 | 718 | ||
695 | build_pairing_cmd(conn, req, &rsp, auth); | 719 | build_pairing_cmd(conn, req, &rsp, auth); |
696 | 720 | ||
@@ -738,6 +762,16 @@ static u8 smp_cmd_pairing_rsp(struct l2cap_conn *conn, struct sk_buff *skb) | |||
738 | if (check_enc_key_size(conn, key_size)) | 762 | if (check_enc_key_size(conn, key_size)) |
739 | return SMP_ENC_KEY_SIZE; | 763 | return SMP_ENC_KEY_SIZE; |
740 | 764 | ||
765 | /* If we need MITM check that it can be acheived */ | ||
766 | if (conn->hcon->pending_sec_level >= BT_SECURITY_HIGH) { | ||
767 | u8 method; | ||
768 | |||
769 | method = get_auth_method(smp, req->io_capability, | ||
770 | rsp->io_capability); | ||
771 | if (method == JUST_WORKS || method == JUST_CFM) | ||
772 | return SMP_AUTH_REQUIREMENTS; | ||
773 | } | ||
774 | |||
741 | get_random_bytes(smp->prnd, sizeof(smp->prnd)); | 775 | get_random_bytes(smp->prnd, sizeof(smp->prnd)); |
742 | 776 | ||
743 | smp->prsp[0] = SMP_CMD_PAIRING_RSP; | 777 | smp->prsp[0] = SMP_CMD_PAIRING_RSP; |
@@ -833,6 +867,7 @@ static u8 smp_cmd_security_req(struct l2cap_conn *conn, struct sk_buff *skb) | |||
833 | struct smp_cmd_pairing cp; | 867 | struct smp_cmd_pairing cp; |
834 | struct hci_conn *hcon = conn->hcon; | 868 | struct hci_conn *hcon = conn->hcon; |
835 | struct smp_chan *smp; | 869 | struct smp_chan *smp; |
870 | u8 sec_level; | ||
836 | 871 | ||
837 | BT_DBG("conn %p", conn); | 872 | BT_DBG("conn %p", conn); |
838 | 873 | ||
@@ -842,7 +877,9 @@ static u8 smp_cmd_security_req(struct l2cap_conn *conn, struct sk_buff *skb) | |||
842 | if (!(conn->hcon->link_mode & HCI_LM_MASTER)) | 877 | if (!(conn->hcon->link_mode & HCI_LM_MASTER)) |
843 | return SMP_CMD_NOTSUPP; | 878 | return SMP_CMD_NOTSUPP; |
844 | 879 | ||
845 | hcon->pending_sec_level = authreq_to_seclevel(rp->auth_req); | 880 | sec_level = authreq_to_seclevel(rp->auth_req); |
881 | if (sec_level > hcon->pending_sec_level) | ||
882 | hcon->pending_sec_level = sec_level; | ||
846 | 883 | ||
847 | if (smp_ltk_encrypt(conn, hcon->pending_sec_level)) | 884 | if (smp_ltk_encrypt(conn, hcon->pending_sec_level)) |
848 | return 0; | 885 | return 0; |
@@ -896,9 +933,12 @@ int smp_conn_security(struct hci_conn *hcon, __u8 sec_level) | |||
896 | if (smp_sufficient_security(hcon, sec_level)) | 933 | if (smp_sufficient_security(hcon, sec_level)) |
897 | return 1; | 934 | return 1; |
898 | 935 | ||
936 | if (sec_level > hcon->pending_sec_level) | ||
937 | hcon->pending_sec_level = sec_level; | ||
938 | |||
899 | if (hcon->link_mode & HCI_LM_MASTER) | 939 | if (hcon->link_mode & HCI_LM_MASTER) |
900 | if (smp_ltk_encrypt(conn, sec_level)) | 940 | if (smp_ltk_encrypt(conn, hcon->pending_sec_level)) |
901 | goto done; | 941 | return 0; |
902 | 942 | ||
903 | if (test_and_set_bit(HCI_CONN_LE_SMP_PEND, &hcon->flags)) | 943 | if (test_and_set_bit(HCI_CONN_LE_SMP_PEND, &hcon->flags)) |
904 | return 0; | 944 | return 0; |
@@ -913,7 +953,7 @@ int smp_conn_security(struct hci_conn *hcon, __u8 sec_level) | |||
913 | * requires it. | 953 | * requires it. |
914 | */ | 954 | */ |
915 | if (hcon->io_capability != HCI_IO_NO_INPUT_OUTPUT || | 955 | if (hcon->io_capability != HCI_IO_NO_INPUT_OUTPUT || |
916 | sec_level > BT_SECURITY_MEDIUM) | 956 | hcon->pending_sec_level > BT_SECURITY_MEDIUM) |
917 | authreq |= SMP_AUTH_MITM; | 957 | authreq |= SMP_AUTH_MITM; |
918 | 958 | ||
919 | if (hcon->link_mode & HCI_LM_MASTER) { | 959 | if (hcon->link_mode & HCI_LM_MASTER) { |
@@ -932,9 +972,6 @@ int smp_conn_security(struct hci_conn *hcon, __u8 sec_level) | |||
932 | 972 | ||
933 | set_bit(SMP_FLAG_INITIATOR, &smp->flags); | 973 | set_bit(SMP_FLAG_INITIATOR, &smp->flags); |
934 | 974 | ||
935 | done: | ||
936 | hcon->pending_sec_level = sec_level; | ||
937 | |||
938 | return 0; | 975 | return 0; |
939 | } | 976 | } |
940 | 977 | ||