aboutsummaryrefslogtreecommitdiffstats
path: root/net/bluetooth/hci_core.c
diff options
context:
space:
mode:
authorJohn W. Linville <linville@tuxdriver.com>2011-05-05 13:32:35 -0400
committerJohn W. Linville <linville@tuxdriver.com>2011-05-05 13:32:35 -0400
commita70171dce9cd44cb06c7d299eba9fa87a8933045 (patch)
tree5425df5f33fadc617c7dec99578d06f0d933578e /net/bluetooth/hci_core.c
parent5a412ad7f4c95bb5b756aa12b52646e857e7c75d (diff)
parenteaef6a93bd52a2cc47b9fce201310010707afdb4 (diff)
Merge branch 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/linville/wireless-next-2.6 into for-davem
Conflicts: drivers/net/wireless/libertas/if_cs.c drivers/net/wireless/rtlwifi/pci.c net/bluetooth/l2cap_sock.c
Diffstat (limited to 'net/bluetooth/hci_core.c')
-rw-r--r--net/bluetooth/hci_core.c75
1 files changed, 66 insertions, 9 deletions
diff --git a/net/bluetooth/hci_core.c b/net/bluetooth/hci_core.c
index e057d123599..815269b07f2 100644
--- a/net/bluetooth/hci_core.c
+++ b/net/bluetooth/hci_core.c
@@ -1020,18 +1020,54 @@ struct link_key *hci_find_link_key(struct hci_dev *hdev, bdaddr_t *bdaddr)
1020 return NULL; 1020 return NULL;
1021} 1021}
1022 1022
1023int hci_add_link_key(struct hci_dev *hdev, int new_key, bdaddr_t *bdaddr, 1023static int hci_persistent_key(struct hci_dev *hdev, struct hci_conn *conn,
1024 u8 *val, u8 type, u8 pin_len) 1024 u8 key_type, u8 old_key_type)
1025{
1026 /* Legacy key */
1027 if (key_type < 0x03)
1028 return 1;
1029
1030 /* Debug keys are insecure so don't store them persistently */
1031 if (key_type == HCI_LK_DEBUG_COMBINATION)
1032 return 0;
1033
1034 /* Changed combination key and there's no previous one */
1035 if (key_type == HCI_LK_CHANGED_COMBINATION && old_key_type == 0xff)
1036 return 0;
1037
1038 /* Security mode 3 case */
1039 if (!conn)
1040 return 1;
1041
1042 /* Neither local nor remote side had no-bonding as requirement */
1043 if (conn->auth_type > 0x01 && conn->remote_auth > 0x01)
1044 return 1;
1045
1046 /* Local side had dedicated bonding as requirement */
1047 if (conn->auth_type == 0x02 || conn->auth_type == 0x03)
1048 return 1;
1049
1050 /* Remote side had dedicated bonding as requirement */
1051 if (conn->remote_auth == 0x02 || conn->remote_auth == 0x03)
1052 return 1;
1053
1054 /* If none of the above criteria match, then don't store the key
1055 * persistently */
1056 return 0;
1057}
1058
1059int hci_add_link_key(struct hci_dev *hdev, struct hci_conn *conn, int new_key,
1060 bdaddr_t *bdaddr, u8 *val, u8 type, u8 pin_len)
1025{ 1061{
1026 struct link_key *key, *old_key; 1062 struct link_key *key, *old_key;
1027 u8 old_key_type; 1063 u8 old_key_type, persistent;
1028 1064
1029 old_key = hci_find_link_key(hdev, bdaddr); 1065 old_key = hci_find_link_key(hdev, bdaddr);
1030 if (old_key) { 1066 if (old_key) {
1031 old_key_type = old_key->type; 1067 old_key_type = old_key->type;
1032 key = old_key; 1068 key = old_key;
1033 } else { 1069 } else {
1034 old_key_type = 0xff; 1070 old_key_type = conn ? conn->key_type : 0xff;
1035 key = kzalloc(sizeof(*key), GFP_ATOMIC); 1071 key = kzalloc(sizeof(*key), GFP_ATOMIC);
1036 if (!key) 1072 if (!key)
1037 return -ENOMEM; 1073 return -ENOMEM;
@@ -1040,16 +1076,37 @@ int hci_add_link_key(struct hci_dev *hdev, int new_key, bdaddr_t *bdaddr,
1040 1076
1041 BT_DBG("%s key for %s type %u", hdev->name, batostr(bdaddr), type); 1077 BT_DBG("%s key for %s type %u", hdev->name, batostr(bdaddr), type);
1042 1078
1079 /* Some buggy controller combinations generate a changed
1080 * combination key for legacy pairing even when there's no
1081 * previous key */
1082 if (type == HCI_LK_CHANGED_COMBINATION &&
1083 (!conn || conn->remote_auth == 0xff) &&
1084 old_key_type == 0xff) {
1085 type = HCI_LK_COMBINATION;
1086 if (conn)
1087 conn->key_type = type;
1088 }
1089
1043 bacpy(&key->bdaddr, bdaddr); 1090 bacpy(&key->bdaddr, bdaddr);
1044 memcpy(key->val, val, 16); 1091 memcpy(key->val, val, 16);
1045 key->type = type;
1046 key->pin_len = pin_len; 1092 key->pin_len = pin_len;
1047 1093
1048 if (new_key) 1094 if (type == HCI_LK_CHANGED_COMBINATION)
1049 mgmt_new_key(hdev->id, key, old_key_type);
1050
1051 if (type == 0x06)
1052 key->type = old_key_type; 1095 key->type = old_key_type;
1096 else
1097 key->type = type;
1098
1099 if (!new_key)
1100 return 0;
1101
1102 persistent = hci_persistent_key(hdev, conn, type, old_key_type);
1103
1104 mgmt_new_key(hdev->id, key, persistent);
1105
1106 if (!persistent) {
1107 list_del(&key->list);
1108 kfree(key);
1109 }
1053 1110
1054 return 0; 1111 return 0;
1055} 1112}