diff options
Diffstat (limited to 'net/bluetooth/smp.c')
-rw-r--r-- | net/bluetooth/smp.c | 76 |
1 files changed, 44 insertions, 32 deletions
diff --git a/net/bluetooth/smp.c b/net/bluetooth/smp.c index 0b4403f3dce1..c71589f4b435 100644 --- a/net/bluetooth/smp.c +++ b/net/bluetooth/smp.c | |||
@@ -409,7 +409,6 @@ static void smp_failure(struct l2cap_conn *conn, u8 reason) | |||
409 | { | 409 | { |
410 | struct hci_conn *hcon = conn->hcon; | 410 | struct hci_conn *hcon = conn->hcon; |
411 | struct l2cap_chan *chan = conn->smp; | 411 | struct l2cap_chan *chan = conn->smp; |
412 | struct smp_chan *smp; | ||
413 | 412 | ||
414 | if (reason) | 413 | if (reason) |
415 | smp_send_cmd(conn, SMP_CMD_PAIRING_FAIL, sizeof(reason), | 414 | smp_send_cmd(conn, SMP_CMD_PAIRING_FAIL, sizeof(reason), |
@@ -419,12 +418,7 @@ static void smp_failure(struct l2cap_conn *conn, u8 reason) | |||
419 | mgmt_auth_failed(hcon->hdev, &hcon->dst, hcon->type, hcon->dst_type, | 418 | mgmt_auth_failed(hcon->hdev, &hcon->dst, hcon->type, hcon->dst_type, |
420 | HCI_ERROR_AUTH_FAILURE); | 419 | HCI_ERROR_AUTH_FAILURE); |
421 | 420 | ||
422 | if (!chan->data) | 421 | if (chan->data) |
423 | return; | ||
424 | |||
425 | smp = chan->data; | ||
426 | |||
427 | if (test_and_clear_bit(HCI_CONN_LE_SMP_PEND, &hcon->flags)) | ||
428 | smp_chan_destroy(conn); | 422 | smp_chan_destroy(conn); |
429 | } | 423 | } |
430 | 424 | ||
@@ -706,9 +700,6 @@ static void smp_distribute_keys(struct smp_chan *smp) | |||
706 | 700 | ||
707 | BT_DBG("conn %p", conn); | 701 | BT_DBG("conn %p", conn); |
708 | 702 | ||
709 | if (!test_bit(HCI_CONN_LE_SMP_PEND, &hcon->flags)) | ||
710 | return; | ||
711 | |||
712 | rsp = (void *) &smp->prsp[1]; | 703 | rsp = (void *) &smp->prsp[1]; |
713 | 704 | ||
714 | /* The responder sends its keys first */ | 705 | /* The responder sends its keys first */ |
@@ -801,7 +792,6 @@ static void smp_distribute_keys(struct smp_chan *smp) | |||
801 | if ((smp->remote_key_dist & 0x07)) | 792 | if ((smp->remote_key_dist & 0x07)) |
802 | return; | 793 | return; |
803 | 794 | ||
804 | clear_bit(HCI_CONN_LE_SMP_PEND, &hcon->flags); | ||
805 | set_bit(SMP_FLAG_COMPLETE, &smp->flags); | 795 | set_bit(SMP_FLAG_COMPLETE, &smp->flags); |
806 | smp_notify_keys(conn); | 796 | smp_notify_keys(conn); |
807 | 797 | ||
@@ -825,16 +815,13 @@ static struct smp_chan *smp_chan_create(struct l2cap_conn *conn) | |||
825 | struct smp_chan *smp; | 815 | struct smp_chan *smp; |
826 | 816 | ||
827 | smp = kzalloc(sizeof(*smp), GFP_ATOMIC); | 817 | smp = kzalloc(sizeof(*smp), GFP_ATOMIC); |
828 | if (!smp) { | 818 | if (!smp) |
829 | clear_bit(HCI_CONN_LE_SMP_PEND, &conn->hcon->flags); | ||
830 | return NULL; | 819 | return NULL; |
831 | } | ||
832 | 820 | ||
833 | smp->tfm_aes = crypto_alloc_blkcipher("ecb(aes)", 0, CRYPTO_ALG_ASYNC); | 821 | smp->tfm_aes = crypto_alloc_blkcipher("ecb(aes)", 0, CRYPTO_ALG_ASYNC); |
834 | if (IS_ERR(smp->tfm_aes)) { | 822 | if (IS_ERR(smp->tfm_aes)) { |
835 | BT_ERR("Unable to create ECB crypto context"); | 823 | BT_ERR("Unable to create ECB crypto context"); |
836 | kfree(smp); | 824 | kfree(smp); |
837 | clear_bit(HCI_CONN_LE_SMP_PEND, &conn->hcon->flags); | ||
838 | return NULL; | 825 | return NULL; |
839 | } | 826 | } |
840 | 827 | ||
@@ -854,16 +841,23 @@ int smp_user_confirm_reply(struct hci_conn *hcon, u16 mgmt_op, __le32 passkey) | |||
854 | struct l2cap_chan *chan; | 841 | struct l2cap_chan *chan; |
855 | struct smp_chan *smp; | 842 | struct smp_chan *smp; |
856 | u32 value; | 843 | u32 value; |
844 | int err; | ||
857 | 845 | ||
858 | BT_DBG(""); | 846 | BT_DBG(""); |
859 | 847 | ||
860 | if (!conn || !test_bit(HCI_CONN_LE_SMP_PEND, &hcon->flags)) | 848 | if (!conn) |
861 | return -ENOTCONN; | 849 | return -ENOTCONN; |
862 | 850 | ||
863 | chan = conn->smp; | 851 | chan = conn->smp; |
864 | if (!chan) | 852 | if (!chan) |
865 | return -ENOTCONN; | 853 | return -ENOTCONN; |
866 | 854 | ||
855 | l2cap_chan_lock(chan); | ||
856 | if (!chan->data) { | ||
857 | err = -ENOTCONN; | ||
858 | goto unlock; | ||
859 | } | ||
860 | |||
867 | smp = chan->data; | 861 | smp = chan->data; |
868 | 862 | ||
869 | switch (mgmt_op) { | 863 | switch (mgmt_op) { |
@@ -879,12 +873,16 @@ int smp_user_confirm_reply(struct hci_conn *hcon, u16 mgmt_op, __le32 passkey) | |||
879 | case MGMT_OP_USER_PASSKEY_NEG_REPLY: | 873 | case MGMT_OP_USER_PASSKEY_NEG_REPLY: |
880 | case MGMT_OP_USER_CONFIRM_NEG_REPLY: | 874 | case MGMT_OP_USER_CONFIRM_NEG_REPLY: |
881 | smp_failure(conn, SMP_PASSKEY_ENTRY_FAILED); | 875 | smp_failure(conn, SMP_PASSKEY_ENTRY_FAILED); |
882 | return 0; | 876 | err = 0; |
877 | goto unlock; | ||
883 | default: | 878 | default: |
884 | smp_failure(conn, SMP_PASSKEY_ENTRY_FAILED); | 879 | smp_failure(conn, SMP_PASSKEY_ENTRY_FAILED); |
885 | return -EOPNOTSUPP; | 880 | err = -EOPNOTSUPP; |
881 | goto unlock; | ||
886 | } | 882 | } |
887 | 883 | ||
884 | err = 0; | ||
885 | |||
888 | /* If it is our turn to send Pairing Confirm, do so now */ | 886 | /* If it is our turn to send Pairing Confirm, do so now */ |
889 | if (test_bit(SMP_FLAG_CFM_PENDING, &smp->flags)) { | 887 | if (test_bit(SMP_FLAG_CFM_PENDING, &smp->flags)) { |
890 | u8 rsp = smp_confirm(smp); | 888 | u8 rsp = smp_confirm(smp); |
@@ -892,12 +890,15 @@ int smp_user_confirm_reply(struct hci_conn *hcon, u16 mgmt_op, __le32 passkey) | |||
892 | smp_failure(conn, rsp); | 890 | smp_failure(conn, rsp); |
893 | } | 891 | } |
894 | 892 | ||
895 | return 0; | 893 | unlock: |
894 | l2cap_chan_unlock(chan); | ||
895 | return err; | ||
896 | } | 896 | } |
897 | 897 | ||
898 | static u8 smp_cmd_pairing_req(struct l2cap_conn *conn, struct sk_buff *skb) | 898 | static u8 smp_cmd_pairing_req(struct l2cap_conn *conn, struct sk_buff *skb) |
899 | { | 899 | { |
900 | struct smp_cmd_pairing rsp, *req = (void *) skb->data; | 900 | struct smp_cmd_pairing rsp, *req = (void *) skb->data; |
901 | struct l2cap_chan *chan = conn->smp; | ||
901 | struct hci_dev *hdev = conn->hcon->hdev; | 902 | struct hci_dev *hdev = conn->hcon->hdev; |
902 | struct smp_chan *smp; | 903 | struct smp_chan *smp; |
903 | u8 key_size, auth, sec_level; | 904 | u8 key_size, auth, sec_level; |
@@ -911,12 +912,10 @@ static u8 smp_cmd_pairing_req(struct l2cap_conn *conn, struct sk_buff *skb) | |||
911 | if (conn->hcon->role != HCI_ROLE_SLAVE) | 912 | if (conn->hcon->role != HCI_ROLE_SLAVE) |
912 | return SMP_CMD_NOTSUPP; | 913 | return SMP_CMD_NOTSUPP; |
913 | 914 | ||
914 | if (!test_and_set_bit(HCI_CONN_LE_SMP_PEND, &conn->hcon->flags)) { | 915 | if (!chan->data) |
915 | smp = smp_chan_create(conn); | 916 | smp = smp_chan_create(conn); |
916 | } else { | 917 | else |
917 | struct l2cap_chan *chan = conn->smp; | ||
918 | smp = chan->data; | 918 | smp = chan->data; |
919 | } | ||
920 | 919 | ||
921 | if (!smp) | 920 | if (!smp) |
922 | return SMP_UNSPECIFIED; | 921 | return SMP_UNSPECIFIED; |
@@ -1122,6 +1121,7 @@ static u8 smp_cmd_security_req(struct l2cap_conn *conn, struct sk_buff *skb) | |||
1122 | struct smp_cmd_security_req *rp = (void *) skb->data; | 1121 | struct smp_cmd_security_req *rp = (void *) skb->data; |
1123 | struct smp_cmd_pairing cp; | 1122 | struct smp_cmd_pairing cp; |
1124 | struct hci_conn *hcon = conn->hcon; | 1123 | struct hci_conn *hcon = conn->hcon; |
1124 | struct l2cap_chan *chan = conn->smp; | ||
1125 | struct smp_chan *smp; | 1125 | struct smp_chan *smp; |
1126 | u8 sec_level; | 1126 | u8 sec_level; |
1127 | 1127 | ||
@@ -1143,7 +1143,8 @@ static u8 smp_cmd_security_req(struct l2cap_conn *conn, struct sk_buff *skb) | |||
1143 | if (smp_ltk_encrypt(conn, hcon->pending_sec_level)) | 1143 | if (smp_ltk_encrypt(conn, hcon->pending_sec_level)) |
1144 | return 0; | 1144 | return 0; |
1145 | 1145 | ||
1146 | if (test_and_set_bit(HCI_CONN_LE_SMP_PEND, &hcon->flags)) | 1146 | /* If SMP is already in progress ignore this request */ |
1147 | if (chan->data) | ||
1147 | return 0; | 1148 | return 0; |
1148 | 1149 | ||
1149 | smp = smp_chan_create(conn); | 1150 | smp = smp_chan_create(conn); |
@@ -1170,8 +1171,10 @@ static u8 smp_cmd_security_req(struct l2cap_conn *conn, struct sk_buff *skb) | |||
1170 | int smp_conn_security(struct hci_conn *hcon, __u8 sec_level) | 1171 | int smp_conn_security(struct hci_conn *hcon, __u8 sec_level) |
1171 | { | 1172 | { |
1172 | struct l2cap_conn *conn = hcon->l2cap_data; | 1173 | struct l2cap_conn *conn = hcon->l2cap_data; |
1174 | struct l2cap_chan *chan = conn->smp; | ||
1173 | struct smp_chan *smp; | 1175 | struct smp_chan *smp; |
1174 | __u8 authreq; | 1176 | __u8 authreq; |
1177 | int ret; | ||
1175 | 1178 | ||
1176 | BT_DBG("conn %p hcon %p level 0x%2.2x", conn, hcon, sec_level); | 1179 | BT_DBG("conn %p hcon %p level 0x%2.2x", conn, hcon, sec_level); |
1177 | 1180 | ||
@@ -1192,12 +1195,19 @@ int smp_conn_security(struct hci_conn *hcon, __u8 sec_level) | |||
1192 | if (smp_ltk_encrypt(conn, hcon->pending_sec_level)) | 1195 | if (smp_ltk_encrypt(conn, hcon->pending_sec_level)) |
1193 | return 0; | 1196 | return 0; |
1194 | 1197 | ||
1195 | if (test_and_set_bit(HCI_CONN_LE_SMP_PEND, &hcon->flags)) | 1198 | l2cap_chan_lock(chan); |
1196 | return 0; | 1199 | |
1200 | /* If SMP is already in progress ignore this request */ | ||
1201 | if (chan->data) { | ||
1202 | ret = 0; | ||
1203 | goto unlock; | ||
1204 | } | ||
1197 | 1205 | ||
1198 | smp = smp_chan_create(conn); | 1206 | smp = smp_chan_create(conn); |
1199 | if (!smp) | 1207 | if (!smp) { |
1200 | return 1; | 1208 | ret = 1; |
1209 | goto unlock; | ||
1210 | } | ||
1201 | 1211 | ||
1202 | authreq = seclevel_to_authreq(sec_level); | 1212 | authreq = seclevel_to_authreq(sec_level); |
1203 | 1213 | ||
@@ -1223,8 +1233,11 @@ int smp_conn_security(struct hci_conn *hcon, __u8 sec_level) | |||
1223 | } | 1233 | } |
1224 | 1234 | ||
1225 | set_bit(SMP_FLAG_INITIATOR, &smp->flags); | 1235 | set_bit(SMP_FLAG_INITIATOR, &smp->flags); |
1236 | ret = 0; | ||
1226 | 1237 | ||
1227 | return 0; | 1238 | unlock: |
1239 | l2cap_chan_unlock(chan); | ||
1240 | return ret; | ||
1228 | } | 1241 | } |
1229 | 1242 | ||
1230 | static int smp_cmd_encrypt_info(struct l2cap_conn *conn, struct sk_buff *skb) | 1243 | static int smp_cmd_encrypt_info(struct l2cap_conn *conn, struct sk_buff *skb) |
@@ -1315,7 +1328,6 @@ static int smp_cmd_ident_addr_info(struct l2cap_conn *conn, | |||
1315 | struct l2cap_chan *chan = conn->smp; | 1328 | struct l2cap_chan *chan = conn->smp; |
1316 | struct smp_chan *smp = chan->data; | 1329 | struct smp_chan *smp = chan->data; |
1317 | struct hci_conn *hcon = conn->hcon; | 1330 | struct hci_conn *hcon = conn->hcon; |
1318 | struct hci_dev *hdev = hcon->hdev; | ||
1319 | bdaddr_t rpa; | 1331 | bdaddr_t rpa; |
1320 | 1332 | ||
1321 | BT_DBG(""); | 1333 | BT_DBG(""); |
@@ -1430,7 +1442,7 @@ static int smp_sig_channel(struct l2cap_chan *chan, struct sk_buff *skb) | |||
1430 | * returns an error). | 1442 | * returns an error). |
1431 | */ | 1443 | */ |
1432 | if (code != SMP_CMD_PAIRING_REQ && code != SMP_CMD_SECURITY_REQ && | 1444 | if (code != SMP_CMD_PAIRING_REQ && code != SMP_CMD_SECURITY_REQ && |
1433 | !test_bit(HCI_CONN_LE_SMP_PEND, &hcon->flags)) { | 1445 | !chan->data) { |
1434 | BT_ERR("Unexpected SMP command 0x%02x. Disconnecting.", code); | 1446 | BT_ERR("Unexpected SMP command 0x%02x. Disconnecting.", code); |
1435 | err = -EOPNOTSUPP; | 1447 | err = -EOPNOTSUPP; |
1436 | goto done; | 1448 | goto done; |
@@ -1504,7 +1516,7 @@ static void smp_teardown_cb(struct l2cap_chan *chan, int err) | |||
1504 | 1516 | ||
1505 | BT_DBG("chan %p", chan); | 1517 | BT_DBG("chan %p", chan); |
1506 | 1518 | ||
1507 | if (test_and_clear_bit(HCI_CONN_LE_SMP_PEND, &conn->hcon->flags)) | 1519 | if (chan->data) |
1508 | smp_chan_destroy(conn); | 1520 | smp_chan_destroy(conn); |
1509 | 1521 | ||
1510 | conn->smp = NULL; | 1522 | conn->smp = NULL; |