diff options
Diffstat (limited to 'net/bluetooth')
-rw-r--r-- | net/bluetooth/hci_core.c | 54 | ||||
-rw-r--r-- | net/bluetooth/hci_event.c | 2 | ||||
-rw-r--r-- | net/bluetooth/mgmt.c | 2 |
3 files changed, 54 insertions, 4 deletions
diff --git a/net/bluetooth/hci_core.c b/net/bluetooth/hci_core.c index 07d0ba35b9a5..5f55aef63e20 100644 --- a/net/bluetooth/hci_core.c +++ b/net/bluetooth/hci_core.c | |||
@@ -1022,8 +1022,44 @@ struct link_key *hci_find_link_key(struct hci_dev *hdev, bdaddr_t *bdaddr) | |||
1022 | return NULL; | 1022 | return NULL; |
1023 | } | 1023 | } |
1024 | 1024 | ||
1025 | int hci_add_link_key(struct hci_dev *hdev, int new_key, bdaddr_t *bdaddr, | 1025 | static int hci_persistent_key(struct hci_dev *hdev, struct hci_conn *conn, |
1026 | u8 *val, u8 type, u8 pin_len) | 1026 | u8 key_type, u8 old_key_type) |
1027 | { | ||
1028 | /* Legacy key */ | ||
1029 | if (key_type < 0x03) | ||
1030 | return 1; | ||
1031 | |||
1032 | /* Debug keys are insecure so don't store them persistently */ | ||
1033 | if (key_type == HCI_LK_DEBUG_COMBINATION) | ||
1034 | return 0; | ||
1035 | |||
1036 | /* Changed combination key and there's no previous one */ | ||
1037 | if (key_type == HCI_LK_CHANGED_COMBINATION && old_key_type == 0xff) | ||
1038 | return 0; | ||
1039 | |||
1040 | /* Security mode 3 case */ | ||
1041 | if (!conn) | ||
1042 | return 1; | ||
1043 | |||
1044 | /* Neither local nor remote side had no-bonding as requirement */ | ||
1045 | if (conn->auth_type > 0x01 && conn->remote_auth > 0x01) | ||
1046 | return 1; | ||
1047 | |||
1048 | /* Local side had dedicated bonding as requirement */ | ||
1049 | if (conn->auth_type == 0x02 || conn->auth_type == 0x03) | ||
1050 | return 1; | ||
1051 | |||
1052 | /* Remote side had dedicated bonding as requirement */ | ||
1053 | if (conn->remote_auth == 0x02 || conn->remote_auth == 0x03) | ||
1054 | return 1; | ||
1055 | |||
1056 | /* If none of the above criteria match, then don't store the key | ||
1057 | * persistently */ | ||
1058 | return 0; | ||
1059 | } | ||
1060 | |||
1061 | int hci_add_link_key(struct hci_dev *hdev, struct hci_conn *conn, int new_key, | ||
1062 | bdaddr_t *bdaddr, u8 *val, u8 type, u8 pin_len) | ||
1027 | { | 1063 | { |
1028 | struct link_key *key, *old_key; | 1064 | struct link_key *key, *old_key; |
1029 | u8 old_key_type; | 1065 | u8 old_key_type; |
@@ -1042,6 +1078,20 @@ int hci_add_link_key(struct hci_dev *hdev, int new_key, bdaddr_t *bdaddr, | |||
1042 | 1078 | ||
1043 | BT_DBG("%s key for %s type %u", hdev->name, batostr(bdaddr), type); | 1079 | BT_DBG("%s key for %s type %u", hdev->name, batostr(bdaddr), type); |
1044 | 1080 | ||
1081 | /* Some buggy controller combinations generate a changed | ||
1082 | * combination key for legacy pairing even when there's no | ||
1083 | * previous key */ | ||
1084 | if (type == HCI_LK_CHANGED_COMBINATION && | ||
1085 | (!conn || conn->remote_auth == 0xff) && | ||
1086 | old_key_type == 0xff) | ||
1087 | type = HCI_LK_COMBINATION; | ||
1088 | |||
1089 | if (new_key && !hci_persistent_key(hdev, conn, type, old_key_type)) { | ||
1090 | list_del(&key->list); | ||
1091 | kfree(key); | ||
1092 | return 0; | ||
1093 | } | ||
1094 | |||
1045 | bacpy(&key->bdaddr, bdaddr); | 1095 | bacpy(&key->bdaddr, bdaddr); |
1046 | memcpy(key->val, val, 16); | 1096 | memcpy(key->val, val, 16); |
1047 | key->type = type; | 1097 | key->type = type; |
diff --git a/net/bluetooth/hci_event.c b/net/bluetooth/hci_event.c index ebbaa6c8d015..8a63d3a463f7 100644 --- a/net/bluetooth/hci_event.c +++ b/net/bluetooth/hci_event.c | |||
@@ -2136,7 +2136,7 @@ static inline void hci_link_key_notify_evt(struct hci_dev *hdev, struct sk_buff | |||
2136 | } | 2136 | } |
2137 | 2137 | ||
2138 | if (test_bit(HCI_LINK_KEYS, &hdev->flags)) | 2138 | if (test_bit(HCI_LINK_KEYS, &hdev->flags)) |
2139 | hci_add_link_key(hdev, 1, &ev->bdaddr, ev->link_key, | 2139 | hci_add_link_key(hdev, conn, 1, &ev->bdaddr, ev->link_key, |
2140 | ev->key_type, pin_len); | 2140 | ev->key_type, pin_len); |
2141 | 2141 | ||
2142 | hci_dev_unlock(hdev); | 2142 | hci_dev_unlock(hdev); |
diff --git a/net/bluetooth/mgmt.c b/net/bluetooth/mgmt.c index a1b0ec4e5178..e1384fc6016c 100644 --- a/net/bluetooth/mgmt.c +++ b/net/bluetooth/mgmt.c | |||
@@ -945,7 +945,7 @@ static int load_keys(struct sock *sk, u16 index, unsigned char *data, u16 len) | |||
945 | for (i = 0; i < key_count; i++) { | 945 | for (i = 0; i < key_count; i++) { |
946 | struct mgmt_key_info *key = &cp->keys[i]; | 946 | struct mgmt_key_info *key = &cp->keys[i]; |
947 | 947 | ||
948 | hci_add_link_key(hdev, 0, &key->bdaddr, key->val, key->type, | 948 | hci_add_link_key(hdev, NULL, 0, &key->bdaddr, key->val, key->type, |
949 | key->pin_len); | 949 | key->pin_len); |
950 | } | 950 | } |
951 | 951 | ||